| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" | 5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" |
| 6 | 6 |
| 7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/signin/chrome_signin_client_factory.h" | 13 #include "chrome/browser/signin/chrome_signin_client_factory.h" |
| 14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | 14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| 15 #include "chrome/browser/signin/signin_manager_factory.h" | 15 #include "chrome/browser/signin/signin_manager_factory.h" |
| 16 #include "components/signin/core/browser/profile_oauth2_token_service.h" | 16 #include "components/signin/core/browser/profile_oauth2_token_service.h" |
| 17 #include "components/signin/core/browser/signin_manager.h" | 17 #include "components/signin/core/browser/signin_manager.h" |
| 18 #include "google_apis/gaia/gaia_constants.h" | 18 #include "google_apis/gaia/gaia_constants.h" |
| 19 #include "google_apis/gaia/gaia_urls.h" | 19 #include "google_apis/gaia/gaia_urls.h" |
| 20 #include "net/base/escape.h" | 20 #include "net/base/escape.h" |
| 21 #include "net/ssl/channel_id_service.h" |
| 22 #include "net/url_request/url_request_context.h" |
| 23 #include "net/url_request/url_request_context_getter.h" |
| 21 | 24 |
| 22 namespace extensions { | 25 namespace extensions { |
| 23 | 26 |
| 24 GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate, | 27 GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate, |
| 25 Profile* profile, | 28 Profile* profile, |
| 26 const ExtensionTokenKey* token_key, | 29 const ExtensionTokenKey* token_key, |
| 27 const std::string& oauth2_client_id, | 30 const std::string& oauth2_client_id, |
| 28 const std::string& locale) | 31 const std::string& locale) |
| 29 : delegate_(delegate), | 32 : delegate_(delegate), |
| 30 profile_(profile), | 33 profile_(profile), |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 } | 87 } |
| 85 | 88 |
| 86 GaiaWebAuthFlow::~GaiaWebAuthFlow() { | 89 GaiaWebAuthFlow::~GaiaWebAuthFlow() { |
| 87 TRACE_EVENT_ASYNC_END0("identity", "GaiaWebAuthFlow", this); | 90 TRACE_EVENT_ASYNC_END0("identity", "GaiaWebAuthFlow", this); |
| 88 | 91 |
| 89 if (web_flow_) | 92 if (web_flow_) |
| 90 web_flow_.release()->DetachDelegateAndDelete(); | 93 web_flow_.release()->DetachDelegateAndDelete(); |
| 91 } | 94 } |
| 92 | 95 |
| 93 void GaiaWebAuthFlow::Start() { | 96 void GaiaWebAuthFlow::Start() { |
| 97 main_context_ = profile_->GetRequestContext(); |
| 98 content::BrowserThread::PostTask( |
| 99 content::BrowserThread::IO, |
| 100 FROM_HERE, |
| 101 base::Bind(&GaiaWebAuthFlow::StartOnIOThread, base::Unretained(this))); |
| 102 } |
| 103 |
| 104 void GaiaWebAuthFlow::StartOnIOThread() { |
| 105 net::URLRequestContext* base_context = main_context_->GetURLRequestContext(); |
| 106 // Create a temporary request context for the Uber Token Fetch that doesn't |
| 107 // have a Channel ID. This way, the Uber Token will not be channel bound and |
| 108 // will be useable for the MergeSession call that will take place in the app's |
| 109 // request context. |
| 110 ProfileIOData::AppRequestContext* context = |
| 111 new ProfileIOData::AppRequestContext; |
| 112 ubertoken_request_context_.reset(context); |
| 113 |
| 114 context->CopyFrom(base_context); |
| 115 context->SetChannelIDService(nullptr); |
| 116 |
| 117 // Merely setting the Channel ID Service isn't enough, we also have to build a |
| 118 // new HttpNetworkSession. |
| 119 std::unique_ptr<net::HttpCache::BackendFactory> app_backend = |
| 120 net::HttpCache::DefaultBackend::InMemory(0); |
| 121 net::HttpNetworkSession::Params network_params = |
| 122 *base_context->GetNetworkSessionParams(); |
| 123 network_params.channel_id_service = nullptr; |
| 124 std::unique_ptr<net::HttpNetworkSession> http_network_session( |
| 125 new net::HttpNetworkSession(network_params)); |
| 126 std::unique_ptr<net::HttpCache> app_http_cache( |
| 127 new net::HttpCache(http_network_session.get(), |
| 128 std::move(app_backend), true)); |
| 129 |
| 130 context->SetHttpNetworkSession( |
| 131 std::move(http_network_session)); |
| 132 context->SetHttpTransactionFactory(std::move(app_http_cache)); |
| 133 |
| 134 content::BrowserThread::PostTask( |
| 135 content::BrowserThread::UI, |
| 136 FROM_HERE, |
| 137 base::Bind(&GaiaWebAuthFlow::StartUberTokenFetch, |
| 138 base::Unretained(this))); |
| 139 } |
| 140 |
| 141 void GaiaWebAuthFlow::StartUberTokenFetch() { |
| 94 ProfileOAuth2TokenService* token_service = | 142 ProfileOAuth2TokenService* token_service = |
| 95 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); | 143 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); |
| 144 context_getter_ = new net::TrivialURLRequestContextGetter( |
| 145 ubertoken_request_context_.get(), |
| 146 main_context_->GetNetworkTaskRunner()); |
| 96 ubertoken_fetcher_.reset(new UbertokenFetcher(token_service, | 147 ubertoken_fetcher_.reset(new UbertokenFetcher(token_service, |
| 97 this, | 148 this, |
| 98 GaiaConstants::kChromeSource, | 149 GaiaConstants::kChromeSource, |
| 99 profile_->GetRequestContext())); | 150 context_getter_.get())); |
| 100 ubertoken_fetcher_->StartFetchingToken(account_id_); | 151 ubertoken_fetcher_->StartFetchingToken(account_id_); |
| 101 } | 152 } |
| 102 | 153 |
| 154 void GaiaWebAuthFlow::CleanupRequestContextOnIOThread() { |
| 155 ubertoken_request_context_.reset(); |
| 156 } |
| 157 |
| 103 void GaiaWebAuthFlow::OnUbertokenSuccess(const std::string& token) { | 158 void GaiaWebAuthFlow::OnUbertokenSuccess(const std::string& token) { |
| 104 TRACE_EVENT_ASYNC_STEP_PAST0( | 159 TRACE_EVENT_ASYNC_STEP_PAST0( |
| 105 "identity", "GaiaWebAuthFlow", this, "OnUbertokenSuccess"); | 160 "identity", "GaiaWebAuthFlow", this, "OnUbertokenSuccess"); |
| 106 | 161 |
| 162 // The temporary request context isn't required after the Uber Token request |
| 163 // completes. It needs to be deleted on the IO Thread, so do that here. |
| 164 content::BrowserThread::PostTask( |
| 165 content::BrowserThread::IO, |
| 166 FROM_HERE, |
| 167 base::Bind(&GaiaWebAuthFlow::CleanupRequestContextOnIOThread, |
| 168 base::Unretained(this))); |
| 169 |
| 107 const char kMergeSessionQueryFormat[] = "?uberauth=%s&" | 170 const char kMergeSessionQueryFormat[] = "?uberauth=%s&" |
| 108 "continue=%s&" | 171 "continue=%s&" |
| 109 "source=appsv2"; | 172 "source=appsv2"; |
| 110 | 173 |
| 111 std::string merge_query = base::StringPrintf( | 174 std::string merge_query = base::StringPrintf( |
| 112 kMergeSessionQueryFormat, | 175 kMergeSessionQueryFormat, |
| 113 net::EscapeUrlEncodedData(token, true).c_str(), | 176 net::EscapeUrlEncodedData(token, true).c_str(), |
| 114 net::EscapeUrlEncodedData(auth_url_.spec(), true).c_str()); | 177 net::EscapeUrlEncodedData(auth_url_.spec(), true).c_str()); |
| 115 GURL merge_url( | 178 GURL merge_url( |
| 116 GaiaUrls::GetInstance()->merge_session_url().Resolve(merge_query)); | 179 GaiaUrls::GetInstance()->merge_session_url().Resolve(merge_query)); |
| 117 | 180 |
| 118 web_flow_ = CreateWebAuthFlow(merge_url); | 181 web_flow_ = CreateWebAuthFlow(merge_url); |
| 119 web_flow_->Start(); | 182 web_flow_->Start(); |
| 120 } | 183 } |
| 121 | 184 |
| 122 void GaiaWebAuthFlow::OnUbertokenFailure(const GoogleServiceAuthError& error) { | 185 void GaiaWebAuthFlow::OnUbertokenFailure(const GoogleServiceAuthError& error) { |
| 123 TRACE_EVENT_ASYNC_STEP_PAST1("identity", | 186 TRACE_EVENT_ASYNC_STEP_PAST1("identity", |
| 124 "GaiaWebAuthFlow", | 187 "GaiaWebAuthFlow", |
| 125 this, | 188 this, |
| 126 "OnUbertokenSuccess", | 189 "OnUbertokenSuccess", |
| 127 "error", | 190 "error", |
| 128 error.ToString()); | 191 error.ToString()); |
| 129 | 192 |
| 193 // The temporary request context isn't required after the Uber Token request |
| 194 // completes. It needs to be deleted on the IO Thread, so do that here. |
| 195 content::BrowserThread::PostTask( |
| 196 content::BrowserThread::IO, |
| 197 FROM_HERE, |
| 198 base::Bind(&GaiaWebAuthFlow::CleanupRequestContextOnIOThread, |
| 199 base::Unretained(this))); |
| 200 |
| 130 DVLOG(1) << "OnUbertokenFailure: " << error.error_message(); | 201 DVLOG(1) << "OnUbertokenFailure: " << error.error_message(); |
| 131 delegate_->OnGaiaFlowFailure( | 202 delegate_->OnGaiaFlowFailure( |
| 132 GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string()); | 203 GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string()); |
| 133 } | 204 } |
| 134 | 205 |
| 135 void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { | 206 void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) { |
| 136 GaiaWebAuthFlow::Failure gaia_failure; | 207 GaiaWebAuthFlow::Failure gaia_failure; |
| 137 | 208 |
| 138 switch (failure) { | 209 switch (failure) { |
| 139 case WebAuthFlow::WINDOW_CLOSED: | 210 case WebAuthFlow::WINDOW_CLOSED: |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 OnAuthFlowURLChange(url); | 301 OnAuthFlowURLChange(url); |
| 231 } | 302 } |
| 232 } | 303 } |
| 233 | 304 |
| 234 std::unique_ptr<WebAuthFlow> GaiaWebAuthFlow::CreateWebAuthFlow(GURL url) { | 305 std::unique_ptr<WebAuthFlow> GaiaWebAuthFlow::CreateWebAuthFlow(GURL url) { |
| 235 return std::unique_ptr<WebAuthFlow>( | 306 return std::unique_ptr<WebAuthFlow>( |
| 236 new WebAuthFlow(this, profile_, url, WebAuthFlow::INTERACTIVE)); | 307 new WebAuthFlow(this, profile_, url, WebAuthFlow::INTERACTIVE)); |
| 237 } | 308 } |
| 238 | 309 |
| 239 } // namespace extensions | 310 } // namespace extensions |
| OLD | NEW |