Chromium Code Reviews| Index: google_apis/gaia/merge_session_helper.cc |
| diff --git a/google_apis/gaia/merge_session_helper.cc b/google_apis/gaia/merge_session_helper.cc |
| index cf2fa95730dd27bfc2f9335e1841969af0ae9259..bf1e9f7d548f20c922f7e324a4b226d0086bdba3 100644 |
| --- a/google_apis/gaia/merge_session_helper.cc |
| +++ b/google_apis/gaia/merge_session_helper.cc |
| @@ -4,19 +4,153 @@ |
| #include "google_apis/gaia/merge_session_helper.h" |
| +#include <vector> |
| + |
| +#include "base/json/json_reader.h" |
| +#include "base/stl_util.h" |
| +#include "base/strings/string_util.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "base/time/time.h" |
| +#include "base/values.h" |
| #include "google_apis/gaia/gaia_auth_fetcher.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "google_apis/gaia/oauth2_token_service.h" |
| +#include "net/base/load_flags.h" |
| +#include "net/http/http_status_code.h" |
| #include "net/url_request/url_fetcher.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| +MergeSessionHelper::ExternalCcResultFetcher::ExternalCcResultFetcher( |
| + MergeSessionHelper* helper) : helper_(helper) { |
| + DCHECK(helper_); |
| +} |
| + |
| +MergeSessionHelper::ExternalCcResultFetcher::~ExternalCcResultFetcher() { |
| + CleanupTransientState(); |
| +} |
| + |
| +std::string MergeSessionHelper::ExternalCcResultFetcher::GetExternalCcResult() { |
| + std::vector<std::string> results; |
| + for (ResultMap::const_iterator it = results_.begin(); it != results_.end(); |
| + ++it) { |
| + results.push_back(it->first + ":" + it->second); |
| + } |
| + return JoinString(results, ","); |
| +} |
| + |
| +void MergeSessionHelper::ExternalCcResultFetcher::Start() { |
| + CleanupTransientState(); |
| + results_.clear(); |
| + gaia_auth_fetcher_.reset( |
| + new GaiaAuthFetcher(this, GaiaConstants::kChromeSource, |
| + helper_->request_context())); |
| + gaia_auth_fetcher_->StartGetCheckConnectionInfo(); |
| +} |
| + |
| +bool MergeSessionHelper::ExternalCcResultFetcher::IsRunning() { |
| + return gaia_auth_fetcher_ || fetchers_.size() > 0u; |
| +} |
| + |
| +void |
| +MergeSessionHelper::ExternalCcResultFetcher::OnGetCheckConnectionInfoSuccess( |
| + const std::string& data) { |
| + base::Value* value = base::JSONReader::Read(data); |
| + const base::ListValue* list; |
| + if (!value || !value->GetAsList(&list)) |
| + return; |
| + |
| + // Start a fetcher for each connection URL that needs to be checked. |
| + for (size_t i = 0; i < list->GetSize(); ++i) { |
| + const base::DictionaryValue* dict; |
| + if (list->GetDictionary(i, &dict)) { |
| + std::string token; |
| + std::string url; |
| + if (dict->GetString("carryBackToken", &token) && |
| + dict->GetString("url", &url)) { |
| + results_[token] = "null"; |
| + net::URLFetcher* fetcher = CreateFetcher(GURL(url)); |
| + fetchers_[fetcher->GetOriginalURL()] = std::make_pair(token, fetcher); |
| + fetcher->Start(); |
| + } |
| + } |
| + } |
| + |
| + // Some fetches may timeout. Start a timer to decide when the result fetcher |
| + // has waited long enough. |
| + // TODO(rogerta): I have no idea how long to wait before timing out. |
| + // Gaia folks say this should take no more than 2 second even in mobile. |
| + // This will need to be tweaked. |
| + timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5), |
| + this, &MergeSessionHelper::ExternalCcResultFetcher::Timeout); |
| +} |
| + |
| +net::URLFetcher* MergeSessionHelper::ExternalCcResultFetcher::CreateFetcher( |
| + const GURL& url) { |
| + net::URLFetcher* fetcher = net::URLFetcher::Create( |
| + 0, |
| + url, |
| + net::URLFetcher::GET, |
| + this); |
| + fetcher->SetRequestContext(helper_->request_context()); |
| + fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| + net::LOAD_DO_NOT_SAVE_COOKIES); |
| + |
| + // Fetchers are sometimes cancelled because a network change was detected, |
| + // especially at startup and after sign-in on ChromeOS. |
| + fetcher->SetAutomaticallyRetryOnNetworkChanges(1); |
| + return fetcher; |
| +} |
| + |
| +void MergeSessionHelper::ExternalCcResultFetcher::OnURLFetchComplete( |
| + const net::URLFetcher* source) { |
| + const GURL& url = source->GetOriginalURL(); |
| + const net::URLRequestStatus& status = source->GetStatus(); |
| + int response_code = source->GetResponseCode(); |
| + if (status.is_success() && response_code == net::HTTP_OK && |
| + fetchers_.count(url) > 0) { |
| + std::string data; |
| + source->GetResponseAsString(&data); |
| + // Only up to the first 16 characters of the response are important. |
|
Alexei Svitkine (slow)
2014/08/08 21:16:48
Why? The comment should provide more insight than
Roger Tawa OOO till Jul 10th
2014/08/09 15:58:28
Because the gaia protocol says only the first 16 c
Alexei Svitkine (slow)
2014/08/11 14:04:51
Okay, can you add that info to the comment? i.e. "
Roger Tawa OOO till Jul 10th
2014/08/11 20:20:54
Fixed in previous patchset.
|
| + // Truncate if needed. |
| + if (data.size() > 16) |
| + data.resize(16); |
| + results_[fetchers_[url].first] = data; |
| + |
| + // If we have received all the responses we expect, cancel the timer and |
| + // report the result. |
| + DCHECK_EQ(source, fetchers_[url].second); |
| + fetchers_.erase(url); |
| + delete source; |
|
Alexei Svitkine (slow)
2014/08/08 21:16:48
Why is |source| only deleted within the if?
What
Roger Tawa OOO till Jul 10th
2014/08/09 15:58:28
Because source == fetcher_[url].second (see DCHECK
Alexei Svitkine (slow)
2014/08/11 14:04:51
Got it. Thanks for the explanation. It might be go
Roger Tawa OOO till Jul 10th
2014/08/11 20:20:54
Done.
|
| + if (fetchers_.size() == 0) { |
|
Alexei Svitkine (slow)
2014/08/11 14:04:50
Nit: empty()
Roger Tawa OOO till Jul 10th
2014/08/11 20:20:54
Done.
|
| + timer_.Stop(); |
| + CleanupTransientState(); |
| + } |
| + } |
| +} |
| + |
| +void MergeSessionHelper::ExternalCcResultFetcher::Timeout() { |
| + CleanupTransientState(); |
| +} |
| + |
| +void MergeSessionHelper::ExternalCcResultFetcher::CleanupTransientState() { |
| + gaia_auth_fetcher_.reset(); |
| + |
| + for (URLToTokenAndFetcher::const_iterator it = fetchers_.begin(); |
| + it != fetchers_.end(); ++it) { |
| + delete it->second.second; |
| + } |
| + fetchers_.clear(); |
| +} |
| + |
|
Alexei Svitkine (slow)
2014/08/08 21:16:48
Nit: Remove extra line.
Roger Tawa OOO till Jul 10th
2014/08/09 15:58:28
Done.
|
| + |
| MergeSessionHelper::MergeSessionHelper( |
| OAuth2TokenService* token_service, |
| net::URLRequestContextGetter* request_context, |
| Observer* observer) |
| : token_service_(token_service), |
| - request_context_(request_context) { |
| + request_context_(request_context), |
| + result_fetcher_(this) { |
| if (observer) |
| AddObserver(observer); |
| } |
| @@ -111,6 +245,14 @@ void MergeSessionHelper::SignalComplete( |
| MergeSessionCompleted(account_id, error)); |
| } |
| +void MergeSessionHelper::StartFetchingExternalCcResult() { |
| + result_fetcher_.Start(); |
| +} |
| + |
| +bool MergeSessionHelper::StillFetchingExternalCcResult() { |
| + return result_fetcher_.IsRunning(); |
| +} |
| + |
| void MergeSessionHelper::StartLogOutUrlFetch() { |
| DCHECK(accounts_.front().empty()); |
| VLOG(1) << "MergeSessionHelper::StartLogOutUrlFetch"; |
| @@ -127,7 +269,11 @@ void MergeSessionHelper::OnUbertokenSuccess(const std::string& uber_token) { |
| gaia_auth_fetcher_.reset(new GaiaAuthFetcher(this, |
| GaiaConstants::kChromeSource, |
| request_context_)); |
| - gaia_auth_fetcher_->StartMergeSession(uber_token); |
| + |
| + // It's possible that not all external checks have completed. |
| + // GetExternalCcResult() returns results for those that have. |
| + gaia_auth_fetcher_->StartMergeSession(uber_token, |
| + result_fetcher_.GetExternalCcResult()); |
| } |
| void MergeSessionHelper::OnUbertokenFailure( |