diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 10:22:43 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:36:28 +0000 |
commit | 271a6c3487a14599023a9106329505597638d793 (patch) | |
tree | e040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/google_apis | |
parent | 7b2ffa587235a47d4094787d72f38102089f402a (diff) | |
download | qtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz |
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/google_apis')
81 files changed, 1483 insertions, 3770 deletions
diff --git a/chromium/google_apis/BUILD.gn b/chromium/google_apis/BUILD.gn index 3c605a4542d..9069f08949b 100644 --- a/chromium/google_apis/BUILD.gn +++ b/chromium/google_apis/BUILD.gn @@ -110,18 +110,15 @@ template("google_apis_tmpl") { "gaia/oauth2_access_token_fetcher_immediate_error.h", "gaia/oauth2_access_token_fetcher_impl.cc", "gaia/oauth2_access_token_fetcher_impl.h", + "gaia/oauth2_access_token_manager.cc", + "gaia/oauth2_access_token_manager.h", "gaia/oauth2_api_call_flow.cc", "gaia/oauth2_api_call_flow.h", "gaia/oauth2_id_token_decoder.cc", "gaia/oauth2_id_token_decoder.h", "gaia/oauth2_mint_token_flow.cc", "gaia/oauth2_mint_token_flow.h", - "gaia/oauth2_token_service.cc", - "gaia/oauth2_token_service.h", - "gaia/oauth2_token_service_delegate.cc", - "gaia/oauth2_token_service_delegate.h", - "gaia/oauth2_token_service_request.cc", - "gaia/oauth2_token_service_request.h", + "gaia/oauth2_token_service_observer.h", "gaia/oauth_multilogin_result.cc", "gaia/oauth_multilogin_result.h", "gaia/oauth_request_signer.cc", @@ -176,12 +173,10 @@ static_library("test_support") { sources = [ "gaia/fake_gaia.cc", "gaia/fake_gaia.h", - "gaia/fake_oauth2_token_service.cc", - "gaia/fake_oauth2_token_service.h", - "gaia/fake_oauth2_token_service_delegate.cc", - "gaia/fake_oauth2_token_service_delegate.h", - "gaia/oauth2_token_service_test_util.cc", - "gaia/oauth2_token_service_test_util.h", + "gaia/fake_oauth2_access_token_manager.cc", + "gaia/fake_oauth2_access_token_manager.h", + "gaia/oauth2_access_token_manager_test_util.cc", + "gaia/oauth2_access_token_manager_test_util.h", ] public_deps = [ @@ -214,12 +209,10 @@ test("google_apis_unittests") { "gaia/gaia_oauth_client_unittest.cc", "gaia/google_service_auth_error_unittest.cc", "gaia/oauth2_access_token_fetcher_impl_unittest.cc", + "gaia/oauth2_access_token_manager_unittest.cc", "gaia/oauth2_api_call_flow_unittest.cc", "gaia/oauth2_id_token_decoder_unittest.cc", "gaia/oauth2_mint_token_flow_unittest.cc", - "gaia/oauth2_token_service_delegate_unittest.cc", - "gaia/oauth2_token_service_request_unittest.cc", - "gaia/oauth2_token_service_unittest.cc", "gaia/oauth_multilogin_result_unittest.cc", "gaia/oauth_request_signer_unittest.cc", "google_api_keys_unittest.cc", diff --git a/chromium/google_apis/OWNERS b/chromium/google_apis/OWNERS index 18ac20e0d10..75d1a794053 100644 --- a/chromium/google_apis/OWNERS +++ b/chromium/google_apis/OWNERS @@ -2,3 +2,4 @@ rogerta@chromium.org file://components/signin/OWNERS per-file BUILD.gn=* +# COMPONENT: Services>SignIn diff --git a/chromium/google_apis/build/OWNERS b/chromium/google_apis/build/OWNERS new file mode 100644 index 00000000000..ab5f1ae7220 --- /dev/null +++ b/chromium/google_apis/build/OWNERS @@ -0,0 +1 @@ +# COMPONENT: Build diff --git a/chromium/google_apis/drive/BUILD.gn b/chromium/google_apis/drive/BUILD.gn index 0f87c310120..77d6bdb3289 100644 --- a/chromium/google_apis/drive/BUILD.gn +++ b/chromium/google_apis/drive/BUILD.gn @@ -40,10 +40,10 @@ source_set("drive") { deps = [ "//base", "//base/third_party/dynamic_annotations", + "//components/signin/public/identity_manager", "//crypto", "//google_apis:google_apis", "//net", - "//services/identity/public/cpp:cpp", "//services/network/public/cpp", ] } diff --git a/chromium/google_apis/drive/DEPS b/chromium/google_apis/drive/DEPS index 2214f5196e6..e704a4712b9 100644 --- a/chromium/google_apis/drive/DEPS +++ b/chromium/google_apis/drive/DEPS @@ -1,3 +1,3 @@ include_rules = [ - "+services/identity/public", + "+components/signin/public", ] diff --git a/chromium/google_apis/drive/auth_service.cc b/chromium/google_apis/drive/auth_service.cc index a91a47f6f8f..b2fbfdae461 100644 --- a/chromium/google_apis/drive/auth_service.cc +++ b/chromium/google_apis/drive/auth_service.cc @@ -13,10 +13,10 @@ #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/signin/public/identity_manager/access_token_fetcher.h" +#include "components/signin/public/identity_manager/access_token_info.h" #include "google_apis/drive/auth_service_observer.h" #include "google_apis/gaia/google_service_auth_error.h" -#include "services/identity/public/cpp/access_token_fetcher.h" -#include "services/identity/public/cpp/access_token_info.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace google_apis { @@ -39,7 +39,7 @@ void RecordAuthResultHistogram(int value) { // OAuth2 authorization token retrieval request. class AuthRequest { public: - AuthRequest(identity::IdentityManager* identity_manager, + AuthRequest(signin::IdentityManager* identity_manager, const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const AuthStatusCallback& callback, @@ -48,17 +48,17 @@ class AuthRequest { private: void OnAccessTokenFetchComplete(GoogleServiceAuthError error, - identity::AccessTokenInfo token_info); + signin::AccessTokenInfo token_info); AuthStatusCallback callback_; - std::unique_ptr<identity::AccessTokenFetcher> access_token_fetcher_; + std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_; base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(AuthRequest); }; AuthRequest::AuthRequest( - identity::IdentityManager* identity_manager, + signin::IdentityManager* identity_manager, const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const AuthStatusCallback& callback, @@ -72,14 +72,14 @@ AuthRequest::AuthRequest( identity::ScopeSet(scopes.begin(), scopes.end()), base::BindOnce(&AuthRequest::OnAccessTokenFetchComplete, base::Unretained(this)), - identity::AccessTokenFetcher::Mode::kImmediate); + signin::AccessTokenFetcher::Mode::kImmediate); } AuthRequest::~AuthRequest() {} void AuthRequest::OnAccessTokenFetchComplete( GoogleServiceAuthError error, - identity::AccessTokenInfo token_info) { + signin::AccessTokenInfo token_info) { DCHECK(thread_checker_.CalledOnValidThread()); if (error.state() == GoogleServiceAuthError::NONE) { @@ -111,7 +111,7 @@ void AuthRequest::OnAccessTokenFetchComplete( } // namespace AuthService::AuthService( - identity::IdentityManager* identity_manager, + signin::IdentityManager* identity_manager, const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::vector<std::string>& scopes) diff --git a/chromium/google_apis/drive/auth_service.h b/chromium/google_apis/drive/auth_service.h index 4cd0a505df9..1a2fc936422 100644 --- a/chromium/google_apis/drive/auth_service.h +++ b/chromium/google_apis/drive/auth_service.h @@ -13,8 +13,8 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" +#include "components/signin/public/identity_manager/identity_manager.h" #include "google_apis/drive/auth_service_interface.h" -#include "services/identity/public/cpp/identity_manager.h" namespace network { class SharedURLLoaderFactory; @@ -29,13 +29,13 @@ class AuthServiceObserver; // (IdentityManager) and provides OAuth2 token refresh infrastructure. // All public functions must be called on UI thread. class AuthService : public AuthServiceInterface, - public identity::IdentityManager::Observer { + public signin::IdentityManager::Observer { public: // |url_loader_factory| is used to perform authentication with // SimpleURLLoader. // // |scopes| specifies OAuth2 scopes. - AuthService(identity::IdentityManager* identity_manager, + AuthService(signin::IdentityManager* identity_manager, const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::vector<std::string>& scopes); @@ -67,7 +67,7 @@ class AuthService : public AuthServiceInterface, DriveApiErrorCode error, const std::string& access_token); - identity::IdentityManager* identity_manager_; + signin::IdentityManager* identity_manager_; CoreAccountId account_id_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; bool has_refresh_token_; diff --git a/chromium/google_apis/drive/drive_api_requests.cc b/chromium/google_apis/drive/drive_api_requests.cc index 76ae9712f75..d7aa3818c23 100644 --- a/chromium/google_apis/drive/drive_api_requests.cc +++ b/chromium/google_apis/drive/drive_api_requests.cc @@ -53,7 +53,6 @@ const char kHttpBr[] = "\r\n"; const char kMultipartMixedMimeTypePrefix[] = "multipart/mixed; boundary="; // UMA names. -const char kUMADriveBatchUploadResponseCode[] = "Drive.BatchUploadResponseCode"; const char kUMADriveTotalFileCountInBatchUpload[] = "Drive.TotalFileCountInBatchUpload"; const char kUMADriveTotalFileSizeInBatchUpload[] = @@ -1325,19 +1324,6 @@ void BatchUploadRequest::ProcessURLFetchResults( const network::ResourceResponseHead* response_head, base::FilePath response_file, std::string response_body) { - // Return the detailed raw HTTP code if the error code is abstracted - // DRIVE_OTHER_ERROR. If HTTP connection is failed and the status code is -1, - // return network status error. - int histogram_error = 0; - if (GetErrorCode() != DRIVE_OTHER_ERROR) { - histogram_error = GetErrorCode(); - } else if (response_head && response_head->headers->response_code() != -1) { - histogram_error = response_head->headers->response_code(); - } else { - histogram_error = NetError(); - } - base::UmaHistogramSparse(kUMADriveBatchUploadResponseCode, histogram_error); - if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) { RunCallbackOnPrematureFailure(GetErrorCode()); sender_->RequestFinished(this); diff --git a/chromium/google_apis/gaia/OWNERS b/chromium/google_apis/gaia/OWNERS index c14b79e1e6f..753faeeff6d 100644 --- a/chromium/google_apis/gaia/OWNERS +++ b/chromium/google_apis/gaia/OWNERS @@ -2,4 +2,8 @@ droger@chromium.org msarda@chromium.org rogerta@chromium.org +# Solely for the duration of the refactoring of OAuth2TokenService +# (https://crbug.com/950159). Do not choose for any other reviews. +blundell@chromium.org + # COMPONENT: Services>SignIn diff --git a/chromium/google_apis/gaia/core_account_id.cc b/chromium/google_apis/gaia/core_account_id.cc index d8080824d5d..0fc8c416d23 100644 --- a/chromium/google_apis/gaia/core_account_id.cc +++ b/chromium/google_apis/gaia/core_account_id.cc @@ -6,8 +6,16 @@ CoreAccountId::CoreAccountId() = default; +CoreAccountId::CoreAccountId(const CoreAccountId&) = default; + +CoreAccountId::CoreAccountId(CoreAccountId&&) noexcept = default; + CoreAccountId::~CoreAccountId() = default; +CoreAccountId& CoreAccountId::operator=(const CoreAccountId&) = default; + +CoreAccountId& CoreAccountId::operator=(CoreAccountId&&) noexcept = default; + CoreAccountId::CoreAccountId(const char* id) : id(id) {} CoreAccountId::CoreAccountId(std::string&& id) : id(std::move(id)) {} @@ -37,3 +45,11 @@ bool operator!=(const CoreAccountId& lhs, const CoreAccountId& rhs) { std::ostream& operator<<(std::ostream& out, const CoreAccountId& a) { return out << a.id; } + +std::vector<std::string> ToStringList( + const std::vector<CoreAccountId>& account_ids) { + std::vector<std::string> account_ids_string; + for (const auto& account_id : account_ids) + account_ids_string.push_back(account_id.id); + return account_ids_string; +}
\ No newline at end of file diff --git a/chromium/google_apis/gaia/core_account_id.h b/chromium/google_apis/gaia/core_account_id.h index 5ea602aba2c..05587543378 100644 --- a/chromium/google_apis/gaia/core_account_id.h +++ b/chromium/google_apis/gaia/core_account_id.h @@ -7,6 +7,7 @@ #include <ostream> #include <string> +#include <vector> // Represent the id of an account for interaction with GAIA. It is // currently implicitly convertible to and from std::string to allow @@ -14,8 +15,13 @@ // for design and tracking). struct CoreAccountId { CoreAccountId(); + CoreAccountId(const CoreAccountId&); + CoreAccountId(CoreAccountId&&) noexcept; ~CoreAccountId(); + CoreAccountId& operator=(const CoreAccountId&); + CoreAccountId& operator=(CoreAccountId&&) noexcept; + // Those implicit constructor and conversion operator allow to // progressively migrate the code to use this struct. Removing // them is tracked by https://crbug.com/959161 @@ -40,4 +46,18 @@ bool operator!=(const CoreAccountId& lhs, const CoreAccountId& rhs); std::ostream& operator<<(std::ostream& out, const CoreAccountId& a); +// Returns the values of the account ids in a vector. Useful especially for +// logs. +std::vector<std::string> ToStringList( + const std::vector<CoreAccountId>& account_ids); + +namespace std { +template <> +struct hash<CoreAccountId> { + size_t operator()(const CoreAccountId& account_id) const { + return std::hash<std::string>()(account_id.id); + } +}; +} // namespace std + #endif // GOOGLE_APIS_GAIA_CORE_ACCOUNT_ID_H_ diff --git a/chromium/google_apis/gaia/fake_oauth2_access_token_manager.cc b/chromium/google_apis/gaia/fake_oauth2_access_token_manager.cc new file mode 100644 index 00000000000..4e48c808d5b --- /dev/null +++ b/chromium/google_apis/gaia/fake_oauth2_access_token_manager.cc @@ -0,0 +1,201 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "google_apis/gaia/fake_oauth2_access_token_manager.h" + +#include <memory> + +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" + +FakeOAuth2AccessTokenManager::PendingRequest::PendingRequest() {} + +FakeOAuth2AccessTokenManager::PendingRequest::PendingRequest( + const PendingRequest& other) = default; + +FakeOAuth2AccessTokenManager::PendingRequest::~PendingRequest() {} + +FakeOAuth2AccessTokenManager::FakeOAuth2AccessTokenManager( + OAuth2AccessTokenManager::Delegate* delegate) + : OAuth2AccessTokenManager(delegate), + auto_post_fetch_response_on_message_loop_(false), + weak_ptr_factory_(this) {} + +FakeOAuth2AccessTokenManager::~FakeOAuth2AccessTokenManager() {} + +void FakeOAuth2AccessTokenManager::IssueAllTokensForAccount( + const std::string& account_id, + const std::string& access_token, + const base::Time& expiration) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests(account_id, true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError::AuthErrorNone(), + OAuth2AccessTokenConsumer::TokenResponse( + access_token, expiration, std::string() /* id_token */)); +} + +void FakeOAuth2AccessTokenManager::IssueAllTokensForAccount( + const std::string& account_id, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests(account_id, true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError::AuthErrorNone(), token_response); +} + +void FakeOAuth2AccessTokenManager::IssueErrorForAllPendingRequestsForAccount( + const std::string& account_id, + const GoogleServiceAuthError& error) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests(account_id, true, FakeOAuth2AccessTokenManager::ScopeSet(), + error, OAuth2AccessTokenConsumer::TokenResponse()); +} + +void FakeOAuth2AccessTokenManager::IssueTokenForScope( + const FakeOAuth2AccessTokenManager::ScopeSet& scope, + const std::string& access_token, + const base::Time& expiration) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", false, scope, GoogleServiceAuthError::AuthErrorNone(), + OAuth2AccessTokenConsumer::TokenResponse( + access_token, expiration, std::string() /* id_token */)); +} + +void FakeOAuth2AccessTokenManager::IssueTokenForScope( + const FakeOAuth2AccessTokenManager::ScopeSet& scope, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", false, scope, GoogleServiceAuthError::AuthErrorNone(), + token_response); +} + +void FakeOAuth2AccessTokenManager::IssueErrorForScope( + const FakeOAuth2AccessTokenManager::ScopeSet& scope, + const GoogleServiceAuthError& error) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", false, scope, error, + OAuth2AccessTokenConsumer::TokenResponse()); +} + +void FakeOAuth2AccessTokenManager::IssueErrorForAllPendingRequests( + const GoogleServiceAuthError& error) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", true, FakeOAuth2AccessTokenManager::ScopeSet(), error, + OAuth2AccessTokenConsumer::TokenResponse()); +} + +void FakeOAuth2AccessTokenManager::IssueTokenForAllPendingRequests( + const std::string& access_token, + const base::Time& expiration) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError::AuthErrorNone(), + OAuth2AccessTokenConsumer::TokenResponse( + access_token, expiration, std::string() /* id_token */)); +} + +void FakeOAuth2AccessTokenManager::IssueTokenForAllPendingRequests( + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + DCHECK(!auto_post_fetch_response_on_message_loop_); + CompleteRequests("", true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError::AuthErrorNone(), token_response); +} + +void FakeOAuth2AccessTokenManager::CompleteRequests( + const std::string& account_id, + bool all_scopes, + const FakeOAuth2AccessTokenManager::ScopeSet& scope, + const GoogleServiceAuthError& error, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + std::vector<FakeOAuth2AccessTokenManager::PendingRequest> requests = + GetPendingRequests(); + + // Walk the requests and notify the callbacks. + for (auto it = requests.begin(); it != requests.end(); ++it) { + // Consumers can drop requests in response to callbacks on other requests + // (e.g., OAuthMultiloginFetcher clears all of its requests when it gets an + // error on any of them). + if (!it->request) + continue; + + bool scope_matches = all_scopes || it->scopes == scope; + bool account_matches = account_id.empty() || account_id == it->account_id; + if (account_matches && scope_matches) { + for (auto& diagnostic_observer : GetDiagnosticsObserversForTesting()) { + diagnostic_observer.OnFetchAccessTokenComplete( + account_id, it->request->GetConsumerId(), scope, error, + base::Time()); + } + + it->request->InformConsumer( + error, OAuth2AccessTokenConsumer::TokenResponse( + token_response.access_token, + token_response.expiration_time, token_response.id_token)); + } + } +} + +std::vector<FakeOAuth2AccessTokenManager::PendingRequest> +FakeOAuth2AccessTokenManager::GetPendingRequests() { + std::vector<PendingRequest> valid_requests; + for (auto it = pending_requests_.begin(); it != pending_requests_.end(); + ++it) { + if (it->request) + valid_requests.push_back(*it); + } + return valid_requests; +} + +void FakeOAuth2AccessTokenManager::CancelAllRequests() { + CompleteRequests( + "", true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), + OAuth2AccessTokenConsumer::TokenResponse()); +} + +void FakeOAuth2AccessTokenManager::CancelRequestsForAccount( + const CoreAccountId& account_id) { + CompleteRequests( + account_id, true, FakeOAuth2AccessTokenManager::ScopeSet(), + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED), + OAuth2AccessTokenConsumer::TokenResponse()); +} + +void FakeOAuth2AccessTokenManager::FetchOAuth2Token( + FakeOAuth2AccessTokenManager::RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const std::string& client_id, + const std::string& client_secret, + const FakeOAuth2AccessTokenManager::ScopeSet& scopes) { + PendingRequest pending_request; + pending_request.account_id = account_id; + pending_request.client_id = client_id; + pending_request.client_secret = client_secret; + pending_request.url_loader_factory = url_loader_factory; + pending_request.scopes = scopes; + pending_request.request = request->AsWeakPtr(); + pending_requests_.push_back(pending_request); + + if (auto_post_fetch_response_on_message_loop_) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FakeOAuth2AccessTokenManager::CompleteRequests, + weak_ptr_factory_.GetWeakPtr(), account_id, + /*all_scoped=*/true, scopes, + GoogleServiceAuthError::AuthErrorNone(), + OAuth2AccessTokenConsumer::TokenResponse( + "access_token", base::Time::Max(), std::string()))); + } +} + +void FakeOAuth2AccessTokenManager::InvalidateAccessTokenImpl( + const CoreAccountId& account_id, + const std::string& client_id, + const FakeOAuth2AccessTokenManager::ScopeSet& scopes, + const std::string& access_token) { + // Do nothing, as we don't have a cache from which to remove the token. +} diff --git a/chromium/google_apis/gaia/fake_oauth2_access_token_manager.h b/chromium/google_apis/gaia/fake_oauth2_access_token_manager.h new file mode 100644 index 00000000000..d9efa6be2fe --- /dev/null +++ b/chromium/google_apis/gaia/fake_oauth2_access_token_manager.h @@ -0,0 +1,123 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GOOGLE_APIS_GAIA_FAKE_OAUTH2_ACCESS_TOKEN_MANAGER_H_ +#define GOOGLE_APIS_GAIA_FAKE_OAUTH2_ACCESS_TOKEN_MANAGER_H_ + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "google_apis/gaia/oauth2_access_token_manager.h" + +namespace network { +class SharedURLLoaderFactory; +} + +// Helper class to simplify writing unittests that depend on an instance of +// OAuth2AccessTokenManager. +class FakeOAuth2AccessTokenManager : public OAuth2AccessTokenManager { + public: + struct PendingRequest { + PendingRequest(); + PendingRequest(const PendingRequest& other); + ~PendingRequest(); + + std::string account_id; + std::string client_id; + std::string client_secret; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory; + OAuth2AccessTokenManager::ScopeSet scopes; + base::WeakPtr<OAuth2AccessTokenManager::RequestImpl> request; + }; + + explicit FakeOAuth2AccessTokenManager( + OAuth2AccessTokenManager::Delegate* delegate); + ~FakeOAuth2AccessTokenManager() override; + + // Gets a list of active requests (can be used by tests to validate that the + // correct request has been issued). + std::vector<PendingRequest> GetPendingRequests(); + + // Helper routines to issue tokens for pending requests. + void IssueAllTokensForAccount(const std::string& account_id, + const std::string& access_token, + const base::Time& expiration); + + // Helper routines to issue token for pending requests based on TokenResponse. + void IssueAllTokensForAccount( + const std::string& account_id, + const OAuth2AccessTokenConsumer::TokenResponse& token_response); + + void IssueErrorForAllPendingRequestsForAccount( + const std::string& account_id, + const GoogleServiceAuthError& error); + + void IssueTokenForScope(const OAuth2AccessTokenManager::ScopeSet& scopes, + const std::string& access_token, + const base::Time& expiration); + + void IssueTokenForScope( + const OAuth2AccessTokenManager::ScopeSet& scopes, + const OAuth2AccessTokenConsumer::TokenResponse& token_response); + + void IssueErrorForScope(const OAuth2AccessTokenManager::ScopeSet& scopes, + const GoogleServiceAuthError& error); + + void IssueTokenForAllPendingRequests(const std::string& access_token, + const base::Time& expiration); + + void IssueTokenForAllPendingRequests( + const OAuth2AccessTokenConsumer::TokenResponse& token_response); + + void IssueErrorForAllPendingRequests(const GoogleServiceAuthError& error); + + void set_auto_post_fetch_response_on_message_loop(bool auto_post_response) { + auto_post_fetch_response_on_message_loop_ = auto_post_response; + } + + // OAuth2AccessTokenManager overrides. + void CancelAllRequests() override; + + void CancelRequestsForAccount(const CoreAccountId& account_id) override; + + void FetchOAuth2Token( + OAuth2AccessTokenManager::RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const std::string& client_id, + const std::string& client_secret, + const OAuth2AccessTokenManager::ScopeSet& scopes) override; + + void InvalidateAccessTokenImpl( + const CoreAccountId& account_id, + const std::string& client_id, + const OAuth2AccessTokenManager::ScopeSet& scopes, + const std::string& access_token) override; + + private: + // Helper function to complete pending requests - if |all_scopes| is true, + // then all pending requests are completed, otherwise, only those requests + // matching |scopes| are completed. If |account_id| is empty, then pending + // requests for all accounts are completed, otherwise only requests for the + // given account. + void CompleteRequests( + const std::string& account_id, + bool all_scopes, + const OAuth2AccessTokenManager::ScopeSet& scopes, + const GoogleServiceAuthError& error, + const OAuth2AccessTokenConsumer::TokenResponse& token_response); + + std::vector<PendingRequest> pending_requests_; + + // If true, then this fake manager will post responses to + // |FetchOAuth2Token| on the current run loop. There is no need to call + // |IssueTokenForScope| in this case. + bool auto_post_fetch_response_on_message_loop_; + + base::WeakPtrFactory<FakeOAuth2AccessTokenManager> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeOAuth2AccessTokenManager); +}; + +#endif // GOOGLE_APIS_GAIA_FAKE_OAUTH2_ACCESS_TOKEN_MANAGER_H_ diff --git a/chromium/google_apis/gaia/fake_oauth2_token_service.cc b/chromium/google_apis/gaia/fake_oauth2_token_service.cc deleted file mode 100644 index 413a421777b..00000000000 --- a/chromium/google_apis/gaia/fake_oauth2_token_service.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "google_apis/gaia/fake_oauth2_token_service.h" - -#include <memory> - -FakeOAuth2TokenService::PendingRequest::PendingRequest() { -} - -FakeOAuth2TokenService::PendingRequest::PendingRequest( - const PendingRequest& other) = default; - -FakeOAuth2TokenService::PendingRequest::~PendingRequest() { -} - -FakeOAuth2TokenService::FakeOAuth2TokenService() - : OAuth2TokenService(std::make_unique<FakeOAuth2TokenServiceDelegate>()) {} - -FakeOAuth2TokenService::~FakeOAuth2TokenService() { -} - -void FakeOAuth2TokenService::FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes) { - PendingRequest pending_request; - pending_request.account_id = account_id; - pending_request.client_id = client_id; - pending_request.client_secret = client_secret; - pending_request.scopes = scopes; - pending_request.request = request->AsWeakPtr(); - pending_requests_.push_back(pending_request); -} - -void FakeOAuth2TokenService::InvalidateAccessTokenImpl( - const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) { -} - -void FakeOAuth2TokenService::AddAccount(const std::string& account_id) { - GetDelegate()->UpdateCredentials(account_id, "fake_refresh_token"); -} - -void FakeOAuth2TokenService::RemoveAccount(const std::string& account_id) { - GetDelegate()->RevokeCredentials(account_id); -} - -void FakeOAuth2TokenService::IssueAllTokensForAccount( - const std::string& account_id, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - // Walk the requests and notify the callbacks. - // Using a copy of pending requests to make sure a new token request triggered - // from the handling code does not invalidate the iterator. - std::vector<PendingRequest> pending_requests_copy = pending_requests_; - for (std::vector<PendingRequest>::iterator it = pending_requests_copy.begin(); - it != pending_requests_copy.end(); - ++it) { - if (it->request && (account_id == it->account_id)) { - it->request->InformConsumer(GoogleServiceAuthError::AuthErrorNone(), - token_response); - } - } -} - -void FakeOAuth2TokenService::IssueErrorForAllPendingRequestsForAccount( - const std::string& account_id, - const GoogleServiceAuthError& auth_error) { - // Walk the requests and notify the callbacks. - // Using a copy of pending requests to make sure retrying a request in - // response to the error does not invalidate the iterator. - std::vector<PendingRequest> pending_requests_copy = pending_requests_; - for (std::vector<PendingRequest>::iterator it = pending_requests_copy.begin(); - it != pending_requests_copy.end(); - ++it) { - if (it->request && (account_id == it->account_id)) { - it->request->InformConsumer(auth_error, - OAuth2AccessTokenConsumer::TokenResponse()); - } - } -} - -FakeOAuth2TokenServiceDelegate* -FakeOAuth2TokenService::GetFakeOAuth2TokenServiceDelegate() { - return static_cast<FakeOAuth2TokenServiceDelegate*>(GetDelegate()); -} diff --git a/chromium/google_apis/gaia/fake_oauth2_token_service.h b/chromium/google_apis/gaia/fake_oauth2_token_service.h deleted file mode 100644 index 032a7094b3c..00000000000 --- a/chromium/google_apis/gaia/fake_oauth2_token_service.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GOOGLE_APIS_GAIA_FAKE_OAUTH2_TOKEN_SERVICE_H_ -#define GOOGLE_APIS_GAIA_FAKE_OAUTH2_TOKEN_SERVICE_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "google_apis/gaia/fake_oauth2_token_service_delegate.h" -#include "google_apis/gaia/oauth2_token_service.h" - -namespace network { -class SharedURLLoaderFactory; -} - -// Do-nothing implementation of OAuth2TokenService. -class FakeOAuth2TokenService : public OAuth2TokenService { - public: - FakeOAuth2TokenService(); - ~FakeOAuth2TokenService() override; - - void AddAccount(const std::string& account_id); - void RemoveAccount(const std::string& account_id); - - // Helper routines to issue tokens for pending requests or complete them with - // error. - void IssueAllTokensForAccount( - const std::string& account_id, - const OAuth2AccessTokenConsumer::TokenResponse& token_response); - void IssueErrorForAllPendingRequestsForAccount( - const std::string& account_id, - const GoogleServiceAuthError& auth_error); - - void InvalidateTokenForMultilogin(const std::string& account_id, - const std::string& token) override {} - - FakeOAuth2TokenServiceDelegate* GetFakeOAuth2TokenServiceDelegate(); - - protected: - // OAuth2TokenService overrides. - void FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes) override; - - void InvalidateAccessTokenImpl(const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) override; - - private: - struct PendingRequest { - PendingRequest(); - PendingRequest(const PendingRequest& other); - ~PendingRequest(); - - std::string account_id; - std::string client_id; - std::string client_secret; - ScopeSet scopes; - base::WeakPtr<RequestImpl> request; - }; - - std::vector<PendingRequest> pending_requests_; - - DISALLOW_COPY_AND_ASSIGN(FakeOAuth2TokenService); -}; - -#endif // GOOGLE_APIS_GAIA_FAKE_OAUTH2_TOKEN_SERVICE_H_ diff --git a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc b/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc deleted file mode 100644 index efc528fc777..00000000000 --- a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "google_apis/gaia/fake_oauth2_token_service_delegate.h" -#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" - -namespace { -// Values used from |MutableProfileOAuth2TokenServiceDelegate|. -const net::BackoffEntry::Policy kBackoffPolicy = { - 0 /* int num_errors_to_ignore */, - - 1000 /* int initial_delay_ms */, - - 2.0 /* double multiply_factor */, - - 0.2 /* double jitter_factor */, - - 15 * 60 * 1000 /* int64_t maximum_backoff_ms */, - - -1 /* int64_t entry_lifetime_ms */, - - false /* bool always_use_initial_delay */, -}; -} // namespace - -FakeOAuth2TokenServiceDelegate::AccountInfo::AccountInfo( - const std::string& refresh_token) - : refresh_token(refresh_token), - error(GoogleServiceAuthError::NONE) {} - -FakeOAuth2TokenServiceDelegate::FakeOAuth2TokenServiceDelegate() - : shared_factory_( - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_)), - backoff_entry_(&kBackoffPolicy) {} - -FakeOAuth2TokenServiceDelegate::~FakeOAuth2TokenServiceDelegate() { -} - -OAuth2AccessTokenFetcher* -FakeOAuth2TokenServiceDelegate::CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer) { - auto it = refresh_tokens_.find(account_id); - DCHECK(it != refresh_tokens_.end()); - return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory, - it->second->refresh_token); -} - -bool FakeOAuth2TokenServiceDelegate::RefreshTokenIsAvailable( - const std::string& account_id) const { - return !GetRefreshToken(account_id).empty(); -} - -GoogleServiceAuthError FakeOAuth2TokenServiceDelegate::GetAuthError( - const std::string& account_id) const { - auto it = refresh_tokens_.find(account_id); - return (it == refresh_tokens_.end()) ? GoogleServiceAuthError::AuthErrorNone() - : it->second->error; -} - -std::string FakeOAuth2TokenServiceDelegate::GetRefreshToken( - const std::string& account_id) const { - auto it = refresh_tokens_.find(account_id); - if (it != refresh_tokens_.end()) - return it->second->refresh_token; - return std::string(); -} - -const net::BackoffEntry* FakeOAuth2TokenServiceDelegate::BackoffEntry() const { - return &backoff_entry_; -} - -std::vector<std::string> FakeOAuth2TokenServiceDelegate::GetAccounts() { - std::vector<std::string> account_ids; - for (const auto& token : refresh_tokens_) - account_ids.push_back(token.first); - return account_ids; -} - -void FakeOAuth2TokenServiceDelegate::RevokeAllCredentials() { - std::vector<std::string> account_ids = GetAccounts(); - for (const auto& account : account_ids) - RevokeCredentials(account); -} - -void FakeOAuth2TokenServiceDelegate::LoadCredentials( - const std::string& primary_account_id) { - set_load_credentials_state(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS); - FireRefreshTokensLoaded(); -} - -void FakeOAuth2TokenServiceDelegate::UpdateCredentials( - const std::string& account_id, - const std::string& refresh_token) { - IssueRefreshTokenForUser(account_id, refresh_token); -} - -void FakeOAuth2TokenServiceDelegate::IssueRefreshTokenForUser( - const std::string& account_id, - const std::string& token) { - ScopedBatchChange batch(this); - if (token.empty()) { - refresh_tokens_.erase(account_id); - FireRefreshTokenRevoked(account_id); - } else { - refresh_tokens_[account_id].reset(new AccountInfo(token)); - // If the token is a special "invalid" value, then that means the token was - // rejected by the client and is thus not valid. So set the appropriate - // error in that case. This logic is essentially duplicated from - // MutableProfileOAuth2TokenServiceDelegate. - if (token == kInvalidRefreshToken) { - refresh_tokens_[account_id]->error = - GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( - GoogleServiceAuthError::InvalidGaiaCredentialsReason:: - CREDENTIALS_REJECTED_BY_CLIENT); - } - FireRefreshTokenAvailable(account_id); - } -} - -void FakeOAuth2TokenServiceDelegate::RevokeCredentials( - const std::string& account_id) { - IssueRefreshTokenForUser(account_id, std::string()); -} - -void FakeOAuth2TokenServiceDelegate::ExtractCredentials( - OAuth2TokenService* to_service, - const std::string& account_id) { - auto it = refresh_tokens_.find(account_id); - DCHECK(it != refresh_tokens_.end()); - to_service->GetDelegate()->UpdateCredentials(account_id, - it->second->refresh_token); - RevokeCredentials(account_id); -} - -scoped_refptr<network::SharedURLLoaderFactory> -FakeOAuth2TokenServiceDelegate::GetURLLoaderFactory() const { - return shared_factory_; -} - -bool FakeOAuth2TokenServiceDelegate::FixRequestErrorIfPossible() { - return fix_request_if_possible_; -} - -void FakeOAuth2TokenServiceDelegate::UpdateAuthError( - const std::string& account_id, - const GoogleServiceAuthError& error) { - backoff_entry_.InformOfRequest(!error.IsTransientError()); - // Drop transient errors to match OAuth2TokenService's stated contract for - // GetAuthError() and to allow clients to test proper behavior in the case of - // transient errors. - if (error.IsTransientError()) - return; - - if (GetAuthError(account_id) == error) - return; - - auto it = refresh_tokens_.find(account_id); - DCHECK(it != refresh_tokens_.end()); - it->second->error = error; - FireAuthErrorChanged(account_id, error); -} diff --git a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.h b/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.h deleted file mode 100644 index 8fff5cc3173..00000000000 --- a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SIGNIN_FAKE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_ -#define CHROME_BROWSER_SIGNIN_FAKE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_token_service_delegate.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" - -namespace network { -class SharedURLLoaderFactory; -} - -class FakeOAuth2TokenServiceDelegate : public OAuth2TokenServiceDelegate { - public: - FakeOAuth2TokenServiceDelegate(); - ~FakeOAuth2TokenServiceDelegate() override; - - OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer) override; - - // Overriden to make sure it works on Android. - bool RefreshTokenIsAvailable(const std::string& account_id) const override; - - GoogleServiceAuthError GetAuthError( - const std::string& account_id) const override; - void UpdateAuthError(const std::string& account_id, - const GoogleServiceAuthError& error) override; - std::vector<std::string> GetAccounts() override; - void RevokeAllCredentials() override; - void LoadCredentials(const std::string& primary_account_id) override; - void UpdateCredentials(const std::string& account_id, - const std::string& refresh_token) override; - void RevokeCredentials(const std::string& account_id) override; - void ExtractCredentials(OAuth2TokenService* to_service, - const std::string& account_id) override; - - scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() - const override; - - bool FixRequestErrorIfPossible() override; - - std::string GetRefreshToken(const std::string& account_id) const; - - network::TestURLLoaderFactory* test_url_loader_factory() { - return &test_url_loader_factory_; - } - - void set_fix_request_if_possible(bool value) { - fix_request_if_possible_ = value; - } - - const net::BackoffEntry* BackoffEntry() const override; - - private: - struct AccountInfo { - AccountInfo(const std::string& refresh_token); - - const std::string refresh_token; - GoogleServiceAuthError error; - }; - - void IssueRefreshTokenForUser(const std::string& account_id, - const std::string& token); - - // Maps account ids to info. - std::map<std::string, std::unique_ptr<AccountInfo>> refresh_tokens_; - - network::TestURLLoaderFactory test_url_loader_factory_; - scoped_refptr<network::SharedURLLoaderFactory> shared_factory_; - bool fix_request_if_possible_ = false; - - net::BackoffEntry backoff_entry_; - - DISALLOW_COPY_AND_ASSIGN(FakeOAuth2TokenServiceDelegate); -}; -#endif diff --git a/chromium/google_apis/gaia/gaia_auth_consumer.cc b/chromium/google_apis/gaia/gaia_auth_consumer.cc index c1034fe5653..db66ff7068b 100644 --- a/chromium/google_apis/gaia/gaia_auth_consumer.cc +++ b/chromium/google_apis/gaia/gaia_auth_consumer.cc @@ -4,20 +4,14 @@ #include "google_apis/gaia/gaia_auth_consumer.h" -GaiaAuthConsumer::ClientLoginResult::ClientLoginResult() - : two_factor(false) { -} +GaiaAuthConsumer::ClientLoginResult::ClientLoginResult() = default; GaiaAuthConsumer::ClientLoginResult::ClientLoginResult( const std::string& new_sid, const std::string& new_lsid, const std::string& new_token, const std::string& new_data) - : sid(new_sid), - lsid(new_lsid), - token(new_token), - data(new_data), - two_factor(false) {} + : sid(new_sid), lsid(new_lsid), token(new_token), data(new_data) {} GaiaAuthConsumer::ClientLoginResult::ClientLoginResult( const ClientLoginResult& other) = default; @@ -26,16 +20,9 @@ GaiaAuthConsumer::ClientLoginResult::~ClientLoginResult() {} bool GaiaAuthConsumer::ClientLoginResult::operator==( const ClientLoginResult &b) const { - return sid == b.sid && - lsid == b.lsid && - token == b.token && - data == b.data && - two_factor == b.two_factor; + return sid == b.sid && lsid == b.lsid && token == b.token && data == b.data; } -GaiaAuthConsumer::ClientOAuthResult::ClientOAuthResult() - : expires_in_secs(0) {} - GaiaAuthConsumer::ClientOAuthResult::ClientOAuthResult( const std::string& new_refresh_token, const std::string& new_access_token, diff --git a/chromium/google_apis/gaia/gaia_auth_consumer.h b/chromium/google_apis/gaia/gaia_auth_consumer.h index f09007842ce..f25ab5deefc 100644 --- a/chromium/google_apis/gaia/gaia_auth_consumer.h +++ b/chromium/google_apis/gaia/gaia_auth_consumer.h @@ -34,11 +34,9 @@ class GaiaAuthConsumer { std::string token; // TODO(chron): Remove the data field later. Don't use it if possible. std::string data; // Full contents of ClientLogin return. - bool two_factor; // set to true if there was a TWO_FACTOR "failure". }; struct ClientOAuthResult { - ClientOAuthResult(); ClientOAuthResult(const std::string& new_refresh_token, const std::string& new_access_token, int new_expires_in_secs, diff --git a/chromium/google_apis/gaia/gaia_auth_fetcher.cc b/chromium/google_apis/gaia/gaia_auth_fetcher.cc index 8eed49b5b46..e20bb74c360 100644 --- a/chromium/google_apis/gaia/gaia_auth_fetcher.cc +++ b/chromium/google_apis/gaia/gaia_auth_fetcher.cc @@ -112,25 +112,40 @@ GetTokenRevocationStatusFromResponseData(const std::string& data, return GaiaAuthConsumer::TokenRevocationStatus::kUnknownError; } -std::string GaiaSourceToString(gaia::GaiaSource source) { +} // namespace + +namespace gaia { + +GaiaSource::GaiaSource(Type type) : type_(type) {} + +GaiaSource::GaiaSource(Type type, const std::string& suffix) + : type_(type), suffix_(suffix) {} + +void GaiaSource::SetGaiaSourceSuffix(const std::string& suffix) { + suffix_ = suffix; +} + +std::string GaiaSource::ToString() { std::string source_string; - switch (source) { - case gaia::GaiaSource::kChrome: + switch (type_) { + case Type::kChrome: source_string = GaiaConstants::kChromeSource; break; - case gaia::GaiaSource::kChromeOS: + case Type::kChromeOS: source_string = GaiaConstants::kChromeOSSource; break; - case gaia::GaiaSource::kAccountReconcilorDice: + case Type::kAccountReconcilorDice: source_string = "ChromiumAccountReconcilorDice"; break; - case gaia::GaiaSource::kAccountReconcilorMirror: + case Type::kAccountReconcilorMirror: source_string = "ChromiumAccountReconcilor"; break; - case gaia::GaiaSource::kOAuth2LoginVerifier: + case Type::kOAuth2LoginVerifier: source_string = "ChromiumOAuth2LoginVerifier"; break; - case gaia::GaiaSource::kSigninManager: + case Type::kPrimaryAccountManager: + // Even though this string refers to an old name from the Chromium POV, it + // should not be changed as it is passed server-side. source_string = "ChromiumSigninManager"; break; } @@ -139,10 +154,10 @@ std::string GaiaSourceToString(gaia::GaiaSource source) { DCHECK(source_string == "chromeos" || base::StartsWith(source_string, "Chromium", base::CompareCase::SENSITIVE)); - return source_string; + return source_string + suffix_; } -} // namespace +} // namespace gaia // static const char GaiaAuthFetcher::kIssueAuthTokenFormat[] = @@ -179,24 +194,9 @@ const char GaiaAuthFetcher::kUberAuthTokenURLFormat[] = const char GaiaAuthFetcher::kOAuthLoginFormat[] = "service=%s&source=%s"; // static -const char GaiaAuthFetcher::kAccountDeletedError[] = "AccountDeleted"; -// static -const char GaiaAuthFetcher::kAccountDisabledError[] = "AccountDisabled"; -// static -const char GaiaAuthFetcher::kCaptchaError[] = "CaptchaRequired"; -// static const char GaiaAuthFetcher::kErrorParam[] = "Error"; // static const char GaiaAuthFetcher::kErrorUrlParam[] = "Url"; -// static -const char GaiaAuthFetcher::kCaptchaUrlParam[] = "CaptchaUrl"; -// static -const char GaiaAuthFetcher::kCaptchaTokenParam[] = "CaptchaToken"; - -// static -const char GaiaAuthFetcher::kSecondFactor[] = "Info=InvalidSecondFactor"; -// static -const char GaiaAuthFetcher::kWebLoginRequired[] = "Info=WebLoginRequired"; // static const char GaiaAuthFetcher::kAuthHeaderFormat[] = @@ -216,7 +216,7 @@ GaiaAuthFetcher::GaiaAuthFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : url_loader_factory_(url_loader_factory), consumer_(consumer), - source_(GaiaSourceToString(source)), + source_(source.ToString()), oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), oauth2_revoke_gurl_(GaiaUrls::GetInstance()->oauth2_revoke_url()), get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), @@ -228,8 +228,6 @@ GaiaAuthFetcher::GaiaAuthFetcher( list_accounts_gurl_( GaiaUrls::GetInstance()->ListAccountsURLWithSource(source_)), logout_gurl_(GaiaUrls::GetInstance()->LogOutURLWithSource(source_)), - logout_with_continue_gurl_( - GaiaUrls::GetInstance()->LogOutURLWithSourceAndContinueURL(source_)), get_check_connection_info_url_( GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource( source_)) {} @@ -441,9 +439,7 @@ std::string GaiaAuthFetcher::MakeOAuthLoginBody(const std::string& service, // static void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, std::string* error, - std::string* error_url, - std::string* captcha_url, - std::string* captcha_token) { + std::string* error_url) { using std::vector; using std::pair; using std::string; @@ -456,10 +452,6 @@ void GaiaAuthFetcher::ParseClientLoginFailure(const std::string& data, error->assign(i->second); } else if (i->first == kErrorUrlParam) { error_url->assign(i->second); - } else if (i->first == kCaptchaUrlParam) { - captcha_url->assign(i->second); - } else if (i->first == kCaptchaTokenParam) { - captcha_token->assign(i->second); } } } @@ -809,14 +801,6 @@ void GaiaAuthFetcher::StartOAuthMultilogin( } void GaiaAuthFetcher::StartLogOut() { - StartLogOutInternal(logout_gurl_); -} - -void GaiaAuthFetcher::StartLogOutWithBlankContinueURL() { - StartLogOutInternal(logout_with_continue_gurl_); -} - -void GaiaAuthFetcher::StartLogOutInternal(const GURL& logout_gurl) { DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; net::NetworkTrafficAnnotationTag traffic_annotation = @@ -846,7 +830,7 @@ void GaiaAuthFetcher::StartLogOutInternal(const GURL& logout_gurl) { } } })"); - CreateAndStartGaiaFetcher(std::string(), std::string(), logout_gurl, + CreateAndStartGaiaFetcher(std::string(), std::string(), logout_gurl_, net::LOAD_NORMAL, traffic_annotation); } @@ -896,29 +880,11 @@ GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( return GoogleServiceAuthError::FromConnectionError(net_error); } - if (IsSecondFactorSuccess(data)) - return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); - - if (IsWebLoginRequiredSuccess(data)) - return GoogleServiceAuthError(GoogleServiceAuthError::WEB_LOGIN_REQUIRED); - std::string error; std::string url; - std::string captcha_url; - std::string captcha_token; - ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); + ParseClientLoginFailure(data, &error, &url); DLOG(WARNING) << "ClientLogin failed with " << error; - if (error == kCaptchaError) { - return GoogleServiceAuthError::FromClientLoginCaptchaChallenge( - captcha_token, - GURL(GaiaUrls::GetInstance()->captcha_base_url().Resolve(captcha_url)), - GURL(url)); - } - if (error == kAccountDeletedError) - return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED); - if (error == kAccountDisabledError) - return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); if (error == kBadAuthenticationShortError || error == kBadAuthenticationError) { return GoogleServiceAuthError( @@ -1145,7 +1111,7 @@ void GaiaAuthFetcher::DispatchFetchedRequest( OnOAuth2RevokeTokenFetched(data, net_error, response_code); } else if (url == list_accounts_gurl_) { OnListAccountsFetched(data, net_error, response_code); - } else if (url == logout_gurl_ || url == logout_with_continue_gurl_) { + } else if (url == logout_gurl_) { OnLogOutFetched(data, net_error, response_code); } else if (url == get_check_connection_info_url_) { OnGetCheckConnectionInfoFetched(data, net_error, response_code); @@ -1153,17 +1119,3 @@ void GaiaAuthFetcher::DispatchFetchedRequest( NOTREACHED() << "Unknown url: '" << url << "'"; } } - -// static -bool GaiaAuthFetcher::IsSecondFactorSuccess( - const std::string& alleged_error) { - return alleged_error.find(kSecondFactor) != - std::string::npos; -} - -// static -bool GaiaAuthFetcher::IsWebLoginRequiredSuccess( - const std::string& alleged_error) { - return alleged_error.find(kWebLoginRequired) != - std::string::npos; -} diff --git a/chromium/google_apis/gaia/gaia_auth_fetcher.h b/chromium/google_apis/gaia/gaia_auth_fetcher.h index bcab70e8ea6..79964d2edf6 100644 --- a/chromium/google_apis/gaia/gaia_auth_fetcher.h +++ b/chromium/google_apis/gaia/gaia_auth_fetcher.h @@ -43,13 +43,26 @@ enum class MultiloginMode { }; // Specifies the "source" parameter for Gaia calls. -enum class GaiaSource { - kChrome, - kChromeOS, - kAccountReconcilorDice, - kAccountReconcilorMirror, - kOAuth2LoginVerifier, - kSigninManager +class GaiaSource { + public: + enum Type { + kChrome, + kChromeOS, + kAccountReconcilorDice, + kAccountReconcilorMirror, + kOAuth2LoginVerifier, + kPrimaryAccountManager + }; + + // Implicit conversion is necessary to avoid boilerplate code. + GaiaSource(Type type); + GaiaSource(Type source, const std::string& suffix); + void SetGaiaSourceSuffix(const std::string& suffix); + std::string ToString(); + + private: + Type type_; + std::string suffix_; }; } // namespace gaia @@ -72,14 +85,6 @@ class GaiaAuthFetcher { } }; - // Magic string indicating that, while a second factor is still - // needed to complete authentication, the user provided the right password. - static const char kSecondFactor[]; - - // Magic string indicating that though the user does not have Less Secure - // Apps enabled, the user provided the right password. - static const char kWebLoginRequired[]; - // This will later be hidden behind an auth service which caches tokens. GaiaAuthFetcher( GaiaAuthConsumer* consumer, @@ -168,10 +173,6 @@ class GaiaAuthFetcher { // Starts a request to log out the accounts in the GAIA cookie. void StartLogOut(); - // Starts a request to log out the accounts in the GAIA cookie. Uses Logout - // endpoint with continue URL. - void StartLogOutWithBlankContinueURL(); - // Starts a request to get the list of URLs to check for connection info. // Returns token/URL pairs to check, and the resulting status can be given to // /MergeSession requests. @@ -245,21 +246,8 @@ class GaiaAuthFetcher { static const char kOAuthLoginFormat[]; // Constants for parsing ClientLogin errors. - static const char kAccountDeletedError[]; - static const char kAccountDeletedErrorCode[]; - static const char kAccountDisabledError[]; - static const char kAccountDisabledErrorCode[]; - static const char kCaptchaError[]; - static const char kCaptchaErrorCode[]; static const char kErrorParam[]; static const char kErrorUrlParam[]; - static const char kCaptchaUrlParam[]; - static const char kCaptchaTokenParam[]; - - // Constants for parsing ClientOAuth errors. - static const char kNeedsAdditional[]; - static const char kCaptcha[]; - static const char kTwoFactor[]; // Constants for request/response for OAuth2 requests. static const char kAuthHeaderFormat[]; @@ -267,9 +255,6 @@ class GaiaAuthFetcher { static const char kOAuth2BearerHeaderFormat[]; static const char kOAuthMultiBearerHeaderFormat[]; - // Starts logout flow with an explicit GURL. - void StartLogOutInternal(const GURL& logout_gurl); - void OnURLLoadComplete(std::unique_ptr<std::string> response_body); void OnOAuth2TokenPairFetched(const std::string& data, @@ -320,15 +305,7 @@ class GaiaAuthFetcher { static void ParseClientLoginFailure(const std::string& data, std::string* error, - std::string* error_url, - std::string* captcha_url, - std::string* captcha_token); - - // Is this a special case Gaia error for TwoFactor auth? - static bool IsSecondFactorSuccess(const std::string& alleged_error); - - // Is this a special case Gaia error for Less Secure Apps? - static bool IsWebLoginRequiredSuccess(const std::string& alleged_error); + std::string* error_url); // Supply the sid / lsid returned from ClientLogin in order to // request a long lived auth token for a service. @@ -376,7 +353,6 @@ class GaiaAuthFetcher { const GURL oauth_multilogin_gurl_; const GURL list_accounts_gurl_; const GURL logout_gurl_; - const GURL logout_with_continue_gurl_; const GURL get_check_connection_info_url_; // While a fetch is going on: @@ -397,8 +373,6 @@ class GaiaAuthFetcher { friend class GaiaAuthFetcherTest; FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, CaptchaParse); - FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDeletedError); - FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, AccountDisabledError); FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationError); FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, BadAuthenticationShortError); FRIEND_TEST_ALL_PREFIXES(GaiaAuthFetcherTest, IncomprehensibleError); diff --git a/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc b/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc index 8f9c4721049..b0163e74480 100644 --- a/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc +++ b/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc @@ -29,6 +29,7 @@ #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -98,23 +99,13 @@ class GaiaAuthFetcherTest : public testing::Test { void RunErrorParsingTest(const std::string& data, const std::string& error, - const std::string& error_url, - const std::string& captcha_url, - const std::string& captcha_token) { + const std::string& error_url) { std::string out_error; std::string out_error_url; - std::string out_captcha_url; - std::string out_captcha_token; - - GaiaAuthFetcher::ParseClientLoginFailure(data, - &out_error, - &out_error_url, - &out_captcha_url, - &out_captcha_token); + + GaiaAuthFetcher::ParseClientLoginFailure(data, &out_error, &out_error_url); EXPECT_EQ(error, out_error); EXPECT_EQ(error_url, out_error_url); - EXPECT_EQ(captcha_url, out_captcha_url); - EXPECT_EQ(captcha_token, out_captcha_token); } GURL oauth2_token_source_; @@ -234,62 +225,18 @@ TEST_F(GaiaAuthFetcherTest, ParseRequest) { } TEST_F(GaiaAuthFetcherTest, ParseErrorRequest) { - RunErrorParsingTest("Url=U\n" - "Error=E\n" - "CaptchaToken=T\n" - "CaptchaUrl=C\n", "E", "U", "C", "T"); - RunErrorParsingTest("CaptchaToken=T\n" - "Error=E\n" - "Url=U\n" - "CaptchaUrl=C\n", "E", "U", "C", "T"); - RunErrorParsingTest("\n\n\nCaptchaToken=T\n" - "\nError=E\n" - "\nUrl=U\n" - "CaptchaUrl=C\n", "E", "U", "C", "T"); -} - -TEST_F(GaiaAuthFetcherTest, CheckTwoFactorResponse) { - std::string response = - base::StringPrintf("Error=BadAuthentication\n%s\n", - GaiaAuthFetcher::kSecondFactor); - EXPECT_TRUE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); -} - -TEST_F(GaiaAuthFetcherTest, CheckNormalErrorCode) { - std::string response = "Error=BadAuthentication\n"; - EXPECT_FALSE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); -} - -TEST_F(GaiaAuthFetcherTest, CaptchaParse) { - std::string data = "Url=http://www.google.com/login/captcha\n" - "Error=CaptchaRequired\n" - "CaptchaToken=CCTOKEN\n" - "CaptchaUrl=Captcha?ctoken=CCTOKEN\n"; - GoogleServiceAuthError error = - GaiaAuthFetcher::GenerateAuthError(data, net::OK); - - std::string token = "CCTOKEN"; - GURL image_url("http://accounts.google.com/Captcha?ctoken=CCTOKEN"); - GURL unlock_url("http://www.google.com/login/captcha"); - - EXPECT_EQ(error.state(), GoogleServiceAuthError::CAPTCHA_REQUIRED); - EXPECT_EQ(error.captcha().token, token); - EXPECT_EQ(error.captcha().image_url, image_url); - EXPECT_EQ(error.captcha().unlock_url, unlock_url); -} - -TEST_F(GaiaAuthFetcherTest, AccountDeletedError) { - std::string data = "Error=AccountDeleted\n"; - GoogleServiceAuthError error = - GaiaAuthFetcher::GenerateAuthError(data, net::OK); - EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DELETED); -} - -TEST_F(GaiaAuthFetcherTest, AccountDisabledError) { - std::string data = "Error=AccountDisabled\n"; - GoogleServiceAuthError error = - GaiaAuthFetcher::GenerateAuthError(data, net::OK); - EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DISABLED); + RunErrorParsingTest( + "Url=U\n" + "Error=E\n", + "E", "U"); + RunErrorParsingTest( + "Error=E\n" + "Url=U\n", + "E", "U"); + RunErrorParsingTest( + "\n\n\nError=E\n" + "\nUrl=U\n", + "E", "U"); } TEST_F(GaiaAuthFetcherTest, BadAuthenticationError) { @@ -494,8 +441,7 @@ TEST_F(GaiaAuthFetcherTest, UberAuthTokenSuccess) { } TEST_F(GaiaAuthFetcherTest, StartOAuthLogin) { - // OAuthLogin returns the same as the ClientLogin endpoint, minus CAPTCHA - // responses. + // OAuthLogin returns the same as the ClientLogin endpoint. std::string data("SID=sid\nLSID=lsid\nAuth=auth\n"); GaiaAuthConsumer::ClientLoginResult result; @@ -510,7 +456,7 @@ TEST_F(GaiaAuthFetcherTest, StartOAuthLogin) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting(/*body=*/"", /*headers=*/"", oauth_login_gurl_, /*load_flags=*/0, - NO_TRAFFIC_ANNOTATION_YET); + TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_OK, data); } @@ -531,7 +477,7 @@ TEST_F(GaiaAuthFetcherTest, ListAccounts) { /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->ListAccountsURLWithSource( GaiaConstants::kChromeSource), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); ASSERT_EQ(received_requests_.size(), 1U); EXPECT_EQ(net::LOAD_NORMAL, received_requests_.at(0).load_flags); EXPECT_EQ(GaiaUrls::GetInstance()->gaia_url(), @@ -548,7 +494,7 @@ TEST_F(GaiaAuthFetcherTest, LogOutSuccess) { /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->LogOutURLWithSource( GaiaConstants::kChromeSource), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK); } @@ -566,7 +512,7 @@ TEST_F(GaiaAuthFetcherTest, LogOutFailure) { /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->LogOutURLWithSource( GaiaConstants::kChromeSource), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(error_no); } @@ -582,7 +528,7 @@ TEST_F(GaiaAuthFetcherTest, GetCheckConnectionInfo) { /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource( GaiaConstants::kChromeSource), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_OK, data); } @@ -596,7 +542,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenSuccess) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_OK, data); } @@ -610,7 +556,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenCanceled) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::ERR_ABORTED); } @@ -624,7 +570,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenFailed) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::ERR_CERT_CONTAINS_ERRORS); } @@ -638,7 +584,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenTimeout) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::ERR_TIMED_OUT); } @@ -653,7 +599,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenInvalidToken) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_BAD_REQUEST, data); } @@ -668,7 +614,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenInvalidRequest) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_BAD_REQUEST, data); } @@ -683,7 +629,7 @@ TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenServerError) { TestGaiaAuthFetcher auth(&consumer, GetURLLoaderFactory()); auth.CreateAndStartGaiaFetcherForTesting( /*body=*/"", /*headers=*/"", GaiaUrls::GetInstance()->oauth2_revoke_url(), - /*load_flags=*/0, NO_TRAFFIC_ANNOTATION_YET); + /*load_flags=*/0, TRAFFIC_ANNOTATION_FOR_TESTS); auth.TestOnURLLoadCompleteInternal(net::OK, net::HTTP_INTERNAL_SERVER_ERROR, data); } diff --git a/chromium/google_apis/gaia/gaia_auth_util.h b/chromium/google_apis/gaia/gaia_auth_util.h index c6af6322490..a8c60d8457f 100644 --- a/chromium/google_apis/gaia/gaia_auth_util.h +++ b/chromium/google_apis/gaia/gaia_auth_util.h @@ -9,6 +9,8 @@ #include <utility> #include <vector> +#include "google_apis/gaia/core_account_id.h" + class GURL; namespace gaia { @@ -16,7 +18,8 @@ namespace gaia { struct ListedAccount { // The account's ID, as per Chrome, will be determined in the // CookieManagerService. - std::string id; + // TODO(triploblastic): Rename the id field to account_id. + CoreAccountId id; std::string email; std::string gaia_id; std::string raw_email; diff --git a/chromium/google_apis/gaia/gaia_constants.cc b/chromium/google_apis/gaia/gaia_constants.cc index 72c9da431a1..63cb6bd0a5e 100644 --- a/chromium/google_apis/gaia/gaia_constants.cc +++ b/chromium/google_apis/gaia/gaia_constants.cc @@ -11,6 +11,7 @@ namespace GaiaConstants { // Gaia uses this for accounting where login is coming from. const char kChromeOSSource[] = "chromeos"; const char kChromeSource[] = "ChromiumBrowser"; +const char kUnexpectedServiceResponse[] = "UnexpectedServiceResponse"; // Service name for Gaia. Used to convert to cookie auth. const char kGaiaService[] = "gaia"; @@ -42,9 +43,9 @@ const char kChromeSyncOAuth2Scope[] = const char kChromeSyncSupervisedOAuth2Scope[] = "https://www.googleapis.com/auth/chromesync_playpen"; -// OAuth2 scope for access to Google Family Link kid scope. -const char kKidFamilyOAuth2Scope[] = - "https://www.googleapis.com/auth/kid.family.readonly"; +// OAuth2 scope for access to Google Family Link Supervision Setup. +const char kKidsSupervisionSetupChildOAuth2Scope[] = + "https://www.googleapis.com/auth/kids.supervision.setup.child"; // OAuth2 scope for access to Google Talk APIs (XMPP). const char kGoogleTalkOAuth2Scope[] = @@ -55,7 +56,15 @@ const char kGoogleUserInfoEmail[] = const char kGoogleUserInfoProfile[] = "https://www.googleapis.com/auth/userinfo.profile"; - // Used to mint uber auth tokens when needed. +// OAuth scope for access to the people API (read-only). +const char kPeopleApiReadOnlyOAuth2Scope[] = + "https://www.googleapis.com/auth/peopleapi.readonly"; + +// OAuth scope for access to the Reauth flow. +const char kAccountsReauthOAuth2Scope[] = + "https://www.googleapis.com/auth/accounts.reauth"; + +// Used to mint uber auth tokens when needed. const char kGaiaSid[] = "sid"; const char kGaiaLsid[] = "lsid"; const char kGaiaOAuthToken[] = "oauthToken"; @@ -74,4 +83,6 @@ const char kObfuscatedGaiaId[] = "obfuscatedGaiaId"; // Canonical email of the account to sign in. const char kClientOAuthEmailKey[] = "email"; +// Used as an Invalid refresh token. +const char kInvalidRefreshToken[] = "invalid_refresh_token"; } // namespace GaiaConstants diff --git a/chromium/google_apis/gaia/gaia_constants.h b/chromium/google_apis/gaia/gaia_constants.h index 42e80763d1f..5694050ede4 100644 --- a/chromium/google_apis/gaia/gaia_constants.h +++ b/chromium/google_apis/gaia/gaia_constants.h @@ -12,6 +12,9 @@ namespace GaiaConstants { // Gaia sources for accounting extern const char kChromeOSSource[]; extern const char kChromeSource[]; +// Used as Gaia source suffix to detect retry requests because of +// |GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE|. +extern const char kUnexpectedServiceResponse[]; // Gaia services for requesting extern const char kGaiaService[]; // uber token @@ -26,10 +29,12 @@ extern const char kDeviceManagementServiceOAuth[]; extern const char kAnyApiOAuth2Scope[]; extern const char kChromeSyncOAuth2Scope[]; extern const char kChromeSyncSupervisedOAuth2Scope[]; -extern const char kKidFamilyOAuth2Scope[]; +extern const char kKidsSupervisionSetupChildOAuth2Scope[]; extern const char kGoogleTalkOAuth2Scope[]; extern const char kGoogleUserInfoEmail[]; extern const char kGoogleUserInfoProfile[]; +extern const char kPeopleApiReadOnlyOAuth2Scope[]; +extern const char kAccountsReauthOAuth2Scope[]; // Used with uber auth tokens when needed. extern const char kGaiaSid[]; @@ -45,6 +50,8 @@ extern const char kObfuscatedGaiaId[]; // Used by wallet sign in helper. extern const char kClientOAuthEmailKey[]; +// Refresh token that is guaranteed to be invalid. +extern const char kInvalidRefreshToken[]; } // namespace GaiaConstants #endif // GOOGLE_APIS_GAIA_GAIA_CONSTANTS_H_ diff --git a/chromium/google_apis/gaia/gaia_oauth_client_unittest.cc b/chromium/google_apis/gaia/gaia_oauth_client_unittest.cc index 3583d242a69..9a543bdb02c 100644 --- a/chromium/google_apis/gaia/gaia_oauth_client_unittest.cc +++ b/chromium/google_apis/gaia/gaia_oauth_client_unittest.cc @@ -169,7 +169,7 @@ class GaiaOAuthClientTest : public testing::Test { protected: GaiaOAuthClientTest() : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {} + base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {} void SetUp() override { client_info_.client_id = "test_client_id"; diff --git a/chromium/google_apis/gaia/gaia_urls.cc b/chromium/google_apis/gaia/gaia_urls.cc index c464febee00..f7796e2ddd2 100644 --- a/chromium/google_apis/gaia/gaia_urls.cc +++ b/chromium/google_apis/gaia/gaia_urls.cc @@ -294,12 +294,6 @@ GURL GaiaUrls::ListAccountsURLWithSource(const std::string& source) { } GURL GaiaUrls::LogOutURLWithSource(const std::string& source) { - return source.empty() ? service_logout_url_ - : service_logout_url_.Resolve( - base::StringPrintf("?source=%s", source.c_str())); -} - -GURL GaiaUrls::LogOutURLWithSourceAndContinueURL(const std::string& source) { std::string params = source.empty() ? base::StringPrintf("?continue=%s", diff --git a/chromium/google_apis/gaia/gaia_urls.h b/chromium/google_apis/gaia/gaia_urls.h index 68455c9e102..76974febfe7 100644 --- a/chromium/google_apis/gaia/gaia_urls.h +++ b/chromium/google_apis/gaia/gaia_urls.h @@ -52,7 +52,6 @@ class GaiaUrls { GURL ListAccountsURLWithSource(const std::string& source); GURL LogOutURLWithSource(const std::string& source); - GURL LogOutURLWithSourceAndContinueURL(const std::string& source); GURL GetCheckConnectionInfoURLWithSource(const std::string& source); private: diff --git a/chromium/google_apis/gaia/google_service_auth_error.cc b/chromium/google_apis/gaia/google_service_auth_error.cc index 4c699c07f1d..73ef9fad244 100644 --- a/chromium/google_apis/gaia/google_service_auth_error.cc +++ b/chromium/google_apis/gaia/google_service_auth_error.cc @@ -33,58 +33,9 @@ const char* InvalidCredentialsReasonToString( } } // namespace -GoogleServiceAuthError::Captcha::Captcha() : image_width(0), image_height(0) { -} - -GoogleServiceAuthError::Captcha::Captcha( - const std::string& token, const GURL& audio, const GURL& img, - const GURL& unlock, int width, int height) - : token(token), audio_url(audio), image_url(img), unlock_url(unlock), - image_width(width), image_height(height) { -} - -GoogleServiceAuthError::Captcha::Captcha(const Captcha& other) = default; - -GoogleServiceAuthError::Captcha::~Captcha() { -} - -bool GoogleServiceAuthError::Captcha::operator==(const Captcha& b) const { - return (token == b.token && - audio_url == b.audio_url && - image_url == b.image_url && - unlock_url == b.unlock_url && - image_width == b.image_width && - image_height == b.image_height); -} - -GoogleServiceAuthError::SecondFactor::SecondFactor() : field_length(0) { -} - -GoogleServiceAuthError::SecondFactor::SecondFactor( - const std::string& token, const std::string& prompt, - const std::string& alternate, int length) - : token(token), prompt_text(prompt), alternate_text(alternate), - field_length(length) { -} - -GoogleServiceAuthError::SecondFactor::SecondFactor(const SecondFactor& other) = - default; - -GoogleServiceAuthError::SecondFactor::~SecondFactor() { -} - -bool GoogleServiceAuthError::SecondFactor::operator==( - const SecondFactor& b) const { - return (token == b.token && - prompt_text == b.prompt_text && - alternate_text == b.alternate_text && - field_length == b.field_length); -} - bool GoogleServiceAuthError::operator==( const GoogleServiceAuthError& b) const { return (state_ == b.state_) && (network_error_ == b.network_error_) && - (captcha_ == b.captcha_) && (second_factor_ == b.second_factor_) && (error_message_ == b.error_message_) && (invalid_gaia_credentials_reason_ == b.invalid_gaia_credentials_reason_); @@ -127,15 +78,6 @@ GoogleServiceAuthError GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( } // static -GoogleServiceAuthError GoogleServiceAuthError::FromClientLoginCaptchaChallenge( - const std::string& captcha_token, - const GURL& captcha_image_url, - const GURL& captcha_unlock_url) { - return GoogleServiceAuthError(CAPTCHA_REQUIRED, captcha_token, GURL(), - captcha_image_url, captcha_unlock_url, 0, 0); -} - -// static GoogleServiceAuthError GoogleServiceAuthError::FromServiceError( const std::string& error_message) { return GoogleServiceAuthError(SERVICE_ERROR, error_message); @@ -153,41 +95,32 @@ GoogleServiceAuthError GoogleServiceAuthError::AuthErrorNone() { } // static -bool GoogleServiceAuthError::IsDeprecated(State state) { - return state == HOSTED_NOT_ALLOWED_DEPRECATED; +bool GoogleServiceAuthError::IsValid(State state) { + switch (state) { + case NONE: + case INVALID_GAIA_CREDENTIALS: + case USER_NOT_SIGNED_UP: + case CONNECTION_FAILED: + case SERVICE_UNAVAILABLE: + case REQUEST_CANCELED: + case UNEXPECTED_SERVICE_RESPONSE: + case SERVICE_ERROR: + return true; + case NUM_STATES: + return false; + } + + return false; } GoogleServiceAuthError::State GoogleServiceAuthError::state() const { return state_; } -const GoogleServiceAuthError::Captcha& GoogleServiceAuthError::captcha() const { - return captcha_; -} - -const GoogleServiceAuthError::SecondFactor& -GoogleServiceAuthError::second_factor() const { - return second_factor_; -} - int GoogleServiceAuthError::network_error() const { return network_error_; } -const std::string& GoogleServiceAuthError::token() const { - switch (state_) { - case CAPTCHA_REQUIRED: - return captcha_.token; - break; - case TWO_FACTOR: - return second_factor_.token; - break; - default: - NOTREACHED(); - } - return base::EmptyString(); -} - const std::string& GoogleServiceAuthError::error_message() const { return error_message_; } @@ -210,18 +143,8 @@ std::string GoogleServiceAuthError::ToString() const { return "Not authorized."; case CONNECTION_FAILED: return base::StringPrintf("Connection failed (%d).", network_error_); - case CAPTCHA_REQUIRED: - return base::StringPrintf("CAPTCHA required (%s).", - captcha_.token.c_str()); - case ACCOUNT_DELETED: - return "Account deleted."; - case ACCOUNT_DISABLED: - return "Account disabled."; case SERVICE_UNAVAILABLE: return "Service unavailable; try again later."; - case TWO_FACTOR: - return base::StringPrintf("2-step verification required (%s).", - second_factor_.token.c_str()); case REQUEST_CANCELED: return "Request canceled."; case UNEXPECTED_SERVICE_RESPONSE: @@ -230,11 +153,6 @@ std::string GoogleServiceAuthError::ToString() const { case SERVICE_ERROR: return base::StringPrintf("Service responded with error: '%s'", error_message_.c_str()); - case WEB_LOGIN_REQUIRED: - return "Less secure apps may not authenticate with this account. " - "Please visit: " - "https://www.google.com/settings/security/lesssecureapps"; - case HOSTED_NOT_ALLOWED_DEPRECATED: case NUM_STATES: NOTREACHED(); return std::string(); @@ -263,20 +181,3 @@ GoogleServiceAuthError::GoogleServiceAuthError(State s, int error) : state_(s), network_error_(error), invalid_gaia_credentials_reason_(InvalidGaiaCredentialsReason::UNKNOWN) {} - -GoogleServiceAuthError::GoogleServiceAuthError(State s, - const std::string& captcha_token, - const GURL& captcha_audio_url, - const GURL& captcha_image_url, - const GURL& captcha_unlock_url, - int image_width, - int image_height) - : state_(s), - captcha_(captcha_token, - captcha_audio_url, - captcha_image_url, - captcha_unlock_url, - image_width, - image_height), - network_error_((state_ == CONNECTION_FAILED) ? net::ERR_FAILED : net::OK), - invalid_gaia_credentials_reason_(InvalidGaiaCredentialsReason::UNKNOWN) {} diff --git a/chromium/google_apis/gaia/google_service_auth_error.h b/chromium/google_apis/gaia/google_service_auth_error.h index 7919ee847e4..e3cd035f2fc 100644 --- a/chromium/google_apis/gaia/google_service_auth_error.h +++ b/chromium/google_apis/gaia/google_service_auth_error.h @@ -45,31 +45,34 @@ class GoogleServiceAuthError { // the service needing GAIA tokens during authentication. CONNECTION_FAILED = 3, + // DEPRECATED. // The user needs to satisfy a CAPTCHA challenge to unlock their account. // If no other information is available, this can be resolved by visiting // https://accounts.google.com/DisplayUnlockCaptcha. Otherwise, captcha() // will provide details about the associated challenge. - CAPTCHA_REQUIRED = 4, + // CAPTCHA_REQUIRED = 4, + // DEPRECATED. // The user account has been deleted. - ACCOUNT_DELETED = 5, + // ACCOUNT_DELETED = 5, + // DEPRECATED. // The user account has been disabled. - ACCOUNT_DISABLED = 6, + // ACCOUNT_DISABLED = 6, // The service is not available; try again later. SERVICE_UNAVAILABLE = 7, + // DEPRECATED. // The password is valid but we need two factor to get a token. - TWO_FACTOR = 8, + // TWO_FACTOR = 8, // The requestor of the authentication step cancelled the request // prior to completion. REQUEST_CANCELED = 9, - // HOSTED accounts are deprecated; left in enumeration to match - // GoogleServiceAuthError enum in histograms.xml. - HOSTED_NOT_ALLOWED_DEPRECATED = 10, + // HOSTED accounts are deprecated. + // HOSTED_NOT_ALLOWED_DEPRECATED = 10, // Indicates the service responded to a request, but we cannot // interpret the response. @@ -79,13 +82,16 @@ class GoogleServiceAuthError { // application error. SERVICE_ERROR = 12, + // DEPRECATED. // The password is valid but web login is required to get a token. - WEB_LOGIN_REQUIRED = 13, + // WEB_LOGIN_REQUIRED = 13, // The number of known error states. NUM_STATES = 14, }; + static constexpr size_t kDeprecatedStateCount = 6; + // Error reason for invalid credentials. Only used when the error is // INVALID_GAIA_CREDENTIALS. // Used by UMA histograms: do not remove or reorder values, add new values at @@ -103,52 +109,6 @@ class GoogleServiceAuthError { NUM_REASONS }; - // Additional data for CAPTCHA_REQUIRED errors. - struct Captcha { - Captcha(); - Captcha(const std::string& token, - const GURL& audio, - const GURL& img, - const GURL& unlock, - int width, - int height); - Captcha(const Captcha& other); - ~Captcha(); - // For test only. - bool operator==(const Captcha &b) const; - - std::string token; // Globally identifies the specific CAPTCHA challenge. - GURL audio_url; // The CAPTCHA audio to use instead of image. - GURL image_url; // The CAPTCHA image to show the user. - GURL unlock_url; // Pretty unlock page containing above captcha. - int image_width; // Width of captcha image. - int image_height; // Height of capture image. - }; - - // Additional data for TWO_FACTOR errors. - struct SecondFactor { - SecondFactor(); - SecondFactor(const std::string& token, - const std::string& prompt, - const std::string& alternate, - int length); - SecondFactor(const SecondFactor& other); - ~SecondFactor(); - // For test only. - bool operator==(const SecondFactor &b) const; - - // Globally identifies the specific second-factor challenge. - std::string token; - // Localized prompt text, e.g. "Enter the verification code sent to your - // phone number ending in XXX". - std::string prompt_text; - // Localized text describing an alternate option, e.g. "Get a verification - // code in a text message". - std::string alternate_text; - // Character length for the challenge field. - int field_length; - }; - bool operator==(const GoogleServiceAuthError &b) const; bool operator!=(const GoogleServiceAuthError &b) const; @@ -168,15 +128,6 @@ class GoogleServiceAuthError { static GoogleServiceAuthError FromInvalidGaiaCredentialsReason( InvalidGaiaCredentialsReason reason); - // Construct a CAPTCHA_REQUIRED error with CAPTCHA challenge data from the - // the ClientLogin endpoint. - // TODO(rogerta): once ClientLogin is no longer used, may be able to get - // rid of this function. - static GoogleServiceAuthError FromClientLoginCaptchaChallenge( - const std::string& captcha_token, - const GURL& captcha_image_url, - const GURL& captcha_unlock_url); - // Construct a SERVICE_ERROR error, e.g. invalid client ID, with an // |error_message| which provides more information about the service error. static GoogleServiceAuthError FromServiceError( @@ -192,14 +143,11 @@ class GoogleServiceAuthError { // to explicit class and State enum relation. Note: shouldn't be inlined! static GoogleServiceAuthError AuthErrorNone(); - static bool IsDeprecated(State state); + static bool IsValid(State state); // The error information. State state() const; - const Captcha& captcha() const; - const SecondFactor& second_factor() const; int network_error() const; - const std::string& token() const; const std::string& error_message() const; // Should only be used when the error state is INVALID_GAIA_CREDENTIALS. @@ -225,16 +173,7 @@ class GoogleServiceAuthError { // Construct a GoogleServiceAuthError from |state| and |error_message|. GoogleServiceAuthError(State state, const std::string& error_message); - GoogleServiceAuthError(State s, const std::string& captcha_token, - const GURL& captcha_audio_url, - const GURL& captcha_image_url, - const GURL& captcha_unlock_url, - int image_width, - int image_height); - State state_; - Captcha captcha_; - SecondFactor second_factor_; int network_error_; std::string error_message_; InvalidGaiaCredentialsReason invalid_gaia_credentials_reason_; diff --git a/chromium/google_apis/gaia/google_service_auth_error_unittest.cc b/chromium/google_apis/gaia/google_service_auth_error_unittest.cc index 4980f3cf398..869a6883961 100644 --- a/chromium/google_apis/gaia/google_service_auth_error_unittest.cc +++ b/chromium/google_apis/gaia/google_service_auth_error_unittest.cc @@ -16,6 +16,9 @@ TEST(GoogleServiceAuthErrorTest, State) { for (GoogleServiceAuthError::State i = GoogleServiceAuthError::NONE; i < GoogleServiceAuthError::NUM_STATES; i = GoogleServiceAuthError::State(i + 1)) { + if (!GoogleServiceAuthError::IsValid(i)) + continue; + GoogleServiceAuthError error(i); EXPECT_EQ(i, error.state()); EXPECT_TRUE(error.error_message().empty()); diff --git a/chromium/google_apis/gaia/oauth2_token_service.cc b/chromium/google_apis/gaia/oauth2_access_token_manager.cc index 1f449aaa5db..4be75cea051 100644 --- a/chromium/google_apis/gaia/oauth2_token_service.cc +++ b/chromium/google_apis/gaia/oauth2_access_token_manager.cc @@ -1,83 +1,69 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "google_apis/gaia/oauth2_token_service.h" +#include "google_apis/gaia/oauth2_access_token_manager.h" -#include <stdint.h> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" -#include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" -#include "google_apis/gaia/oauth2_token_service_delegate.h" +#include "google_apis/gaia/oauth2_access_token_fetcher.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -int OAuth2TokenService::max_fetch_retry_num_ = 5; +int OAuth2AccessTokenManager::max_fetch_retry_num_ = 5; -OAuth2TokenService::RequestParameters::RequestParameters( - const std::string& client_id, - const std::string& account_id, - const ScopeSet& scopes) - : client_id(client_id), - account_id(account_id), - scopes(scopes) { +OAuth2AccessTokenManager::Delegate::Delegate() = default; + +OAuth2AccessTokenManager::Delegate::~Delegate() = default; + +bool OAuth2AccessTokenManager::Delegate::FixRequestErrorIfPossible() { + return false; } -OAuth2TokenService::RequestParameters::RequestParameters( - const RequestParameters& other) = default; +scoped_refptr<network::SharedURLLoaderFactory> +OAuth2AccessTokenManager::Delegate::GetURLLoaderFactory() const { + return nullptr; +} -OAuth2TokenService::RequestParameters::~RequestParameters() { +bool OAuth2AccessTokenManager::Delegate::HandleAccessTokenFetch( + RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const std::string& client_id, + const std::string& client_secret, + const ScopeSet& scopes) { + return false; } -bool OAuth2TokenService::RequestParameters::operator<( - const RequestParameters& p) const { - if (client_id < p.client_id) - return true; - else if (p.client_id < client_id) - return false; +OAuth2AccessTokenManager::Request::Request() {} - if (account_id < p.account_id) - return true; - else if (p.account_id < account_id) - return false; +OAuth2AccessTokenManager::Request::~Request() {} - return scopes < p.scopes; -} +OAuth2AccessTokenManager::Consumer::Consumer(const std::string& id) : id_(id) {} -OAuth2TokenService::RequestImpl::RequestImpl( - const std::string& account_id, - OAuth2TokenService::Consumer* consumer) - : account_id_(account_id), - consumer_(consumer) { -} +OAuth2AccessTokenManager::Consumer::~Consumer() {} -OAuth2TokenService::RequestImpl::~RequestImpl() { +OAuth2AccessTokenManager::RequestImpl::RequestImpl( + const CoreAccountId& account_id, + Consumer* consumer) + : account_id_(account_id), consumer_(consumer) {} + +OAuth2AccessTokenManager::RequestImpl::~RequestImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -std::string OAuth2TokenService::RequestImpl::GetAccountId() const { +CoreAccountId OAuth2AccessTokenManager::RequestImpl::GetAccountId() const { return account_id_; } -std::string OAuth2TokenService::RequestImpl::GetConsumerId() const { +std::string OAuth2AccessTokenManager::RequestImpl::GetConsumerId() const { return consumer_->id(); } -void OAuth2TokenService::RequestImpl::InformConsumer( +void OAuth2AccessTokenManager::RequestImpl::InformConsumer( const GoogleServiceAuthError& error, const OAuth2AccessTokenConsumer::TokenResponse& token_response) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -87,24 +73,50 @@ void OAuth2TokenService::RequestImpl::InformConsumer( consumer_->OnGetTokenFailure(this, error); } +OAuth2AccessTokenManager::RequestParameters::RequestParameters( + const std::string& client_id, + const CoreAccountId& account_id, + const ScopeSet& scopes) + : client_id(client_id), account_id(account_id), scopes(scopes) {} + +OAuth2AccessTokenManager::RequestParameters::RequestParameters( + const RequestParameters& other) = default; + +OAuth2AccessTokenManager::RequestParameters::~RequestParameters() {} + +bool OAuth2AccessTokenManager::RequestParameters::operator<( + const RequestParameters& p) const { + if (client_id < p.client_id) + return true; + else if (p.client_id < client_id) + return false; + + if (account_id < p.account_id) + return true; + else if (p.account_id < account_id) + return false; + + return scopes < p.scopes; +} + // Class that fetches an OAuth2 access token for a given account id and set of // scopes. // -// It aims to meet OAuth2TokenService's requirements on token fetching. Retry -// mechanism is used to handle failures. +// It aims to meet OAuth2AccessTokenManager's requirements on token fetching. +// Retry mechanism is used to handle failures. // // To use this class, call CreateAndStart() to create and start a Fetcher. // -// The Fetcher will call back the service by calling -// OAuth2TokenService::OnFetchComplete() when it completes fetching, if it is -// not destroyed before it completes fetching; if the Fetcher is destroyed -// before it completes fetching, the service will never be called back. The -// Fetcher destroys itself after calling back the service when it finishes +// The Fetcher will call back the token manager by calling +// OAuth2AccessTokenManager::OnFetchComplete() when it completes fetching, if +// it is not destroyed before it completes fetching; if the Fetcher is destroyed +// before it completes fetching, the token manager will never be called back. +// The Fetcher destroys itself after calling back the manager when it finishes // fetching. // // Requests that are waiting for the fetching results of this Fetcher can be // added to the Fetcher by calling -// OAuth2TokenService::Fetcher::AddWaitingRequest() before the Fetcher +// OAuth2AccessTokenManager::Fetcher::AddWaitingRequest() before the Fetcher // completes fetching. // // The waiting requests are taken as weak pointers and they can be deleted. @@ -112,17 +124,18 @@ void OAuth2TokenService::RequestImpl::InformConsumer( // fetching or is destroyed, whichever comes first. In the latter case, the // waiting requests will be called back with an error. // -// The OAuth2TokenService and the waiting requests will never be called back on -// the same turn of the message loop as when the fetcher is started, even if an -// immediate error occurred. -class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { +// The OAuth2AccessTokenManager and the waiting requests will never be called +// back on the same turn of the message loop as when the fetcher is started, +// even if an immediate error occurred. +class OAuth2AccessTokenManager::Fetcher : public OAuth2AccessTokenConsumer { public: // Creates a Fetcher and starts fetching an OAuth2 access token for // |account_id| and |scopes| in the request context obtained by |getter|. - // The given |oauth2_token_service| will be informed when fetching is done. - static std::unique_ptr<OAuth2TokenService::Fetcher> CreateAndStart( - OAuth2TokenService* oauth2_token_service, - const std::string& account_id, + // The given |oauth2_access_token_manager| will be informed when fetching is + // done. + static std::unique_ptr<OAuth2AccessTokenManager::Fetcher> CreateAndStart( + OAuth2AccessTokenManager* oauth2_access_token_manager, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, @@ -136,7 +149,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { // Returns count of waiting requests. size_t GetWaitingRequestCount() const; - const std::vector<base::WeakPtr<RequestImpl> >& waiting_requests() const { + const std::vector<base::WeakPtr<RequestImpl>>& waiting_requests() const { return waiting_requests_; } @@ -144,7 +157,7 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { const ScopeSet& GetScopeSet() const; const std::string& GetClientId() const; - const std::string& GetAccountId() const; + const CoreAccountId& GetAccountId() const; // The error result from this fetcher. const GoogleServiceAuthError& error() const { return error_; } @@ -156,12 +169,12 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { void OnGetTokenFailure(const GoogleServiceAuthError& error) override; private: - Fetcher(OAuth2TokenService* oauth2_token_service, - const std::string& account_id, + Fetcher(OAuth2AccessTokenManager* oauth2_access_token_manager, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, - const OAuth2TokenService::ScopeSet& scopes, + const ScopeSet& scopes, base::WeakPtr<RequestImpl> waiting_request); void Start(); void InformWaitingRequests(); @@ -174,15 +187,15 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { // and false otherwise. bool RetryIfPossible(const GoogleServiceAuthError& error); - // |oauth2_token_service_| remains valid for the life of this Fetcher, since - // this Fetcher is destructed in the dtor of the OAuth2TokenService or is - // scheduled for deletion at the end of OnGetTokenFailure/OnGetTokenSuccess - // (whichever comes first). - OAuth2TokenService* const oauth2_token_service_; + // |oauth2_access_token_manager_| remains valid for the life of this + // Fetcher, since this Fetcher is destructed in the dtor of the + // OAuth2AccessTokenManager or is scheduled for deletion at the end of + // OnGetTokenFailure/OnGetTokenSuccess (whichever comes first). + OAuth2AccessTokenManager* const oauth2_access_token_manager_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - const std::string account_id_; + const CoreAccountId account_id_; const ScopeSet scopes_; - std::vector<base::WeakPtr<RequestImpl> > waiting_requests_; + std::vector<base::WeakPtr<RequestImpl>> waiting_requests_; int retry_number_; base::OneShotTimer retry_timer_; @@ -202,32 +215,32 @@ class OAuth2TokenService::Fetcher : public OAuth2AccessTokenConsumer { }; // static -std::unique_ptr<OAuth2TokenService::Fetcher> -OAuth2TokenService::Fetcher::CreateAndStart( - OAuth2TokenService* oauth2_token_service, - const std::string& account_id, +std::unique_ptr<OAuth2AccessTokenManager::Fetcher> +OAuth2AccessTokenManager::Fetcher::CreateAndStart( + OAuth2AccessTokenManager* oauth2_access_token_manager, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, - const OAuth2TokenService::ScopeSet& scopes, + const ScopeSet& scopes, base::WeakPtr<RequestImpl> waiting_request) { - std::unique_ptr<OAuth2TokenService::Fetcher> fetcher = base::WrapUnique( - new Fetcher(oauth2_token_service, account_id, url_loader_factory, + std::unique_ptr<OAuth2AccessTokenManager::Fetcher> fetcher = base::WrapUnique( + new Fetcher(oauth2_access_token_manager, account_id, url_loader_factory, client_id, client_secret, scopes, waiting_request)); fetcher->Start(); return fetcher; } -OAuth2TokenService::Fetcher::Fetcher( - OAuth2TokenService* oauth2_token_service, - const std::string& account_id, +OAuth2AccessTokenManager::Fetcher::Fetcher( + OAuth2AccessTokenManager* oauth2_access_token_manager, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, - const OAuth2TokenService::ScopeSet& scopes, + const ScopeSet& scopes, base::WeakPtr<RequestImpl> waiting_request) - : oauth2_token_service_(oauth2_token_service), + : oauth2_access_token_manager_(oauth2_access_token_manager), url_loader_factory_(url_loader_factory), account_id_(account_id), scopes_(scopes), @@ -235,30 +248,29 @@ OAuth2TokenService::Fetcher::Fetcher( error_(GoogleServiceAuthError::SERVICE_UNAVAILABLE), client_id_(client_id), client_secret_(client_secret) { - DCHECK(oauth2_token_service_); + DCHECK(oauth2_access_token_manager_); waiting_requests_.push_back(waiting_request); } -OAuth2TokenService::Fetcher::~Fetcher() { +OAuth2AccessTokenManager::Fetcher::~Fetcher() { // Inform the waiting requests if it has not done so. if (waiting_requests_.size()) InformWaitingRequests(); } -void OAuth2TokenService::Fetcher::Start() { - fetcher_.reset(oauth2_token_service_->CreateAccessTokenFetcher( - account_id_, url_loader_factory_, this)); +void OAuth2AccessTokenManager::Fetcher::Start() { + fetcher_ = oauth2_access_token_manager_->CreateAccessTokenFetcher( + account_id_, url_loader_factory_, this); DCHECK(fetcher_); // Stop the timer before starting the fetch, as defense in depth against the // fetcher calling us back synchronously (which might restart the timer). retry_timer_.Stop(); - fetcher_->Start(client_id_, - client_secret_, + fetcher_->Start(client_id_, client_secret_, std::vector<std::string>(scopes_.begin(), scopes_.end())); } -void OAuth2TokenService::Fetcher::OnGetTokenSuccess( +void OAuth2AccessTokenManager::Fetcher::OnGetTokenSuccess( const OAuth2AccessTokenConsumer::TokenResponse& token_response) { fetcher_.reset(); @@ -266,41 +278,42 @@ void OAuth2TokenService::Fetcher::OnGetTokenSuccess( error_ = GoogleServiceAuthError::AuthErrorNone(); token_response_ = token_response; - // Subclasses may override this method to skip caching in some cases, but + // Delegates may override this method to skip caching in some cases, but // we still inform all waiting Consumers of a successful token fetch below. // This is intentional -- some consumers may need the token for cleanup // tasks. https://chromiumcodereview.appspot.com/11312124/ - oauth2_token_service_->RegisterTokenResponse(client_id_, account_id_, scopes_, - token_response_); + oauth2_access_token_manager_->RegisterTokenResponse(client_id_, account_id_, + scopes_, token_response_); InformWaitingRequestsAndDelete(); } -void OAuth2TokenService::Fetcher::OnGetTokenFailure( +void OAuth2AccessTokenManager::Fetcher::OnGetTokenFailure( const GoogleServiceAuthError& error) { fetcher_.reset(); if (ShouldRetry(error) && RetryIfPossible(error)) return; - UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetFailure", - error.state(), GoogleServiceAuthError::NUM_STATES); + UMA_HISTOGRAM_ENUMERATION("Signin.OAuth2TokenGetFailure", error.state(), + GoogleServiceAuthError::NUM_STATES); error_ = error; InformWaitingRequestsAndDelete(); } // Returns an exponential backoff in milliseconds including randomness less than // 1000 ms when retrying fetching an OAuth2 access token. -int64_t OAuth2TokenService::Fetcher::ComputeExponentialBackOffMilliseconds( +int64_t +OAuth2AccessTokenManager::Fetcher::ComputeExponentialBackOffMilliseconds( int retry_num) { - DCHECK(retry_num < max_fetch_retry_num_); + DCHECK(retry_num < oauth2_access_token_manager_->max_fetch_retry_num_); int exponential_backoff_in_seconds = 1 << retry_num; // Returns a backoff with randomness < 1000ms return (exponential_backoff_in_seconds + base::RandDouble()) * 1000; } -bool OAuth2TokenService::Fetcher::RetryIfPossible( +bool OAuth2AccessTokenManager::Fetcher::RetryIfPossible( const GoogleServiceAuthError& error) { - if (retry_number_ < max_fetch_retry_num_) { + if (retry_number_ < oauth2_access_token_manager_->max_fetch_retry_num_) { base::TimeDelta backoff = base::TimeDelta::FromMilliseconds( ComputeExponentialBackOffMilliseconds(retry_number_)); ++retry_number_; @@ -308,14 +321,14 @@ bool OAuth2TokenService::Fetcher::RetryIfPossible( GoogleServiceAuthError::NUM_STATES); retry_timer_.Stop(); retry_timer_.Start(FROM_HERE, backoff, this, - &OAuth2TokenService::Fetcher::Start); + &OAuth2AccessTokenManager::Fetcher::Start); return true; } return false; } -bool OAuth2TokenService::Fetcher::ShouldRetry( +bool OAuth2AccessTokenManager::Fetcher::ShouldRetry( const GoogleServiceAuthError& error) const { GoogleServiceAuthError::State error_state = error.state(); bool should_retry = @@ -325,11 +338,11 @@ bool OAuth2TokenService::Fetcher::ShouldRetry( // Give the delegate a chance to correct the error first. This is a best // effort only. - return should_retry || - oauth2_token_service_->GetDelegate()->FixRequestErrorIfPossible(); + return should_retry || oauth2_access_token_manager_->GetDelegate() + ->FixRequestErrorIfPossible(); } -void OAuth2TokenService::Fetcher::InformWaitingRequests() { +void OAuth2AccessTokenManager::Fetcher::InformWaitingRequests() { for (const base::WeakPtr<RequestImpl>& request : waiting_requests_) { if (request) request->InformConsumer(error_, token_response_); @@ -337,24 +350,24 @@ void OAuth2TokenService::Fetcher::InformWaitingRequests() { waiting_requests_.clear(); } -void OAuth2TokenService::Fetcher::InformWaitingRequestsAndDelete() { - // Deregisters itself from the service to prevent more waiting requests to +void OAuth2AccessTokenManager::Fetcher::InformWaitingRequestsAndDelete() { + // Deregisters itself from the manager to prevent more waiting requests to // be added when it calls back the waiting requests. - oauth2_token_service_->OnFetchComplete(this); + oauth2_access_token_manager_->OnFetchComplete(this); InformWaitingRequests(); base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); } -void OAuth2TokenService::Fetcher::AddWaitingRequest( - base::WeakPtr<OAuth2TokenService::RequestImpl> waiting_request) { +void OAuth2AccessTokenManager::Fetcher::AddWaitingRequest( + base::WeakPtr<RequestImpl> waiting_request) { waiting_requests_.push_back(waiting_request); } -size_t OAuth2TokenService::Fetcher::GetWaitingRequestCount() const { +size_t OAuth2AccessTokenManager::Fetcher::GetWaitingRequestCount() const { return waiting_requests_.size(); } -void OAuth2TokenService::Fetcher::Cancel() { +void OAuth2AccessTokenManager::Fetcher::Cancel() { if (fetcher_) fetcher_->CancelRequest(); fetcher_.reset(); @@ -363,125 +376,75 @@ void OAuth2TokenService::Fetcher::Cancel() { InformWaitingRequestsAndDelete(); } -const OAuth2TokenService::ScopeSet& OAuth2TokenService::Fetcher::GetScopeSet() - const { +const OAuth2AccessTokenManager::ScopeSet& +OAuth2AccessTokenManager::Fetcher::GetScopeSet() const { return scopes_; } -const std::string& OAuth2TokenService::Fetcher::GetClientId() const { +const std::string& OAuth2AccessTokenManager::Fetcher::GetClientId() const { return client_id_; } -const std::string& OAuth2TokenService::Fetcher::GetAccountId() const { +const CoreAccountId& OAuth2AccessTokenManager::Fetcher::GetAccountId() const { return account_id_; } -OAuth2TokenService::Request::Request() { -} - -OAuth2TokenService::Request::~Request() { -} - -OAuth2TokenService::Consumer::Consumer(const std::string& id) - : id_(id) {} - -OAuth2TokenService::Consumer::~Consumer() { -} - -OAuth2TokenService::OAuth2TokenService( - std::unique_ptr<OAuth2TokenServiceDelegate> delegate) - : delegate_(std::move(delegate)) { +OAuth2AccessTokenManager::OAuth2AccessTokenManager( + OAuth2AccessTokenManager::Delegate* delegate) + : delegate_(delegate) { DCHECK(delegate_); } -OAuth2TokenService::~OAuth2TokenService() { +OAuth2AccessTokenManager::~OAuth2AccessTokenManager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Release all the pending fetchers. pending_fetchers_.clear(); } -OAuth2TokenServiceDelegate* OAuth2TokenService::GetDelegate() { - return delegate_.get(); +OAuth2AccessTokenManager::Delegate* OAuth2AccessTokenManager::GetDelegate() { + return delegate_; } -const OAuth2TokenServiceDelegate* OAuth2TokenService::GetDelegate() const { - return delegate_.get(); +const OAuth2AccessTokenManager::Delegate* +OAuth2AccessTokenManager::GetDelegate() const { + return delegate_; } -void OAuth2TokenService::AddObserver(Observer* observer) { - delegate_->AddObserver(observer); -} - -void OAuth2TokenService::RemoveObserver(Observer* observer) { - delegate_->RemoveObserver(observer); -} - -void OAuth2TokenService::AddDiagnosticsObserver(DiagnosticsObserver* observer) { +void OAuth2AccessTokenManager::AddDiagnosticsObserver( + DiagnosticsObserver* observer) { diagnostics_observer_list_.AddObserver(observer); } -void OAuth2TokenService::RemoveDiagnosticsObserver( +void OAuth2AccessTokenManager::RemoveDiagnosticsObserver( DiagnosticsObserver* observer) { diagnostics_observer_list_.RemoveObserver(observer); } -std::unique_ptr<OAuth2TokenService::Request> -OAuth2TokenService::StartRequestForMultilogin( - const std::string& account_id, - OAuth2TokenService::Consumer* consumer) { - const std::string refresh_token = - delegate_->GetTokenForMultilogin(account_id); - if (refresh_token.empty()) { - // If we can't get refresh token from the delegate, start request for access - // token. - OAuth2TokenService::ScopeSet scopes; - scopes.insert(GaiaConstants::kOAuth1LoginScope); - return StartRequest(account_id, scopes, consumer); - } - std::unique_ptr<RequestImpl> request(new RequestImpl(account_id, consumer)); - // Create token response from token. Expiration time and id token do not - // matter and should not be accessed. - OAuth2AccessTokenConsumer::TokenResponse token_response( - refresh_token, base::Time(), std::string()); - // If we can get refresh token from the delegate, inform cosumer right away. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&RequestImpl::InformConsumer, request.get()->AsWeakPtr(), - GoogleServiceAuthError(GoogleServiceAuthError::NONE), - token_response)); - return std::move(request); -} - -std::unique_ptr<OAuth2TokenService::Request> OAuth2TokenService::StartRequest( - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes, - OAuth2TokenService::Consumer* consumer) { +std::unique_ptr<OAuth2AccessTokenManager::Request> +OAuth2AccessTokenManager::StartRequest(const CoreAccountId& account_id, + const ScopeSet& scopes, + Consumer* consumer) { return StartRequestForClientWithContext( account_id, delegate_->GetURLLoaderFactory(), GaiaUrls::GetInstance()->oauth2_chrome_client_id(), GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), scopes, consumer); } -std::unique_ptr<OAuth2TokenService::Request> -OAuth2TokenService::StartRequestForClient( - const std::string& account_id, +std::unique_ptr<OAuth2AccessTokenManager::Request> +OAuth2AccessTokenManager::StartRequestForClient( + const CoreAccountId& account_id, const std::string& client_id, const std::string& client_secret, - const OAuth2TokenService::ScopeSet& scopes, - OAuth2TokenService::Consumer* consumer) { - return StartRequestForClientWithContext(account_id, GetURLLoaderFactory(), - client_id, client_secret, scopes, - consumer); -} - -scoped_refptr<network::SharedURLLoaderFactory> -OAuth2TokenService::GetURLLoaderFactory() const { - return delegate_->GetURLLoaderFactory(); + const ScopeSet& scopes, + Consumer* consumer) { + return StartRequestForClientWithContext( + account_id, delegate_->GetURLLoaderFactory(), client_id, client_secret, + scopes, consumer); } -std::unique_ptr<OAuth2TokenService::Request> -OAuth2TokenService::StartRequestWithContext( - const std::string& account_id, +std::unique_ptr<OAuth2AccessTokenManager::Request> +OAuth2AccessTokenManager::StartRequestWithContext( + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const ScopeSet& scopes, Consumer* consumer) { @@ -491,9 +454,153 @@ OAuth2TokenService::StartRequestWithContext( GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), scopes, consumer); } -std::unique_ptr<OAuth2TokenService::Request> -OAuth2TokenService::StartRequestForClientWithContext( - const std::string& account_id, +void OAuth2AccessTokenManager::FetchOAuth2Token( + RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const std::string& client_id, + const std::string& client_secret, + const ScopeSet& scopes) { + // If there is already a pending fetcher for |scopes| and |account_id|, + // simply register this |request| for those results rather than starting + // a new fetcher. + RequestParameters request_parameters = + RequestParameters(client_id, account_id, scopes); + auto iter = pending_fetchers_.find(request_parameters); + if (iter != pending_fetchers_.end()) { + iter->second->AddWaitingRequest(request->AsWeakPtr()); + return; + } + + pending_fetchers_[request_parameters] = + Fetcher::CreateAndStart(this, account_id, url_loader_factory, client_id, + client_secret, scopes, request->AsWeakPtr()); +} + +void OAuth2AccessTokenManager::RegisterTokenResponse( + const std::string& client_id, + const CoreAccountId& account_id, + const ScopeSet& scopes, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + token_cache_[RequestParameters(client_id, account_id, scopes)] = + token_response; +} + +const OAuth2AccessTokenConsumer::TokenResponse* +OAuth2AccessTokenManager::GetCachedTokenResponse( + const RequestParameters& request_parameters) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + TokenCache::iterator token_iterator = token_cache_.find(request_parameters); + if (token_iterator == token_cache_.end()) + return nullptr; + if (token_iterator->second.expiration_time <= base::Time::Now()) { + token_cache_.erase(token_iterator); + return nullptr; + } + return &token_iterator->second; +} + +void OAuth2AccessTokenManager::ClearCache() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + for (const auto& entry : token_cache_) { + for (auto& observer : diagnostics_observer_list_) + observer.OnAccessTokenRemoved(entry.first.account_id, entry.first.scopes); + } + + token_cache_.clear(); +} + +void OAuth2AccessTokenManager::ClearCacheForAccount( + const CoreAccountId& account_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + for (TokenCache::iterator iter = token_cache_.begin(); + iter != token_cache_.end(); + /* iter incremented in body */) { + if (iter->first.account_id == account_id) { + for (auto& observer : diagnostics_observer_list_) + observer.OnAccessTokenRemoved(account_id, iter->first.scopes); + token_cache_.erase(iter++); + } else { + ++iter; + } + } +} + +void OAuth2AccessTokenManager::CancelAllRequests() { + std::vector<Fetcher*> fetchers_to_cancel; + for (const auto& pending_fetcher : pending_fetchers_) + fetchers_to_cancel.push_back(pending_fetcher.second.get()); + CancelFetchers(fetchers_to_cancel); +} + +void OAuth2AccessTokenManager::CancelRequestsForAccount( + const CoreAccountId& account_id) { + std::vector<Fetcher*> fetchers_to_cancel; + for (const auto& pending_fetcher : pending_fetchers_) { + if (pending_fetcher.first.account_id == account_id) + fetchers_to_cancel.push_back(pending_fetcher.second.get()); + } + CancelFetchers(fetchers_to_cancel); +} + +void OAuth2AccessTokenManager::InvalidateAccessToken( + const CoreAccountId& account_id, + const ScopeSet& scopes, + const std::string& access_token) { + InvalidateAccessTokenImpl(account_id, + GaiaUrls::GetInstance()->oauth2_chrome_client_id(), + scopes, access_token); +} + +void OAuth2AccessTokenManager::InvalidateAccessTokenImpl( + const CoreAccountId& account_id, + const std::string& client_id, + const ScopeSet& scopes, + const std::string& access_token) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RemoveCachedTokenResponse(RequestParameters(client_id, account_id, scopes), + access_token); + delegate_->OnAccessTokenInvalidated(account_id, client_id, scopes, + access_token); +} + +void OAuth2AccessTokenManager:: + set_max_authorization_token_fetch_retries_for_testing(int max_retries) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + max_fetch_retry_num_ = max_retries; +} + +size_t OAuth2AccessTokenManager::GetNumPendingRequestsForTesting( + const std::string& client_id, + const CoreAccountId& account_id, + const ScopeSet& scopes) const { + auto iter = + pending_fetchers_.find(RequestParameters(client_id, account_id, scopes)); + return iter == pending_fetchers_.end() + ? 0 + : iter->second->GetWaitingRequestCount(); +} + +const base::ObserverList<OAuth2AccessTokenManager::DiagnosticsObserver, + true>::Unchecked& +OAuth2AccessTokenManager::GetDiagnosticsObserversForTesting() { + return diagnostics_observer_list_; +} + +std::unique_ptr<OAuth2AccessTokenFetcher> +OAuth2AccessTokenManager::CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer) { + return delegate_->CreateAccessTokenFetcher(account_id, url_loader_factory, + consumer); +} + +std::unique_ptr<OAuth2AccessTokenManager::Request> +OAuth2AccessTokenManager::StartRequestForClientWithContext( + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, @@ -505,7 +612,7 @@ OAuth2TokenService::StartRequestForClientWithContext( for (auto& observer : diagnostics_observer_list_) observer.OnAccessTokenRequested(account_id, consumer->id(), scopes); - if (!RefreshTokenIsAvailable(account_id)) { + if (!delegate_->HasRefreshToken(account_id)) { GoogleServiceAuthError error(GoogleServiceAuthError::USER_NOT_SIGNED_UP); for (auto& observer : diagnostics_observer_list_) { @@ -520,54 +627,27 @@ OAuth2TokenService::StartRequestForClientWithContext( return std::move(request); } - RequestParameters request_parameters(client_id, - account_id, - scopes); + RequestParameters request_parameters(client_id, account_id, scopes); const OAuth2AccessTokenConsumer::TokenResponse* token_response = GetCachedTokenResponse(request_parameters); if (token_response && token_response->access_token.length()) { InformConsumerWithCachedTokenResponse(token_response, request.get(), request_parameters); + } else if (delegate_->HandleAccessTokenFetch(request.get(), account_id, + url_loader_factory, client_id, + client_secret, scopes)) { + // The delegate handling the fetch request means that we *don't* perform a + // fetch. } else { + // The token isn't in the cache and the delegate isn't fetching it: fetch it + // ourselves! FetchOAuth2Token(request.get(), account_id, url_loader_factory, client_id, client_secret, scopes); } return std::move(request); } -void OAuth2TokenService::FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes) { - // If there is already a pending fetcher for |scopes| and |account_id|, - // simply register this |request| for those results rather than starting - // a new fetcher. - RequestParameters request_parameters = RequestParameters(client_id, - account_id, - scopes); - auto iter = pending_fetchers_.find(request_parameters); - if (iter != pending_fetchers_.end()) { - iter->second->AddWaitingRequest(request->AsWeakPtr()); - return; - } - - pending_fetchers_[request_parameters] = - Fetcher::CreateAndStart(this, account_id, url_loader_factory, client_id, - client_secret, scopes, request->AsWeakPtr()); -} - -OAuth2AccessTokenFetcher* OAuth2TokenService::CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer) { - return delegate_->CreateAccessTokenFetcher(account_id, url_loader_factory, - consumer); -} - -void OAuth2TokenService::InformConsumerWithCachedTokenResponse( +void OAuth2AccessTokenManager::InformConsumerWithCachedTokenResponse( const OAuth2AccessTokenConsumer::TokenResponse* cache_token_response, RequestImpl* request, const RequestParameters& request_parameters) { @@ -585,86 +665,41 @@ void OAuth2TokenService::InformConsumerWithCachedTokenResponse( *cache_token_response)); } -std::vector<std::string> OAuth2TokenService::GetAccounts() const { - return delegate_->GetAccounts(); -} - -bool OAuth2TokenService::RefreshTokenIsAvailable( - const std::string& account_id) const { - return delegate_->RefreshTokenIsAvailable(account_id); -} - -bool OAuth2TokenService::RefreshTokenHasError( - const std::string& account_id) const { - return GetAuthError(account_id) != GoogleServiceAuthError::AuthErrorNone(); -} - -GoogleServiceAuthError OAuth2TokenService::GetAuthError( - const std::string& account_id) const { - GoogleServiceAuthError error = delegate_->GetAuthError(account_id); - DCHECK(!error.IsTransientError()); - return error; -} - -void OAuth2TokenService::InvalidateAccessToken( - const std::string& account_id, - const ScopeSet& scopes, - const std::string& access_token) { - InvalidateAccessTokenImpl(account_id, - GaiaUrls::GetInstance()->oauth2_chrome_client_id(), - scopes, access_token); -} - -void OAuth2TokenService::InvalidateTokenForMultilogin( - const std::string& failed_account, - const std::string& token) { - OAuth2TokenService::ScopeSet scopes; - scopes.insert(GaiaConstants::kOAuth1LoginScope); - // Remove from cache. This will have no effect on desktop since token is a - // refresh token and is not in cache. - InvalidateAccessToken(failed_account, scopes, token); - // For desktop refresh tokens can be invalidated directly in delegate. This - // will have no effect on mobile. - delegate_->InvalidateTokenForMultilogin(failed_account); -} - -void OAuth2TokenService::InvalidateAccessTokenForClient( - const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) { - InvalidateAccessTokenImpl(account_id, client_id, scopes, access_token); -} - -void OAuth2TokenService::InvalidateAccessTokenImpl( - const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) { +bool OAuth2AccessTokenManager::RemoveCachedTokenResponse( + const RequestParameters& request_parameters, + const std::string& token_to_remove) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - RemoveCachedTokenResponse(RequestParameters(client_id, account_id, scopes), - access_token); - delegate_->InvalidateAccessToken(account_id, client_id, scopes, access_token); + TokenCache::iterator token_iterator = token_cache_.find(request_parameters); + if (token_iterator != token_cache_.end() && + token_iterator->second.access_token == token_to_remove) { + for (auto& observer : diagnostics_observer_list_) { + observer.OnAccessTokenRemoved(request_parameters.account_id, + request_parameters.scopes); + } + token_cache_.erase(token_iterator); + return true; + } + return false; } -void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { +void OAuth2AccessTokenManager::OnFetchComplete( + OAuth2AccessTokenManager::Fetcher* fetcher) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Update the auth error state so auth errors are appropriately communicated - // to the user. - UpdateAuthError(fetcher->GetAccountId(), fetcher->error()); + delegate_->OnAccessTokenFetched(fetcher->GetAccountId(), fetcher->error()); - // Note |fetcher| is recorded in |pending_fetcher_| mapped to its refresh - // token and scope set. This is guaranteed as follows; here a Fetcher is said - // to be uncompleted if it has not finished calling back - // OAuth2TokenService::OnFetchComplete(). + // Note |fetcher| is recorded in |pending_fetcher_| mapped from its + // combination of client ID, account ID, and scope set. This is guaranteed as + // follows; here a Fetcher is said to be uncompleted if it has not finished + // calling back + // OAuth2AccessTokenManager::OnFetchComplete(). // - // (1) All the live Fetchers are created by this service. + // (1) All the live Fetchers are created by this manager. // This is because (1) all the live Fetchers are created by a live - // service, as all the fetchers created by a service are destructed in the - // service's dtor. + // manager, as all the fetchers created by a manager are destructed in the + // manager's dtor. // - // (2) All the uncompleted Fetchers created by this service are recorded in + // (2) All the uncompleted Fetchers created by this manager are recorded in // |pending_fetchers_|. // This is because (1) all the created Fetchers are added to // |pending_fetchers_| (in method StartRequest()) and (2) method @@ -672,17 +707,17 @@ void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { // |pending_fetchers_|. Note no Fetcher is erased in method // StartRequest(). // - // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped to its - // refresh token and ScopeSet. This is guaranteed by Fetcher creation in - // method StartRequest(). + // (3) Each of the Fetchers recorded in |pending_fetchers_| is mapped from + // its combination of client ID, account ID, and scope set. This is + // guaranteed by Fetcher creation in method StartRequest(). // // When this method is called, |fetcher| is alive and uncompleted. - // By (1), |fetcher| is created by this service. + // By (1), |fetcher| is created by this manager. // Then by (2), |fetcher| is recorded in |pending_fetchers_|. - // Then by (3), |fetcher_| is mapped to its refresh token and ScopeSet. - RequestParameters request_param(fetcher->GetClientId(), - fetcher->GetAccountId(), - fetcher->GetScopeSet()); + // Then by (3), |fetcher_| is mapped from its combination of client ID, + // account ID, and scope set. + RequestParameters request_param( + fetcher->GetClientId(), fetcher->GetAccountId(), fetcher->GetScopeSet()); const OAuth2AccessTokenConsumer::TokenResponse* entry = GetCachedTokenResponse(request_param); @@ -705,112 +740,8 @@ void OAuth2TokenService::OnFetchComplete(Fetcher* fetcher) { pending_fetchers_.erase(iter); } -const OAuth2AccessTokenConsumer::TokenResponse* -OAuth2TokenService::GetCachedTokenResponse( - const RequestParameters& request_parameters) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TokenCache::iterator token_iterator = token_cache_.find(request_parameters); - if (token_iterator == token_cache_.end()) - return nullptr; - if (token_iterator->second.expiration_time <= base::Time::Now()) { - token_cache_.erase(token_iterator); - return nullptr; - } - return &token_iterator->second; -} - -bool OAuth2TokenService::RemoveCachedTokenResponse( - const RequestParameters& request_parameters, - const std::string& token_to_remove) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - TokenCache::iterator token_iterator = token_cache_.find(request_parameters); - if (token_iterator != token_cache_.end() && - token_iterator->second.access_token == token_to_remove) { - for (auto& observer : diagnostics_observer_list_) { - observer.OnAccessTokenRemoved(request_parameters.account_id, - request_parameters.scopes); - } - token_cache_.erase(token_iterator); - return true; - } - return false; -} -void OAuth2TokenService::UpdateAuthError(const std::string& account_id, - const GoogleServiceAuthError& error) { - delegate_->UpdateAuthError(account_id, error); -} - -void OAuth2TokenService::RegisterTokenResponse( - const std::string& client_id, - const std::string& account_id, - const ScopeSet& scopes, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - token_cache_[RequestParameters(client_id, account_id, scopes)] = - token_response; -} - -void OAuth2TokenService::ClearCache() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (const auto& entry : token_cache_) { - for (auto& observer : diagnostics_observer_list_) - observer.OnAccessTokenRemoved(entry.first.account_id, entry.first.scopes); - } - - token_cache_.clear(); -} - -void OAuth2TokenService::ClearCacheForAccount(const std::string& account_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (TokenCache::iterator iter = token_cache_.begin(); - iter != token_cache_.end(); - /* iter incremented in body */) { - if (iter->first.account_id == account_id) { - for (auto& observer : diagnostics_observer_list_) - observer.OnAccessTokenRemoved(account_id, iter->first.scopes); - token_cache_.erase(iter++); - } else { - ++iter; - } - } -} - -void OAuth2TokenService::CancelAllRequests() { - std::vector<Fetcher*> fetchers_to_cancel; - for (const auto& pending_fetcher : pending_fetchers_) - fetchers_to_cancel.push_back(pending_fetcher.second.get()); - CancelFetchers(fetchers_to_cancel); -} - -void OAuth2TokenService::CancelRequestsForAccount( - const std::string& account_id) { - std::vector<Fetcher*> fetchers_to_cancel; - for (const auto& pending_fetcher : pending_fetchers_) { - if (pending_fetcher.first.account_id == account_id) - fetchers_to_cancel.push_back(pending_fetcher.second.get()); - } - CancelFetchers(fetchers_to_cancel); -} - -void OAuth2TokenService::CancelFetchers( +void OAuth2AccessTokenManager::CancelFetchers( std::vector<Fetcher*> fetchers_to_cancel) { for (Fetcher* pending_fetcher : fetchers_to_cancel) pending_fetcher->Cancel(); } - -void OAuth2TokenService::set_max_authorization_token_fetch_retries_for_testing( - int max_retries) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - max_fetch_retry_num_ = max_retries; -} - -size_t OAuth2TokenService::GetNumPendingRequestsForTesting( - const std::string& client_id, - const std::string& account_id, - const ScopeSet& scopes) const { - auto iter = pending_fetchers_.find( - OAuth2TokenService::RequestParameters(client_id, account_id, scopes)); - return iter == pending_fetchers_.end() ? - 0 : iter->second->GetWaitingRequestCount(); -} diff --git a/chromium/google_apis/gaia/oauth2_token_service.h b/chromium/google_apis/gaia/oauth2_access_token_manager.h index 44ac84efb83..a7454adcd32 100644 --- a/chromium/google_apis/gaia/oauth2_token_service.h +++ b/chromium/google_apis/gaia/oauth2_access_token_manager.h @@ -1,75 +1,83 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_ -#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_ +#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_H_ +#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_H_ -#include <stddef.h> - -#include <map> -#include <memory> -#include <set> -#include <string> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/sequence_checker.h" #include "base/time/time.h" #include "google_apis/gaia/core_account_id.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_access_token_consumer.h" -#include "google_apis/gaia/oauth2_access_token_fetcher.h" - -namespace network { -class SharedURLLoaderFactory; -} namespace network { class SharedURLLoaderFactory; } -class GoogleServiceAuthError; class OAuth2AccessTokenFetcher; -class OAuth2TokenServiceDelegate; - -// Abstract base class for a service that fetches and caches OAuth2 access -// tokens. Concrete subclasses should implement GetRefreshToken to return -// the appropriate refresh token. Derived services might maintain refresh tokens -// for multiple accounts. -// -// All calls are expected from the UI thread. -// -// To use this service, call StartRequest() with a given set of scopes and a -// consumer of the request results. The consumer is required to outlive the -// request. The request can be deleted. The consumer may be called back -// asynchronously with the fetch results. -// -// - If the consumer is not called back before the request is deleted, it will -// never be called back. -// Note in this case, the actual network requests are not canceled and the -// cache will be populated with the fetched results; it is just the consumer -// callback that is aborted. -// -// - Otherwise the consumer will be called back with the request and the fetch -// results. -// -// The caller of StartRequest() owns the returned request and is responsible to -// delete the request even once the callback has been invoked. -class OAuth2TokenService { + +// Class that manages requests for OAuth2 access tokens. +class OAuth2AccessTokenManager { public: // A set of scopes in OAuth2 authentication. typedef std::set<std::string> ScopeSet; + class RequestImpl; + + class Delegate { + public: + Delegate(); + virtual ~Delegate(); + + // Creates and returns an OAuth2AccessTokenFetcher. + virtual std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer) WARN_UNUSED_RESULT = 0; + + // Returns |true| if a refresh token is available for |account_id|, and + // |false| otherwise. + virtual bool HasRefreshToken(const CoreAccountId& account_id) const = 0; + + // Attempts to fix the error if possible. Returns true if the error was + // fixed and false otherwise. Default implementation returns false. + virtual bool FixRequestErrorIfPossible(); + + // Returns a SharedURLLoaderFactory object that will be used as part of + // fetching access tokens. Default implementation returns nullptr. + virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() + const; + + // Gives the delegate a chance to handle the access token request before + // the manager sends the request over the network. Returns true if the + // request was handled by the delegate (in which case the manager will not + // send the request) and false otherwise. + virtual bool HandleAccessTokenFetch( + RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const std::string& client_id, + const std::string& client_secret, + const ScopeSet& scopes); + + // Called when an access token is invalidated. + virtual void OnAccessTokenInvalidated(const CoreAccountId& account_id, + const std::string& client_id, + const std::set<std::string>& scopes, + const std::string& access_token) {} + + // Called when an access token is fetched. + virtual void OnAccessTokenFetched(const CoreAccountId& account_id, + const GoogleServiceAuthError& error) {} + }; // Class representing a request that fetches an OAuth2 access token. class Request { public: virtual ~Request(); - virtual std::string GetAccountId() const = 0; + virtual CoreAccountId GetAccountId() const = 0; + protected: Request(); }; @@ -90,39 +98,37 @@ class OAuth2TokenService { const OAuth2AccessTokenConsumer::TokenResponse& token_response) = 0; virtual void OnGetTokenFailure(const Request* request, const GoogleServiceAuthError& error) = 0; + private: std::string id_; }; - // Classes that want to listen for refresh token availability should - // implement this interface and register with the AddObserver() call. - class Observer { + // Implements a cancelable |OAuth2AccessTokenManager::Request|, which should + // be operated on the UI thread. + // TODO(davidroche): move this out of header file. + class RequestImpl : public base::SupportsWeakPtr<RequestImpl>, + public Request { public: - // Called whenever a new login-scoped refresh token is available for - // account |account_id|. Once available, access tokens can be retrieved for - // this account. This is called during initial startup for each token - // loaded (and any time later when, e.g., credentials change). When called, - // any pending token request is cancelled and needs to be retried. Such a - // pending request can easily occur on Android, where refresh tokens are - // held by the OS and are thus often available on startup even before - // OnRefreshTokenAvailable() is called. - virtual void OnRefreshTokenAvailable(const std::string& account_id) {} - // Called whenever the login-scoped refresh token becomes unavailable for - // account |account_id|. - virtual void OnRefreshTokenRevoked(const std::string& account_id) {} - // Called after all refresh tokens are loaded during OAuth2TokenService - // startup. - virtual void OnRefreshTokensLoaded() {} - // Sent after a batch of refresh token changes is done. - virtual void OnEndBatchChanges() {} - // Called when the authentication error state for |account_id| has changed. - // Note: It is always called after |OnRefreshTokenAvailable| when refresh - // token is updated. It is not called when the refresh token is revoked. - virtual void OnAuthErrorChanged(const std::string& account_id, - const GoogleServiceAuthError& auth_error) {} + // |consumer| is required to outlive this. + RequestImpl(const CoreAccountId& account_id, Consumer* consumer); + ~RequestImpl() override; - protected: - virtual ~Observer() {} + // Overridden from Request: + CoreAccountId GetAccountId() const override; + + std::string GetConsumerId() const; + + // Informs |consumer_| that this request is completed. + void InformConsumer( + const GoogleServiceAuthError& error, + const OAuth2AccessTokenConsumer::TokenResponse& token_response); + + private: + const CoreAccountId account_id_; + // |consumer_| to call back when this request completes. + Consumer* const consumer_; + + SEQUENCE_CHECKER(sequence_checker_); }; // Classes that want to monitor status of access token and access token @@ -134,6 +140,7 @@ class OAuth2TokenService { virtual void OnAccessTokenRequested(const CoreAccountId& account_id, const std::string& consumer_id, const ScopeSet& scopes) {} + // Called when access token fetching finished successfully or // unsuccessfully. |expiration_time| are only valid with // successful completion. @@ -142,33 +149,39 @@ class OAuth2TokenService { const ScopeSet& scopes, GoogleServiceAuthError error, base::Time expiration_time) {} + // Called when an access token was removed. virtual void OnAccessTokenRemoved(const CoreAccountId& account_id, const ScopeSet& scopes) {} + }; - // Caled when a new refresh token is available. Contains diagnostic - // information about the source of the update credentials operation. - virtual void OnRefreshTokenAvailableFromSource( - const CoreAccountId& account_id, - bool is_refresh_token_valid, - const std::string& source) {} + // The parameters used to fetch an OAuth2 access token. + struct RequestParameters { + RequestParameters(const std::string& client_id, + const CoreAccountId& account_id, + const ScopeSet& scopes); + RequestParameters(const RequestParameters& other); + ~RequestParameters(); + bool operator<(const RequestParameters& params) const; - // Called when a refreh token is revoked. Contains diagnostic information - // about the source that initiated the revokation operation. - virtual void OnRefreshTokenRevokedFromSource( - const CoreAccountId& account_id, - const std::string& source) {} + // OAuth2 client id. + std::string client_id; + // Account id for which the request is made. + CoreAccountId account_id; + // URL scopes for the requested access token. + ScopeSet scopes; }; + typedef std::map<RequestParameters, OAuth2AccessTokenConsumer::TokenResponse> + TokenCache; - explicit OAuth2TokenService( - std::unique_ptr<OAuth2TokenServiceDelegate> delegate); - virtual ~OAuth2TokenService(); + explicit OAuth2AccessTokenManager( + OAuth2AccessTokenManager::Delegate* delegate); + virtual ~OAuth2AccessTokenManager(); - // Add or remove observers of this token service. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); + OAuth2AccessTokenManager::Delegate* GetDelegate(); + const OAuth2AccessTokenManager::Delegate* GetDelegate() const; - // Add or remove observers of this token service. + // Add or remove observers of this token manager. void AddDiagnosticsObserver(DiagnosticsObserver* observer); void RemoveDiagnosticsObserver(DiagnosticsObserver* observer); @@ -178,23 +191,16 @@ class OAuth2TokenService { // |account_id|. The caller owns the returned Request. // |scopes| is the set of scopes to get an access token for, |consumer| is // the object that will be called back with results if the returned request - // is not deleted. Virtual for mocking. - virtual std::unique_ptr<Request> StartRequest(const std::string& account_id, - const ScopeSet& scopes, - Consumer* consumer); - - // Try to get refresh token from delegate. If it is accessible (i.e. not - // empty), return it directly, otherwise start request to get access token. - // Used for getting tokens to send to Gaia Multilogin endpoint. - std::unique_ptr<OAuth2TokenService::Request> StartRequestForMultilogin( - const std::string& account_id, - OAuth2TokenService::Consumer* consumer); + // is not deleted. + std::unique_ptr<Request> StartRequest(const CoreAccountId& account_id, + const ScopeSet& scopes, + Consumer* consumer); // This method does the same as |StartRequest| except it uses |client_id| and // |client_secret| to identify OAuth client app instead of using // Chrome's default values. std::unique_ptr<Request> StartRequestForClient( - const std::string& account_id, + const CoreAccountId& account_id, const std::string& client_id, const std::string& client_secret, const ScopeSet& scopes, @@ -202,185 +208,105 @@ class OAuth2TokenService { // This method does the same as |StartRequest| except it uses the // URLLoaderfactory given by |url_loader_factory| instead of using the one - // returned by |GetURLLoaderFactory| implemented by derived classes. + // returned by |GetURLLoaderFactory| implemented by the delegate. std::unique_ptr<Request> StartRequestWithContext( - const std::string& account_id, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const ScopeSet& scopes, Consumer* consumer); - // Lists account IDs of all accounts with a refresh token maintained by this - // instance. - // Note: For each account returned by |GetAccounts|, |RefreshTokenIsAvailable| - // will return true. - // Note: If tokens have not been fully loaded yet, an empty list is returned. - std::vector<std::string> GetAccounts() const; - - // Returns true if a refresh token exists for |account_id|. If false, calls to - // |StartRequest| will result in a Consumer::OnGetTokenFailure callback. - // Note: This will return |true| if and only if |account_id| is contained in - // the list returned by |GetAccounts|. - bool RefreshTokenIsAvailable(const std::string& account_id) const; - - // Returns true if a refresh token exists for |account_id| and it is in a - // persistent error state. - bool RefreshTokenHasError(const std::string& account_id) const; - - // Returns the auth error associated with |account_id|. Only persistent errors - // will be returned. - GoogleServiceAuthError GetAuthError(const std::string& account_id) const; - - // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as - // invalid. This should be done if the token was received from this class, - // but was not accepted by the server (e.g., the server returned - // 401 Unauthorized). The token will be removed from the cache for the given - // scopes. - void InvalidateAccessToken(const std::string& account_id, - const ScopeSet& scopes, - const std::string& access_token); - - // Like |InvalidateToken| except is uses |client_id| to identity OAuth2 client - // app that issued the request instead of Chrome's default values. - void InvalidateAccessTokenForClient(const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token); - - // Removes token from cache (if it is cached) and calls - // InvalidateTokenForMultilogin method of the delegate. This should be done if - // the token was received from this class, but was not accepted by the server - // (e.g., the server returned 401 Unauthorized). - virtual void InvalidateTokenForMultilogin(const std::string& failed_account, - const std::string& token); - - void set_max_authorization_token_fetch_retries_for_testing(int max_retries); - // Returns the current number of pending fetchers matching given params. - size_t GetNumPendingRequestsForTesting( + // Fetches an OAuth token for the specified client/scopes. Virtual so it can + // be overridden for tests. + // TODO(https://crbug.com/967598): Move this to protected. + virtual void FetchOAuth2Token( + RequestImpl* request, + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, - const std::string& account_id, - const ScopeSet& scopes) const; - - OAuth2TokenServiceDelegate* GetDelegate(); - const OAuth2TokenServiceDelegate* GetDelegate() const; - - protected: - // Implements a cancelable |OAuth2TokenService::Request|, which should be - // operated on the UI thread. - // TODO(davidroche): move this out of header file. - class RequestImpl : public base::SupportsWeakPtr<RequestImpl>, - public Request { - public: - // |consumer| is required to outlive this. - RequestImpl(const std::string& account_id, Consumer* consumer); - ~RequestImpl() override; - - // Overridden from Request: - std::string GetAccountId() const override; - - std::string GetConsumerId() const; - - // Informs |consumer_| that this request is completed. - void InformConsumer( - const GoogleServiceAuthError& error, - const OAuth2AccessTokenConsumer::TokenResponse& token_response); - - private: - // |consumer_| to call back when this request completes. - const std::string account_id_; - Consumer* const consumer_; - - SEQUENCE_CHECKER(sequence_checker_); - }; - - // Implement it in delegates if they want to report errors to the user. - void UpdateAuthError(const std::string& account_id, - const GoogleServiceAuthError& error); + const std::string& client_secret, + const ScopeSet& scopes); // Add a new entry to the cache. - // Subclasses can override if there are implementation-specific reasons - // that an access token should ever not be cached. - virtual void RegisterTokenResponse( + void RegisterTokenResponse( const std::string& client_id, - const std::string& account_id, + const CoreAccountId& account_id, const ScopeSet& scopes, const OAuth2AccessTokenConsumer::TokenResponse& token_response); + // Returns a currently valid OAuth2 access token for the given set of scopes, + // or NULL if none have been cached. Note the user of this method should + // ensure no entry with the same |client_scopes| is added before the usage of + // the returned entry is done. + const OAuth2AccessTokenConsumer::TokenResponse* GetCachedTokenResponse( + const RequestParameters& client_scopes); + // Clears the internal token cache. void ClearCache(); // Clears all of the tokens belonging to |account_id| from the internal token // cache. It does not matter what other parameters, like |client_id| were // used to request the tokens. - void ClearCacheForAccount(const std::string& account_id); + void ClearCacheForAccount(const CoreAccountId& account_id); // Cancels all requests that are currently in progress. Virtual so it can be // overridden for tests. + // TODO(https://crbug.com/967598): Move this to protected. virtual void CancelAllRequests(); // Cancels all requests related to a given |account_id|. Virtual so it can be // overridden for tests. - virtual void CancelRequestsForAccount(const std::string& account_id); + // TODO(https://crbug.com/967598): Move this to protected. + virtual void CancelRequestsForAccount(const CoreAccountId& account_id); - // Fetches an OAuth token for the specified client/scopes. Virtual so it can - // be overridden for tests and for platform-specific behavior. - virtual void FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes); - - // Create an access token fetcher for the given account id. - OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer); + // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as + // invalid. This should be done if the token was received from this class, + // but was not accepted by the server (e.g., the server returned + // 401 Unauthorized). The token will be removed from the cache for the given + // scopes. + void InvalidateAccessToken(const CoreAccountId& account_id, + const ScopeSet& scopes, + const std::string& access_token); // Invalidates the |access_token| issued for |account_id|, |client_id| and - // |scopes|. Virtual so it can be overriden for tests and for platform- - // specifc behavior. - virtual void InvalidateAccessTokenImpl(const std::string& account_id, + // |scopes|. Virtual so it can be overridden for tests. + // TODO(https://crbug.com/967598): Move this to protected. + virtual void InvalidateAccessTokenImpl(const CoreAccountId& account_id, const std::string& client_id, const ScopeSet& scopes, const std::string& access_token); + void set_max_authorization_token_fetch_retries_for_testing(int max_retries); + + // Returns the current number of pending fetchers matching given params. + size_t GetNumPendingRequestsForTesting(const std::string& client_id, + const CoreAccountId& account_id, + const ScopeSet& scopes) const; + + // Returns a list of DiagnosticsObservers. const base::ObserverList<DiagnosticsObserver, true>::Unchecked& - GetDiagnicsObservers() { - return diagnostics_observer_list_; - } + GetDiagnosticsObserversForTesting(); private: + // TODO(https://crbug.com/967598): Determine whether ProfileOAuth2TokenService + // needs to have API to access to token_cache(). + friend class ProfileOAuth2TokenService; + class Fetcher; friend class Fetcher; - friend class OAuth2TokenServiceDelegate; - // The parameters used to fetch an OAuth2 access token. - struct RequestParameters { - RequestParameters(const std::string& client_id, - const std::string& account_id, - const ScopeSet& scopes); - RequestParameters(const RequestParameters& other); - ~RequestParameters(); - bool operator<(const RequestParameters& params) const; + TokenCache& token_cache() { return token_cache_; } - // OAuth2 client id. - std::string client_id; - // Account id for which the request is made. - std::string account_id; - // URL scopes for the requested access token. - ScopeSet scopes; - }; - - // Provide a URLLoaderFactory used for fetching access tokens with the - // |StartRequest| method. - scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() const; + // Create an access token fetcher for the given account id. + std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer); // This method does the same as |StartRequestWithContext| except it // uses |client_id| and |client_secret| to identify OAuth // client app instead of using Chrome's default values. std::unique_ptr<Request> StartRequestForClientWithContext( - const std::string& account_id, + const CoreAccountId& account_id, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const std::string& client_id, const std::string& client_secret, @@ -393,13 +319,6 @@ class OAuth2TokenService { RequestImpl* request, const RequestParameters& client_scopes); - // Returns a currently valid OAuth2 access token for the given set of scopes, - // or NULL if none have been cached. Note the user of this method should - // ensure no entry with the same |client_scopes| is added before the usage of - // the returned entry is done. - const OAuth2AccessTokenConsumer::TokenResponse* GetCachedTokenResponse( - const RequestParameters& client_scopes); - // Removes an access token for the given set of scopes from the cache. // Returns true if the entry was removed, otherwise false. bool RemoveCachedTokenResponse(const RequestParameters& client_scopes, @@ -412,34 +331,20 @@ class OAuth2TokenService { void CancelFetchers(std::vector<Fetcher*> fetchers_to_cancel); // The cache of currently valid tokens. - typedef std::map<RequestParameters, OAuth2AccessTokenConsumer::TokenResponse> - TokenCache; TokenCache token_cache_; - - std::unique_ptr<OAuth2TokenServiceDelegate> delegate_; - - // A map from fetch parameters to a fetcher that is fetching an OAuth2 access - // token using these parameters. - std::map<RequestParameters, std::unique_ptr<Fetcher>> pending_fetchers_; - // List of observers to notify when access token status changes. base::ObserverList<DiagnosticsObserver, true>::Unchecked diagnostics_observer_list_; - - // The depth of batch changes. - int batch_change_depth_; - + Delegate* delegate_; + // A map from fetch parameters to a fetcher that is fetching an OAuth2 access + // token using these parameters. + std::map<RequestParameters, std::unique_ptr<Fetcher>> pending_fetchers_; // Maximum number of retries in fetching an OAuth2 access token. static int max_fetch_retry_num_; - FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, RequestParametersOrderTest); - FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, - SameScopesRequestedForDifferentClients); - FRIEND_TEST_ALL_PREFIXES(OAuth2TokenServiceTest, UpdateClearsCache); - SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService); + DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenManager); }; -#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_H_ +#endif // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_H_ diff --git a/chromium/google_apis/gaia/oauth2_token_service_test_util.cc b/chromium/google_apis/gaia/oauth2_access_token_manager_test_util.cc index 774e1b0f6aa..427fe9d4294 100644 --- a/chromium/google_apis/gaia/oauth2_token_service_test_util.cc +++ b/chromium/google_apis/gaia/oauth2_access_token_manager_test_util.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "google_apis/gaia/oauth2_token_service_test_util.h" +#include "google_apis/gaia/oauth2_access_token_manager_test_util.h" #include "base/strings/stringprintf.h" @@ -19,25 +19,25 @@ std::string GetValidTokenResponse(const std::string& token, int expiration) { return base::StringPrintf(kValidTokenResponse, token.c_str(), expiration); } -TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer() - : OAuth2TokenService::Consumer("test"), +TestingOAuth2AccessTokenManagerConsumer:: + TestingOAuth2AccessTokenManagerConsumer() + : OAuth2AccessTokenManager::Consumer("test"), number_of_successful_tokens_(0), last_error_(GoogleServiceAuthError::AuthErrorNone()), - number_of_errors_(0) { -} + number_of_errors_(0) {} -TestingOAuth2TokenServiceConsumer::~TestingOAuth2TokenServiceConsumer() { -} +TestingOAuth2AccessTokenManagerConsumer:: + ~TestingOAuth2AccessTokenManagerConsumer() {} -void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, +void TestingOAuth2AccessTokenManagerConsumer::OnGetTokenSuccess( + const OAuth2AccessTokenManager::Request* request, const OAuth2AccessTokenConsumer::TokenResponse& token_response) { last_token_ = token_response.access_token; ++number_of_successful_tokens_; } -void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( - const OAuth2TokenService::Request* request, +void TestingOAuth2AccessTokenManagerConsumer::OnGetTokenFailure( + const OAuth2AccessTokenManager::Request* request, const GoogleServiceAuthError& error) { last_error_ = error; ++number_of_errors_; diff --git a/chromium/google_apis/gaia/oauth2_token_service_test_util.h b/chromium/google_apis/gaia/oauth2_access_token_manager_test_util.h index ed389867fb5..e79e9264e05 100644 --- a/chromium/google_apis/gaia/oauth2_token_service_test_util.h +++ b/chromium/google_apis/gaia/oauth2_access_token_manager_test_util.h @@ -2,27 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_ -#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_ +#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_TEST_UTIL_H_ +#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_TEST_UTIL_H_ #include <string> #include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_token_service.h" +#include "google_apis/gaia/oauth2_access_token_manager.h" std::string GetValidTokenResponse(const std::string& token, int expiration); // A simple testing consumer. -class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { +class TestingOAuth2AccessTokenManagerConsumer + : public OAuth2AccessTokenManager::Consumer { public: - TestingOAuth2TokenServiceConsumer(); - ~TestingOAuth2TokenServiceConsumer() override; + TestingOAuth2AccessTokenManagerConsumer(); + ~TestingOAuth2AccessTokenManagerConsumer() override; - // OAuth2TokenService::Consumer overrides. + // OAuth2AccessTokenManager::Consumer overrides. void OnGetTokenSuccess( - const OAuth2TokenService::Request* request, + const OAuth2AccessTokenManager::Request* request, const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, + void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request, const GoogleServiceAuthError& error) override; std::string last_token_; @@ -31,4 +32,4 @@ class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { int number_of_errors_; }; -#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_ +#endif // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_MANAGER_TEST_UTIL_H_ diff --git a/chromium/google_apis/gaia/oauth2_access_token_manager_unittest.cc b/chromium/google_apis/gaia/oauth2_access_token_manager_unittest.cc new file mode 100644 index 00000000000..04bb9ba9b9f --- /dev/null +++ b/chromium/google_apis/gaia/oauth2_access_token_manager_unittest.cc @@ -0,0 +1,130 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "google_apis/gaia/oauth2_access_token_manager.h" +#include "base/memory/ref_counted.h" +#include "base/test/scoped_task_environment.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_urls.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" +#include "google_apis/gaia/oauth2_access_token_manager_test_util.h" +#include "net/http/http_status_code.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +constexpr char kTestAccountId[] = "test_user@gmail.com"; + +class FakeOAuth2AccessTokenManagerDelegate + : public OAuth2AccessTokenManager::Delegate { + public: + FakeOAuth2AccessTokenManagerDelegate( + network::TestURLLoaderFactory* test_url_loader_factory) + : shared_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + test_url_loader_factory)) {} + ~FakeOAuth2AccessTokenManagerDelegate() override = default; + + // OAuth2AccessTokenManager::Delegate: + std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer) override { + EXPECT_EQ(CoreAccountId(kTestAccountId), account_id); + return std::make_unique<OAuth2AccessTokenFetcherImpl>( + consumer, url_loader_factory, "fake_refresh_token"); + } + + bool HasRefreshToken(const CoreAccountId& account_id) const override { + return CoreAccountId(kTestAccountId) == account_id; + } + + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() + const override { + return shared_factory_; + } + + private: + scoped_refptr<network::SharedURLLoaderFactory> shared_factory_; +}; + +class FakeOAuth2AccessTokenManagerConsumer + : public TestingOAuth2AccessTokenManagerConsumer { + public: + FakeOAuth2AccessTokenManagerConsumer() = default; + ~FakeOAuth2AccessTokenManagerConsumer() override = default; + + // TestingOAuth2AccessTokenManagerConsumer overrides. + void OnGetTokenSuccess( + const OAuth2AccessTokenManager::Request* request, + const OAuth2AccessTokenConsumer::TokenResponse& token_response) override { + TestingOAuth2AccessTokenManagerConsumer::OnGetTokenSuccess(request, + token_response); + if (closure_) + std::move(closure_).Run(); + } + + void OnGetTokenFailure(const OAuth2AccessTokenManager::Request* request, + const GoogleServiceAuthError& error) override { + TestingOAuth2AccessTokenManagerConsumer::OnGetTokenFailure(request, error); + if (closure_) + std::move(closure_).Run(); + } + + void SetResponseCompletedClosure(base::OnceClosure closure) { + closure_ = std::move(closure); + } + + private: + base::OnceClosure closure_; +}; + +} // namespace + +class OAuth2AccessTokenManagerTest : public testing::Test { + public: + OAuth2AccessTokenManagerTest() + : delegate_(&test_url_loader_factory_), token_manager_(&delegate_) {} + + void SetUp() override { account_id_ = CoreAccountId(kTestAccountId); } + + void TearDown() override { + // Makes sure that all the clean up tasks are run. It's required because of + // cleaning up OAuth2AccessTokenManager::Fetcher on + // InformWaitingRequestsAndDelete(). + base::RunLoop().RunUntilIdle(); + } + + void SimulateOAuthTokenResponse(const std::string& token, + net::HttpStatusCode status = net::HTTP_OK) { + test_url_loader_factory_.AddResponse( + GaiaUrls::GetInstance()->oauth2_token_url().spec(), token, status); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + CoreAccountId account_id_; + network::TestURLLoaderFactory test_url_loader_factory_; + FakeOAuth2AccessTokenManagerDelegate delegate_; + OAuth2AccessTokenManager token_manager_; + FakeOAuth2AccessTokenManagerConsumer consumer_; +}; + +// Test if StartRequest gets a response properly. +TEST_F(OAuth2AccessTokenManagerTest, StartRequest) { + base::RunLoop run_loop; + consumer_.SetResponseCompletedClosure(run_loop.QuitClosure()); + std::unique_ptr<OAuth2AccessTokenManager::Request> request( + token_manager_.StartRequest( + account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_)); + SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); + run_loop.Run(); + + EXPECT_EQ(1, consumer_.number_of_successful_tokens_); + EXPECT_EQ(0, consumer_.number_of_errors_); +} diff --git a/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc b/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc index cd7a4811031..1a9ba7911b3 100644 --- a/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc +++ b/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc @@ -10,8 +10,8 @@ #include <string> #include <utility> -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/time/time.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -100,7 +100,7 @@ class OAuth2ApiCallFlowTest : public testing::Test { AddFetchResult(url, succeeds, status, std::string()); } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> shared_factory_; StrictMock<MockApiCallFlow> flow_; diff --git a/chromium/google_apis/gaia/oauth2_mint_token_flow_unittest.cc b/chromium/google_apis/gaia/oauth2_mint_token_flow_unittest.cc index 965237e0037..0ccae2d0ed0 100644 --- a/chromium/google_apis/gaia/oauth2_mint_token_flow_unittest.cc +++ b/chromium/google_apis/gaia/oauth2_mint_token_flow_unittest.cc @@ -142,7 +142,8 @@ class MockMintTokenFlow : public OAuth2MintTokenFlow { : OAuth2MintTokenFlow(delegate, parameters) {} ~MockMintTokenFlow() override {} - MOCK_METHOD0(CreateAccessTokenFetcher, OAuth2AccessTokenFetcher*()); + MOCK_METHOD0(CreateAccessTokenFetcher, + std::unique_ptr<OAuth2AccessTokenFetcher>()); }; } // namespace @@ -168,9 +169,9 @@ class OAuth2MintTokenFlowTest : public testing::Test { std::string ext_id = "ext1"; std::string client_id = "client1"; std::vector<std::string> scopes(CreateTestScopes()); - flow_.reset(new MockMintTokenFlow( + flow_ = std::make_unique<MockMintTokenFlow>( delegate, OAuth2MintTokenFlow::Parameters(ext_id, client_id, scopes, - device_id, mode))); + device_id, mode)); } // Helper to parse the given string to DictionaryValue. diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc b/chromium/google_apis/gaia/oauth2_token_service_delegate.cc deleted file mode 100644 index d4a4409ef0b..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "google_apis/gaia/oauth2_token_service_delegate.h" - -#include "google_apis/gaia/oauth2_token_service.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" - -// static -const char OAuth2TokenServiceDelegate::kInvalidRefreshToken[] = - "invalid_refresh_token"; - -OAuth2TokenServiceDelegate::ScopedBatchChange::ScopedBatchChange( - OAuth2TokenServiceDelegate* delegate) - : delegate_(delegate) { - DCHECK(delegate_); - delegate_->StartBatchChanges(); -} - -OAuth2TokenServiceDelegate::ScopedBatchChange::~ScopedBatchChange() { - delegate_->EndBatchChanges(); -} - -OAuth2TokenServiceDelegate::OAuth2TokenServiceDelegate() - : batch_change_depth_(0) { -} - -OAuth2TokenServiceDelegate::~OAuth2TokenServiceDelegate() { -} - -bool OAuth2TokenServiceDelegate::ValidateAccountId( - const std::string& account_id) const { - bool valid = !account_id.empty(); - - // If the account is given as an email, make sure its a canonical email. - // Note that some tests don't use email strings as account id, and after - // the gaia id migration it won't be an email. So only check for - // canonicalization if the account_id is suspected to be an email. - if (account_id.find('@') != std::string::npos && - gaia::CanonicalizeEmail(account_id) != account_id) { - valid = false; - } - - DCHECK(valid); - return valid; -} - -void OAuth2TokenServiceDelegate::AddObserver( - OAuth2TokenService::Observer* observer) { - observer_list_.AddObserver(observer); -} - -void OAuth2TokenServiceDelegate::RemoveObserver( - OAuth2TokenService::Observer* observer) { - observer_list_.RemoveObserver(observer); -} - -void OAuth2TokenServiceDelegate::StartBatchChanges() { - ++batch_change_depth_; -} - -void OAuth2TokenServiceDelegate::EndBatchChanges() { - --batch_change_depth_; - DCHECK_LE(0, batch_change_depth_); - if (batch_change_depth_ == 0) { - for (auto& observer : observer_list_) - observer.OnEndBatchChanges(); - } -} - -void OAuth2TokenServiceDelegate::FireRefreshTokenAvailable( - const std::string& account_id) { - DCHECK(!account_id.empty()); - for (auto& observer : observer_list_) - observer.OnRefreshTokenAvailable(account_id); -} - -void OAuth2TokenServiceDelegate::FireRefreshTokenRevoked( - const std::string& account_id) { - DCHECK(!account_id.empty()); - for (auto& observer : observer_list_) - observer.OnRefreshTokenRevoked(account_id); -} - -void OAuth2TokenServiceDelegate::FireRefreshTokensLoaded() { - for (auto& observer : observer_list_) - observer.OnRefreshTokensLoaded(); -} - -void OAuth2TokenServiceDelegate::FireAuthErrorChanged( - const std::string& account_id, - const GoogleServiceAuthError& error) { - DCHECK(!account_id.empty()); - for (auto& observer : observer_list_) - observer.OnAuthErrorChanged(account_id, error); -} - -std::string OAuth2TokenServiceDelegate::GetTokenForMultilogin( - const std::string& account_id) const { - return std::string(); -} - -scoped_refptr<network::SharedURLLoaderFactory> -OAuth2TokenServiceDelegate::GetURLLoaderFactory() const { - return nullptr; -} - -GoogleServiceAuthError OAuth2TokenServiceDelegate::GetAuthError( - const std::string& account_id) const { - return GoogleServiceAuthError::AuthErrorNone(); -} - -std::vector<std::string> OAuth2TokenServiceDelegate::GetAccounts() { - return std::vector<std::string>(); -} - -const net::BackoffEntry* OAuth2TokenServiceDelegate::BackoffEntry() const { - return nullptr; -} - -void OAuth2TokenServiceDelegate::LoadCredentials( - const std::string& primary_account_id) { - NOTREACHED() << "OAuth2TokenServiceDelegate does not load credentials. " - "Subclasses that need to load credentials must provide " - "an implemenation of this method"; -} - -void OAuth2TokenServiceDelegate::ExtractCredentials( - OAuth2TokenService* to_service, - const std::string& account_id) { - NOTREACHED(); -} - -bool OAuth2TokenServiceDelegate::FixRequestErrorIfPossible() { - return false; -} diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate.h b/chromium/google_apis/gaia/oauth2_token_service_delegate.h deleted file mode 100644 index a8c4135e085..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_delegate.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_DELEGATE_H_ -#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_DELEGATE_H_ - -#include <set> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/observer_list.h" -#include "build/build_config.h" -#include "google_apis/gaia/gaia_auth_util.h" -#include "google_apis/gaia/oauth2_token_service.h" -#include "net/base/backoff_entry.h" - -namespace network { -class SharedURLLoaderFactory; -} - -// Abstract base class to fetch and maintain refresh tokens from various -// entities. Concrete subclasses should implement RefreshTokenIsAvailable and -// CreateAccessTokenFetcher properly. -class OAuth2TokenServiceDelegate { - public: - // Refresh token guaranteed to be invalid. Can be passed to - // UpdateCredentials() to force an authentication error. - static const char kInvalidRefreshToken[]; - - enum LoadCredentialsState { - LOAD_CREDENTIALS_NOT_STARTED, - LOAD_CREDENTIALS_IN_PROGRESS, - LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, - LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS, - LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS, - LOAD_CREDENTIALS_FINISHED_WITH_NO_TOKEN_FOR_PRIMARY_ACCOUNT, - LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS, - }; - - OAuth2TokenServiceDelegate(); - virtual ~OAuth2TokenServiceDelegate(); - - virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer) = 0; - - // Returns |true| if a refresh token is available for |account_id|, and - // |false| otherwise. - // Note: Implementations must make sure that |RefreshTokenIsAvailable| returns - // |true| if and only if |account_id| is contained in the list of accounts - // returned by |GetAccounts|. - virtual bool RefreshTokenIsAvailable(const std::string& account_id) const = 0; - virtual GoogleServiceAuthError GetAuthError( - const std::string& account_id) const; - virtual void UpdateAuthError(const std::string& account_id, - const GoogleServiceAuthError& error) {} - - // Returns a list of accounts for which a refresh token is maintained by - // |this| instance. - // Note: If tokens have not been fully loaded yet, an empty list is returned. - // Also, see |RefreshTokenIsAvailable|. - virtual std::vector<std::string> GetAccounts(); - virtual void RevokeAllCredentials() {} - - virtual void InvalidateAccessToken(const std::string& account_id, - const std::string& client_id, - const std::set<std::string>& scopes, - const std::string& access_token) {} - - // If refresh token is accessible (on Desktop) sets error for it to - // INVALID_GAIA_CREDENTIALS and notifies the observers. Otherwise - // does nothing. - virtual void InvalidateTokenForMultilogin(const std::string& failed_account) { - } - - virtual void Shutdown() {} - virtual void UpdateCredentials(const std::string& account_id, - const std::string& refresh_token) {} - virtual void RevokeCredentials(const std::string& account_id) {} - virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() - const; - - // Returns refresh token if the platform allows it (on Desktop) and if it is - // available and doesn't have error. Otherwise returns empty string (for iOS - // and Android). - virtual std::string GetTokenForMultilogin( - const std::string& account_id) const; - - bool ValidateAccountId(const std::string& account_id) const; - - // Add or remove observers of this token service. - void AddObserver(OAuth2TokenService::Observer* observer); - void RemoveObserver(OAuth2TokenService::Observer* observer); - - // Returns a pointer to its instance of net::BackoffEntry if it has one, or - // a nullptr otherwise. - virtual const net::BackoffEntry* BackoffEntry() const; - - // ----------------------------------------------------------------------- - // Methods that are only used by ProfileOAuth2TokenService. - // ----------------------------------------------------------------------- - - // Loads the credentials from disk. Called only once when the token service - // is initialized. Default implementation is NOTREACHED - subsclasses that - // are used by the ProfileOAuth2TokenService must provide an implementation - // for this method. - virtual void LoadCredentials(const std::string& primary_account_id); - - // Returns the state of the load credentials operation. - LoadCredentialsState load_credentials_state() const { - return load_credentials_state_; - } - - // Removes the credentials associated to account_id from the internal storage, - // and moves them to |to_service|. The credentials are not revoked on the - // server, but the OnRefreshTokenRevoked() notification is sent to the - // observers. - virtual void ExtractCredentials(OAuth2TokenService* to_service, - const std::string& account_id); - - // Attempts to fix the error if possible. Returns true if the error was fixed - // and false otherwise. - virtual bool FixRequestErrorIfPossible(); - -#if defined(OS_IOS) - // Triggers platform specific implementation for IOS to add a given account - // to the token service from a system account. - virtual void AddAccountFromSystem(const std::string& account_id) {} -#endif - -#if defined(OS_ANDROID) || defined(OS_IOS) - // Triggers platform specific implementation for Android and IOS to reload - // accounts from system. - virtual void ReloadAccountsFromSystem(const std::string& primary_account_id) { - } -#endif - - // ----------------------------------------------------------------------- - // End of methods that are only used by ProfileOAuth2TokenService - // ----------------------------------------------------------------------- - - protected: - void set_load_credentials_state(LoadCredentialsState state) { - load_credentials_state_ = state; - } - - // Called by subclasses to notify observers. Some are virtual to allow Android - // to broadcast the notifications to Java code. - virtual void FireRefreshTokenAvailable(const std::string& account_id); - virtual void FireRefreshTokenRevoked(const std::string& account_id); - virtual void FireRefreshTokensLoaded(); - void FireAuthErrorChanged(const std::string& account_id, - const GoogleServiceAuthError& error); - - // Helper class to scope batch changes. - class ScopedBatchChange { - public: - explicit ScopedBatchChange(OAuth2TokenServiceDelegate* delegate); - ~ScopedBatchChange(); - - private: - OAuth2TokenServiceDelegate* delegate_; // Weak. - DISALLOW_COPY_AND_ASSIGN(ScopedBatchChange); - }; - - private: - // List of observers to notify when refresh token availability changes. - // Makes sure list is empty on destruction. - base::ObserverList<OAuth2TokenService::Observer, true>::Unchecked - observer_list_; - - // The state of the load credentials operation. - LoadCredentialsState load_credentials_state_ = LOAD_CREDENTIALS_NOT_STARTED; - - void StartBatchChanges(); - void EndBatchChanges(); - - // The depth of batch changes. - int batch_change_depth_; - - DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceDelegate); -}; - -#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_DELEGATE_H_ diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate_unittest.cc b/chromium/google_apis/gaia/oauth2_token_service_delegate_unittest.cc deleted file mode 100644 index 01555eeab53..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_delegate_unittest.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include <string> - -#include "base/macros.h" -#include "google_apis/gaia/fake_oauth2_token_service_delegate.h" -#include "google_apis/gaia/gaia_urls.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_token_service_delegate.h" -#include "google_apis/gaia/oauth2_token_service_test_util.h" -#include "services/network/test/test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -// The default implementation of -// OAuth2TokenServiceDelegate::InvalidateTokensForMultilogin is used on mobile -// where refresh tokens are not accessible. This test checks that refresh tokens -// are not affected on INVALID_TOKENS Multilogin error. -TEST(OAuth2TokenServiceDelegateTest, InvalidateTokensForMultilogin) { - class TokenServiceObserver : public OAuth2TokenService::Observer { - public: - MOCK_METHOD2(OnAuthErrorChanged, - void(const std::string&, const GoogleServiceAuthError&)); - }; - - FakeOAuth2TokenServiceDelegate delegate; - - TokenServiceObserver observer; - delegate.AddObserver(&observer); - // Check that OnAuthErrorChanged is not fired from - // InvalidateTokensForMultilogin and refresh tokens are not set in error. - EXPECT_CALL( - observer, - OnAuthErrorChanged(::testing::_, - GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS))) - .Times(0); - - const std::string account_id1 = "account_id1"; - const std::string account_id2 = "account_id2"; - - delegate.UpdateCredentials(account_id1, "refresh_token1"); - delegate.UpdateCredentials(account_id2, "refresh_token2"); - - delegate.InvalidateTokenForMultilogin(account_id1); - - EXPECT_EQ(delegate.GetAuthError(account_id1).state(), - GoogleServiceAuthError::NONE); - EXPECT_EQ(delegate.GetAuthError(account_id2).state(), - GoogleServiceAuthError::NONE); - - delegate.RemoveObserver(&observer); -} diff --git a/chromium/google_apis/gaia/oauth2_token_service_observer.h b/chromium/google_apis/gaia/oauth2_token_service_observer.h new file mode 100644 index 00000000000..bbbd1968244 --- /dev/null +++ b/chromium/google_apis/gaia/oauth2_token_service_observer.h @@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_OBSERVER_H_ +#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_OBSERVER_H_ + +#include "google_apis/gaia/core_account_id.h" +#include "google_apis/gaia/google_service_auth_error.h" + +// Classes that want to listen for refresh token availability should +// implement this interface and register with the OAuth2TokenService:: +// AddObserver() call. +class OAuth2TokenServiceObserver { + public: + // Called whenever a new login-scoped refresh token is available for + // account |account_id|. Once available, access tokens can be retrieved for + // this account. This is called during initial startup for each token + // loaded (and any time later when, e.g., credentials change). When called, + // any pending token request is cancelled and needs to be retried. Such a + // pending request can easily occur on Android, where refresh tokens are + // held by the OS and are thus often available on startup even before + // OnRefreshTokenAvailable() is called. + virtual void OnRefreshTokenAvailable(const CoreAccountId& account_id) {} + // Called whenever the login-scoped refresh token becomes unavailable for + // account |account_id|. + virtual void OnRefreshTokenRevoked(const CoreAccountId& account_id) {} + // Called after all refresh tokens are loaded during OAuth2TokenService + // startup. + virtual void OnRefreshTokensLoaded() {} + // Sent after a batch of refresh token changes is done. + virtual void OnEndBatchChanges() {} + // Called when the authentication error state for |account_id| has changed. + // Note: It is always called after |OnRefreshTokenAvailable| when refresh + // token is updated. It is not called when the refresh token is revoked. + virtual void OnAuthErrorChanged(const CoreAccountId& account_id, + const GoogleServiceAuthError& auth_error) {} + + protected: + virtual ~OAuth2TokenServiceObserver() {} +}; + +#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_OBSERVER_H_ diff --git a/chromium/google_apis/gaia/oauth2_token_service_request.cc b/chromium/google_apis/gaia/oauth2_token_service_request.cc deleted file mode 100644 index 22ef1d68789..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_request.cc +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "google_apis/gaia/oauth2_token_service_request.h" - -#include <memory> - -#include "base/bind.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/ref_counted_delete_on_sequence.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_access_token_consumer.h" - -OAuth2TokenServiceRequest::TokenServiceProvider::TokenServiceProvider() { -} - -OAuth2TokenServiceRequest::TokenServiceProvider::~TokenServiceProvider() { -} - -// Core serves as the base class for OAuth2TokenService operations. Each -// operation should be modeled as a derived type. -// -// Core is used like this: -// -// 1. Constructed on owner thread. -// -// 2. Start() is called on owner thread, which calls StartOnTokenServiceThread() -// on token service thread. -// -// 3. Request is executed. -// -// 4. Stop() is called on owner thread, which calls StopOnTokenServiceThread() -// on token service thread. -// -// 5. Core is destroyed on owner thread. -class OAuth2TokenServiceRequest::Core - : public base::RefCountedDeleteOnSequence<OAuth2TokenServiceRequest::Core> { - public: - // Note the thread where an instance of Core is constructed is referred to as - // the "owner thread" here. - Core(OAuth2TokenServiceRequest* owner, - const scoped_refptr<TokenServiceProvider>& provider); - - // Starts the core. Must be called on the owner thread. - void Start(); - - // Stops the core. Must be called on the owner thread. - void Stop(); - - // Returns true if this object has been stopped. Must be called on the owner - // thread. - bool IsStopped() const; - - protected: - // Core must be destroyed on the owner thread. If data members must be - // cleaned up or destroyed on the token service thread, do so in the - // StopOnTokenServiceThread method. - virtual ~Core(); - - // Called on the token service thread. - virtual void StartOnTokenServiceThread() = 0; - - // Called on the token service thread. - virtual void StopOnTokenServiceThread() = 0; - - const base::SingleThreadTaskRunner* token_service_task_runner() const { - return token_service_task_runner_.get(); - } - OAuth2TokenService* token_service(); - OAuth2TokenServiceRequest* owner(); - - SEQUENCE_CHECKER(sequence_checker_); - - private: - friend class base::RefCountedDeleteOnSequence< - OAuth2TokenServiceRequest::Core>; - friend class base::DeleteHelper<OAuth2TokenServiceRequest::Core>; - - scoped_refptr<base::SingleThreadTaskRunner> token_service_task_runner_; - OAuth2TokenServiceRequest* owner_; - - // Clear on owner thread. OAuth2TokenServiceRequest promises to clear its - // last reference to TokenServiceProvider on the owner thread so the caller - // can ensure it is destroyed on the owner thread if desired. - scoped_refptr<TokenServiceProvider> provider_; - - DISALLOW_COPY_AND_ASSIGN(Core); -}; - -OAuth2TokenServiceRequest::Core::Core( - OAuth2TokenServiceRequest* owner, - const scoped_refptr<TokenServiceProvider>& provider) - : RefCountedDeleteOnSequence<OAuth2TokenServiceRequest::Core>( - base::SequencedTaskRunnerHandle::Get()), - owner_(owner), - provider_(provider) { - DCHECK(owner_); - DCHECK(provider_.get()); - token_service_task_runner_ = provider_->GetTokenServiceTaskRunner(); - DCHECK(token_service_task_runner()); -} - -OAuth2TokenServiceRequest::Core::~Core() { -} - -void OAuth2TokenServiceRequest::Core::Start() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - token_service_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - &OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread, this)); -} - -void OAuth2TokenServiceRequest::Core::Stop() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!IsStopped()); - - // Detaches |owner_| from this instance so |owner_| will be called back only - // if |Stop()| has never been called. - owner_ = nullptr; - - // Stop on the token service thread. RefCountedDeleteOnSequence ensures we - // will be destroyed on the owner thread. - token_service_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread, - this)); -} - -bool OAuth2TokenServiceRequest::Core::IsStopped() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return owner_ == nullptr; -} - -OAuth2TokenService* OAuth2TokenServiceRequest::Core::token_service() { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - return provider_->GetTokenService(); -} - -OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return owner_; -} - -namespace { - -// An implementation of Core for getting an access token. -class RequestCore : public OAuth2TokenServiceRequest::Core, - public OAuth2TokenService::Consumer { - public: - RequestCore(OAuth2TokenServiceRequest* owner, - const scoped_refptr< - OAuth2TokenServiceRequest::TokenServiceProvider>& provider, - OAuth2TokenService::Consumer* consumer, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes); - - // OAuth2TokenService::Consumer. Must be called on the token service thread. - void OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override; - - private: - friend class base::RefCountedThreadSafe<RequestCore>; - - // Must be destroyed on the owner thread. - ~RequestCore() override; - - // Core implementation. - void StartOnTokenServiceThread() override; - void StopOnTokenServiceThread() override; - - void InformOwnerOnGetTokenSuccess( - const OAuth2AccessTokenConsumer::TokenResponse& token_response); - void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error); - - OAuth2TokenService::Consumer* const consumer_; - std::string account_id_; - OAuth2TokenService::ScopeSet scopes_; - - // OAuth2TokenService request for fetching OAuth2 access token; it should be - // created, reset and accessed only on the token service thread. - std::unique_ptr<OAuth2TokenService::Request> request_; - - DISALLOW_COPY_AND_ASSIGN(RequestCore); -}; - -RequestCore::RequestCore( - OAuth2TokenServiceRequest* owner, - const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>& - provider, - OAuth2TokenService::Consumer* consumer, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes) - : OAuth2TokenServiceRequest::Core(owner, provider), - OAuth2TokenService::Consumer("oauth2_token_service"), - consumer_(consumer), - account_id_(account_id), - scopes_(scopes) { - DCHECK(consumer_); - DCHECK(!account_id_.empty()); - DCHECK(!scopes_.empty()); -} - -RequestCore::~RequestCore() { -} - -void RequestCore::StartOnTokenServiceThread() { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - request_ = token_service()->StartRequest(account_id_, scopes_, this); -} - -void RequestCore::StopOnTokenServiceThread() { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - request_.reset(); -} - -void RequestCore::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - DCHECK_EQ(request_.get(), request); - owning_task_runner()->PostTask( - FROM_HERE, base::BindOnce(&RequestCore::InformOwnerOnGetTokenSuccess, - this, token_response)); - request_.reset(); -} - -void RequestCore::OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - DCHECK_EQ(request_.get(), request); - owning_task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&RequestCore::InformOwnerOnGetTokenFailure, this, error)); - request_.reset(); -} - -void RequestCore::InformOwnerOnGetTokenSuccess( - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!IsStopped()) { - consumer_->OnGetTokenSuccess(owner(), token_response); - } -} - -void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!IsStopped()) { - consumer_->OnGetTokenFailure(owner(), error); - } -} - -// An implementation of Core for invalidating an access token. -class InvalidateCore : public OAuth2TokenServiceRequest::Core { - public: - InvalidateCore(OAuth2TokenServiceRequest* owner, - const scoped_refptr< - OAuth2TokenServiceRequest::TokenServiceProvider>& provider, - const std::string& access_token, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes); - - private: - friend class base::RefCountedThreadSafe<InvalidateCore>; - - // Must be destroyed on the owner thread. - ~InvalidateCore() override; - - // Core implementation. - void StartOnTokenServiceThread() override; - void StopOnTokenServiceThread() override; - - std::string access_token_; - std::string account_id_; - OAuth2TokenService::ScopeSet scopes_; - - DISALLOW_COPY_AND_ASSIGN(InvalidateCore); -}; - -InvalidateCore::InvalidateCore( - OAuth2TokenServiceRequest* owner, - const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>& - provider, - const std::string& access_token, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes) - : OAuth2TokenServiceRequest::Core(owner, provider), - access_token_(access_token), - account_id_(account_id), - scopes_(scopes) { - DCHECK(!access_token_.empty()); - DCHECK(!account_id_.empty()); - DCHECK(!scopes.empty()); -} - -InvalidateCore::~InvalidateCore() { -} - -void InvalidateCore::StartOnTokenServiceThread() { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - token_service()->InvalidateAccessToken(account_id_, scopes_, access_token_); -} - -void InvalidateCore::StopOnTokenServiceThread() { - DCHECK(token_service_task_runner()->RunsTasksInCurrentSequence()); - // Nothing to do. -} - -} // namespace - -// static -std::unique_ptr<OAuth2TokenServiceRequest> -OAuth2TokenServiceRequest::CreateAndStart( - const scoped_refptr<TokenServiceProvider>& provider, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes, - OAuth2TokenService::Consumer* consumer) { - std::unique_ptr<OAuth2TokenServiceRequest> request( - new OAuth2TokenServiceRequest(account_id)); - scoped_refptr<Core> core( - new RequestCore(request.get(), provider, consumer, account_id, scopes)); - request->StartWithCore(core); - return request; -} - -// static -void OAuth2TokenServiceRequest::InvalidateToken( - const scoped_refptr<TokenServiceProvider>& provider, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes, - const std::string& access_token) { - std::unique_ptr<OAuth2TokenServiceRequest> request( - new OAuth2TokenServiceRequest(account_id)); - scoped_refptr<Core> core(new InvalidateCore( - request.get(), provider, access_token, account_id, scopes)); - request->StartWithCore(core); -} - -OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - core_->Stop(); -} - -std::string OAuth2TokenServiceRequest::GetAccountId() const { - return account_id_; -} - -OAuth2TokenServiceRequest::OAuth2TokenServiceRequest( - const std::string& account_id) - : account_id_(account_id) { - DCHECK(!account_id_.empty()); -} - -void OAuth2TokenServiceRequest::StartWithCore(const scoped_refptr<Core>& core) { - DCHECK(core.get()); - core_ = core; - core_->Start(); -} diff --git a/chromium/google_apis/gaia/oauth2_token_service_request.h b/chromium/google_apis/gaia/oauth2_token_service_request.h deleted file mode 100644 index 1ce03258dbc..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_request.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ -#define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ - -#include <memory> -#include <set> -#include <string> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/sequence_checker.h" -#include "base/single_thread_task_runner.h" -#include "google_apis/gaia/oauth2_token_service.h" - -// OAuth2TokenServiceRequest represents an asynchronous request to an -// OAuth2TokenService that may live in another thread. -// -// An OAuth2TokenServiceRequest can be created and started from any thread. -class OAuth2TokenServiceRequest : public OAuth2TokenService::Request { - public: - class Core; - - // Interface for providing an OAuth2TokenService. - // - // Ref-counted so that OAuth2TokenServiceRequest can ensure this object isn't - // destroyed out from under the token service task runner thread. Because - // OAuth2TokenServiceRequest has a reference, implementations of - // TokenServiceProvider must be capable of being destroyed on the same thread - // on which the OAuth2TokenServiceRequest was created. - class TokenServiceProvider - : public base::RefCountedThreadSafe<TokenServiceProvider> { - public: - TokenServiceProvider(); - - // Returns the task runner on which the token service lives. - // - // This method may be called from any thread. - virtual scoped_refptr<base::SingleThreadTaskRunner> - GetTokenServiceTaskRunner() = 0; - - // Returns a pointer to a token service. - // - // Caller does not own the token service and must not delete it. The token - // service must outlive all instances of OAuth2TokenServiceRequest. - // - // This method may only be called from the task runner returned by - // |GetTokenServiceTaskRunner|. - virtual OAuth2TokenService* GetTokenService() = 0; - - protected: - friend class base::RefCountedThreadSafe<TokenServiceProvider>; - virtual ~TokenServiceProvider(); - }; - - // Creates and starts an access token request for |account_id| and |scopes|. - // - // |provider| is used to get the OAuth2TokenService. - // - // |account_id| must not be empty. - // - // |scopes| must not be empty. - // - // |consumer| will be invoked in the same thread that invoked CreateAndStart - // and must outlive the returned request object. Destroying the request - // object ensure that |consumer| will not be called. However, the actual - // network activities may not be canceled and the cache in OAuth2TokenService - // may be populated with the fetched results. - static std::unique_ptr<OAuth2TokenServiceRequest> CreateAndStart( - const scoped_refptr<TokenServiceProvider>& provider, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes, - OAuth2TokenService::Consumer* consumer); - - // Invalidates |access_token| for |account_id| and |scopes|. - // - // |provider| is used to get the OAuth2TokenService. - // - // |account_id| must not be empty. - // - // |scopes| must not be empty. - static void InvalidateToken( - const scoped_refptr<TokenServiceProvider>& provider, - const std::string& account_id, - const OAuth2TokenService::ScopeSet& scopes, - const std::string& access_token); - - ~OAuth2TokenServiceRequest() override; - - // OAuth2TokenService::Request. - std::string GetAccountId() const override; - - private: - OAuth2TokenServiceRequest(const std::string& account_id); - - void StartWithCore(const scoped_refptr<Core>& core); - - const std::string account_id_; - scoped_refptr<Core> core_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceRequest); -}; - -#endif // GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_REQUEST_H_ diff --git a/chromium/google_apis/gaia/oauth2_token_service_request_unittest.cc b/chromium/google_apis/gaia/oauth2_token_service_request_unittest.cc deleted file mode 100644 index 509f28ac21b..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_request_unittest.cc +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "google_apis/gaia/oauth2_token_service_request.h" - -#include <set> -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/location.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "google_apis/gaia/fake_oauth2_token_service.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_token_service.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char kAccessToken[] = "access_token"; -const char kAccountId[] = "test_user@gmail.com"; -const char kScope[] = "SCOPE"; - -class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { - public: - TestingOAuth2TokenServiceConsumer(); - ~TestingOAuth2TokenServiceConsumer() override; - - void OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override; - - int num_get_token_success_; - int num_get_token_failure_; - std::string last_token_; - std::string last_id_token_; - GoogleServiceAuthError last_error_; -}; - -TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer() - : OAuth2TokenService::Consumer("test"), - num_get_token_success_(0), - num_get_token_failure_(0), - last_error_(GoogleServiceAuthError::AuthErrorNone()) { -} - -TestingOAuth2TokenServiceConsumer::~TestingOAuth2TokenServiceConsumer() { -} - -void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { - last_token_ = token_response.access_token; - last_id_token_ = token_response.id_token; - ++num_get_token_success_; -} - -void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( - const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) { - last_error_ = error; - ++num_get_token_failure_; -} - -// A mock implementation of an OAuth2TokenService. -// -// Use SetResponse to vary the response to token requests. -class MockOAuth2TokenService : public FakeOAuth2TokenService { - public: - MockOAuth2TokenService(); - ~MockOAuth2TokenService() override; - - void SetResponse(const GoogleServiceAuthError& error, - const std::string& access_token, - const base::Time& expiration, - const std::string& id_token); - - int num_invalidate_token() const { return num_invalidate_token_; } - - const std::string& last_token_invalidated() const { - return last_token_invalidated_; - } - - protected: - void FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes) override; - - void InvalidateAccessTokenImpl(const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) override; - - private: - GoogleServiceAuthError response_error_; - std::string response_access_token_; - base::Time response_expiration_; - std::string response_id_token_; - int num_invalidate_token_; - std::string last_token_invalidated_; -}; - -MockOAuth2TokenService::MockOAuth2TokenService() - : response_error_(GoogleServiceAuthError::AuthErrorNone()), - response_access_token_(kAccessToken), - response_expiration_(base::Time::Max()), - num_invalidate_token_(0) { -} - -MockOAuth2TokenService::~MockOAuth2TokenService() { -} - -void MockOAuth2TokenService::SetResponse(const GoogleServiceAuthError& error, - const std::string& access_token, - const base::Time& expiration, - const std::string& id_token) { - response_error_ = error; - response_access_token_ = access_token; - response_expiration_ = expiration; - response_id_token_ = id_token; -} - -void MockOAuth2TokenService::FetchOAuth2Token( - RequestImpl* request, - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::string& client_id, - const std::string& client_secret, - const ScopeSet& scopes) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&OAuth2TokenService::RequestImpl::InformConsumer, - request->AsWeakPtr(), response_error_, - OAuth2AccessTokenConsumer::TokenResponse( - response_access_token_, response_expiration_, - response_id_token_))); -} - -void MockOAuth2TokenService::InvalidateAccessTokenImpl( - const std::string& account_id, - const std::string& client_id, - const ScopeSet& scopes, - const std::string& access_token) { - ++num_invalidate_token_; - last_token_invalidated_ = access_token; -} - -class OAuth2TokenServiceRequestTest : public testing::Test { - public: - void SetUp() override; - void TearDown() override; - - protected: - class Provider : public OAuth2TokenServiceRequest::TokenServiceProvider { - public: - Provider(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - OAuth2TokenService* token_service); - - scoped_refptr<base::SingleThreadTaskRunner> GetTokenServiceTaskRunner() - override; - OAuth2TokenService* GetTokenService() override; - - private: - ~Provider() override; - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - OAuth2TokenService* token_service_; - }; - - base::MessageLoop ui_loop_; - OAuth2TokenService::ScopeSet scopes_; - std::unique_ptr<MockOAuth2TokenService> oauth2_service_; - scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider> provider_; - TestingOAuth2TokenServiceConsumer consumer_; -}; - -void OAuth2TokenServiceRequestTest::SetUp() { - scopes_.insert(kScope); - oauth2_service_.reset(new MockOAuth2TokenService); - oauth2_service_->AddAccount(kAccountId); - provider_ = - new Provider(base::ThreadTaskRunnerHandle::Get(), oauth2_service_.get()); -} - -void OAuth2TokenServiceRequestTest::TearDown() { - // Run the loop to execute any pending tasks that may free resources. - base::RunLoop().RunUntilIdle(); -} - -OAuth2TokenServiceRequestTest::Provider::Provider( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - OAuth2TokenService* token_service) - : task_runner_(task_runner), token_service_(token_service) { -} - -scoped_refptr<base::SingleThreadTaskRunner> -OAuth2TokenServiceRequestTest::Provider::GetTokenServiceTaskRunner() { - return task_runner_; -} - -OAuth2TokenService* OAuth2TokenServiceRequestTest::Provider::GetTokenService() { - return token_service_; -} - -OAuth2TokenServiceRequestTest::Provider::~Provider() { -} - -TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Failure) { - oauth2_service_->SetResponse( - GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE), - std::string(), base::Time(), std::string()); - std::unique_ptr<OAuth2TokenServiceRequest> request( - OAuth2TokenServiceRequest::CreateAndStart(provider_.get(), kAccountId, - scopes_, &consumer_)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.num_get_token_success_); - EXPECT_EQ(1, consumer_.num_get_token_failure_); - EXPECT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE, - consumer_.last_error_.state()); - EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); -} - -TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Success) { - std::unique_ptr<OAuth2TokenServiceRequest> request( - OAuth2TokenServiceRequest::CreateAndStart(provider_.get(), kAccountId, - scopes_, &consumer_)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, consumer_.num_get_token_success_); - EXPECT_EQ(0, consumer_.num_get_token_failure_); - EXPECT_EQ(kAccessToken, consumer_.last_token_); - EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); -} - -TEST_F(OAuth2TokenServiceRequestTest, - CreateAndStart_DestroyRequestBeforeCompletes) { - std::unique_ptr<OAuth2TokenServiceRequest> request( - OAuth2TokenServiceRequest::CreateAndStart(provider_.get(), kAccountId, - scopes_, &consumer_)); - request.reset(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.num_get_token_success_); - EXPECT_EQ(0, consumer_.num_get_token_failure_); - EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); -} - -TEST_F(OAuth2TokenServiceRequestTest, - CreateAndStart_DestroyRequestAfterCompletes) { - std::unique_ptr<OAuth2TokenServiceRequest> request( - OAuth2TokenServiceRequest::CreateAndStart(provider_.get(), kAccountId, - scopes_, &consumer_)); - base::RunLoop().RunUntilIdle(); - request.reset(); - EXPECT_EQ(1, consumer_.num_get_token_success_); - EXPECT_EQ(0, consumer_.num_get_token_failure_); - EXPECT_EQ(kAccessToken, consumer_.last_token_); - EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); -} - -TEST_F(OAuth2TokenServiceRequestTest, InvalidateToken) { - OAuth2TokenServiceRequest::InvalidateToken( - provider_.get(), kAccountId, scopes_, kAccessToken); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.num_get_token_success_); - EXPECT_EQ(0, consumer_.num_get_token_failure_); - EXPECT_EQ(kAccessToken, oauth2_service_->last_token_invalidated()); - EXPECT_EQ(1, oauth2_service_->num_invalidate_token()); -} - -} // namespace diff --git a/chromium/google_apis/gaia/oauth2_token_service_unittest.cc b/chromium/google_apis/gaia/oauth2_token_service_unittest.cc deleted file mode 100644 index 9e0648b8299..00000000000 --- a/chromium/google_apis/gaia/oauth2_token_service_unittest.cc +++ /dev/null @@ -1,834 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> - -#include <string> - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/platform_thread.h" -#include "google_apis/gaia/fake_oauth2_token_service_delegate.h" -#include "google_apis/gaia/gaia_constants.h" -#include "google_apis/gaia/gaia_urls.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "google_apis/gaia/oauth2_access_token_consumer.h" -#include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h" -#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" -#include "google_apis/gaia/oauth2_token_service.h" -#include "google_apis/gaia/oauth2_token_service_test_util.h" -#include "net/http/http_status_code.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_test_util.h" -#include "services/network/test/test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -// A testing consumer that retries on error. -class RetryingTestingOAuth2TokenServiceConsumer - : public TestingOAuth2TokenServiceConsumer { - public: - RetryingTestingOAuth2TokenServiceConsumer( - OAuth2TokenService* oauth2_service, - const std::string& account_id) - : oauth2_service_(oauth2_service), - account_id_(account_id) {} - ~RetryingTestingOAuth2TokenServiceConsumer() override {} - - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override { - if (retry_counter_ <= 0) - return; - retry_counter_--; - TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(request, error); - request_ = oauth2_service_->StartRequest( - account_id_, OAuth2TokenService::ScopeSet(), this); - } - - int retry_counter_ = 2; - OAuth2TokenService* oauth2_service_; - std::string account_id_; - std::unique_ptr<OAuth2TokenService::Request> request_; -}; - -class FakeOAuth2TokenServiceObserver : public OAuth2TokenService::Observer { - public: - MOCK_METHOD2(OnAuthErrorChanged, - void(const std::string&, const GoogleServiceAuthError&)); -}; - -class TestOAuth2TokenService : public OAuth2TokenService { - public: - explicit TestOAuth2TokenService( - std::unique_ptr<FakeOAuth2TokenServiceDelegate> delegate) - : OAuth2TokenService(std::move(delegate)) {} - - void CancelAllRequestsForTest() { CancelAllRequests(); } - - void CancelRequestsForAccountForTest(const std::string& account_id) { - CancelRequestsForAccount(account_id); - } - - FakeOAuth2TokenServiceDelegate* GetFakeOAuth2TokenServiceDelegate() { - return static_cast<FakeOAuth2TokenServiceDelegate*>(GetDelegate()); - } -}; - -// This class fakes the behaviour of a MutableProfileOAuth2TokenServiceDelegate -// used on Desktop. -class FakeOAuth2TokenServiceDelegateDesktop - : public FakeOAuth2TokenServiceDelegate { - std::string GetTokenForMultilogin( - const std::string& account_id) const override { - if (GetAuthError(account_id) == GoogleServiceAuthError::AuthErrorNone()) - return GetRefreshToken(account_id); - return std::string(); - } - - OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( - const std::string& account_id, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - OAuth2AccessTokenConsumer* consumer) override { - if (GetAuthError(account_id).IsPersistentError()) { - return new OAuth2AccessTokenFetcherImmediateError( - consumer, GetAuthError(account_id)); - } - return FakeOAuth2TokenServiceDelegate::CreateAccessTokenFetcher( - account_id, url_loader_factory, consumer); - } - void InvalidateTokenForMultilogin( - const std::string& failed_account) override { - UpdateAuthError(failed_account, - GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); - } -}; - -class OAuth2TokenServiceTest : public testing::Test { - public: - void SetUp() override { - auto delegate = std::make_unique<FakeOAuth2TokenServiceDelegate>(); - // Save raw delegate pointer for later. - delegate_ptr_ = delegate.get(); - - test_url_loader_factory_ = delegate->test_url_loader_factory(); - oauth2_service_ = - std::make_unique<TestOAuth2TokenService>(std::move(delegate)); - account_id_ = "test_user@gmail.com"; - } - - void TearDown() override { - // Makes sure that all the clean up tasks are run. - base::RunLoop().RunUntilIdle(); - } - - void SimulateOAuthTokenResponse(const std::string& token, - net::HttpStatusCode status = net::HTTP_OK) { - test_url_loader_factory_->AddResponse( - GaiaUrls::GetInstance()->oauth2_token_url().spec(), token, status); - } - - protected: - base::MessageLoopForIO message_loop_; // net:: stuff needs IO message loop. - network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr; - FakeOAuth2TokenServiceDelegate* delegate_ptr_ = nullptr; // Not owned. - std::unique_ptr<TestOAuth2TokenService> oauth2_service_; - std::string account_id_; - TestingOAuth2TokenServiceConsumer consumer_; -}; - -TEST_F(OAuth2TokenServiceTest, NoOAuth2RefreshToken) { - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(1, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, FailureShouldNotRetry) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(1, consumer_.number_of_errors_); - EXPECT_EQ(0, test_url_loader_factory_->NumPending()); -} - -TEST_F(OAuth2TokenServiceTest, SuccessWithoutCaching) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, SuccessWithCaching) { - OAuth2TokenService::ScopeSet scopes1; - scopes1.insert("s1"); - scopes1.insert("s2"); - OAuth2TokenService::ScopeSet scopes1_same; - scopes1_same.insert("s2"); - scopes1_same.insert("s1"); - OAuth2TokenService::ScopeSet scopes2; - scopes2.insert("s3"); - - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - // First request. - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, scopes1, &consumer_)); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Second request to the same set of scopes, should return the same token - // without needing a network request. - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, scopes1_same, &consumer_)); - base::RunLoop().RunUntilIdle(); - - // No new network fetcher. - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Third request to a new set of scopes, should return another token. - SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600)); - std::unique_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(account_id_, scopes2, &consumer_)); - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(3, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token2", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndFailure) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - // First request. - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0)); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Second request must try to access the network as the token has expired. - SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED); // Network failure. - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(1, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, SuccessAndExpirationAndSuccess) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - // First request. - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0)); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Second request must try to access the network as the token has expired. - SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 0)); - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("another token", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, RequestDeletedBeforeCompletion) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ(1, test_url_loader_factory_->NumPending()); - - request.reset(); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, RequestDeletedAfterCompletion) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - request.reset(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, MultipleRequestsForTheSameScopesWithOneDeleted) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - - request.reset(); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, ClearedRefreshTokenFailsSubsequentRequests) { - // We have a valid refresh token; the first request is successful. - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // The refresh token is no longer available; subsequent requests fail. - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, ""); - request = oauth2_service_->StartRequest(account_id_, - OAuth2TokenService::ScopeSet(), &consumer_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(1, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, - ChangedRefreshTokenDoesNotAffectInFlightRequests) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "first refreshToken"); - OAuth2TokenService::ScopeSet scopes; - scopes.insert("s1"); - scopes.insert("s2"); - OAuth2TokenService::ScopeSet scopes1; - scopes.insert("s3"); - scopes.insert("s4"); - - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); - base::RunLoop().RunUntilIdle(); - ASSERT_EQ(1, test_url_loader_factory_->NumPending()); - - // Note |request| is still pending when the refresh token changes. - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "second refreshToken"); - - // A 2nd request (using the new refresh token) that occurs and completes - // while the 1st request is in flight is successful. - TestingOAuth2TokenServiceConsumer consumer2; - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, scopes1, &consumer2)); - base::RunLoop().RunUntilIdle(); - ASSERT_EQ(2, test_url_loader_factory_->NumPending()); - - network::URLLoaderCompletionStatus ok_status(net::OK); - network::ResourceResponseHead response_head = - network::CreateResourceResponseHead(net::HTTP_OK); - EXPECT_TRUE(test_url_loader_factory_->SimulateResponseForPendingRequest( - GaiaUrls::GetInstance()->oauth2_token_url(), ok_status, response_head, - GetValidTokenResponse("second token", 3600), - network::TestURLLoaderFactory::kMostRecentMatch)); - EXPECT_EQ(1, consumer2.number_of_successful_tokens_); - EXPECT_EQ(0, consumer2.number_of_errors_); - EXPECT_EQ("second token", consumer2.last_token_); - - EXPECT_TRUE(test_url_loader_factory_->SimulateResponseForPendingRequest( - GaiaUrls::GetInstance()->oauth2_token_url(), ok_status, response_head, - GetValidTokenResponse("first token", 3600), - network::TestURLLoaderFactory::kMostRecentMatch)); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("first token", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, StartRequestForMultiloginDesktop) { - class MockOAuth2AccessTokenConsumer - : public TestingOAuth2TokenServiceConsumer { - public: - MockOAuth2AccessTokenConsumer() = default; - ~MockOAuth2AccessTokenConsumer() = default; - - MOCK_METHOD2( - OnGetTokenSuccess, - void(const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response)); - - MOCK_METHOD2(OnGetTokenFailure, - void(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error)); - - DISALLOW_COPY_AND_ASSIGN(MockOAuth2AccessTokenConsumer); - }; - TestOAuth2TokenService token_service( - std::make_unique<FakeOAuth2TokenServiceDelegateDesktop>()); - - token_service.GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - const std::string account_id_2 = "account_id_2"; - token_service.GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_2, "refreshToken"); - token_service.GetFakeOAuth2TokenServiceDelegate()->UpdateAuthError( - account_id_2, - GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); - - MockOAuth2AccessTokenConsumer consumer; - - EXPECT_CALL(consumer, OnGetTokenSuccess(::testing::_, ::testing::_)).Times(1); - EXPECT_CALL( - consumer, - OnGetTokenFailure( - ::testing::_, - GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP))) - .Times(1); - EXPECT_CALL( - consumer, - OnGetTokenFailure(::testing::_, - GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS))) - .Times(1); - - std::unique_ptr<OAuth2TokenService::Request> request1( - token_service.StartRequestForMultilogin(account_id_, &consumer)); - std::unique_ptr<OAuth2TokenService::Request> request2( - token_service.StartRequestForMultilogin(account_id_2, &consumer)); - std::unique_ptr<OAuth2TokenService::Request> request3( - token_service.StartRequestForMultilogin("unknown_account", &consumer)); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(OAuth2TokenServiceTest, StartRequestForMultiloginMobile) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequestForMultilogin(account_id_, &consumer_)); - - base::RunLoop().RunUntilIdle(); - network::URLLoaderCompletionStatus ok_status(net::OK); - network::ResourceResponseHead response_head = - network::CreateResourceResponseHead(net::HTTP_OK); - EXPECT_TRUE(test_url_loader_factory_->SimulateResponseForPendingRequest( - GaiaUrls::GetInstance()->oauth2_token_url(), ok_status, response_head, - GetValidTokenResponse("second token", 3600), - network::TestURLLoaderFactory::kMostRecentMatch)); - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, ServiceShutDownBeforeFetchComplete) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - // The destructor should cancel all in-flight fetchers. - oauth2_service_.reset(nullptr); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(1, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, RetryingConsumer) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - RetryingTestingOAuth2TokenServiceConsumer consumer(oauth2_service_.get(), - account_id_); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer)); - EXPECT_EQ(0, consumer.number_of_successful_tokens_); - EXPECT_EQ(0, consumer.number_of_errors_); - - SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer.number_of_successful_tokens_); - EXPECT_EQ(2, consumer.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, InvalidateTokensForMultiloginDesktop) { - auto delegate = std::make_unique<FakeOAuth2TokenServiceDelegateDesktop>(); - TestOAuth2TokenService token_service(std::move(delegate)); - FakeOAuth2TokenServiceObserver observer; - token_service.GetFakeOAuth2TokenServiceDelegate()->AddObserver(&observer); - EXPECT_CALL( - observer, - OnAuthErrorChanged(account_id_, - GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS))) - .Times(1); - - token_service.GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - const std::string account_id_2 = "account_id_2"; - token_service.GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_2, "refreshToken2"); - token_service.InvalidateTokenForMultilogin(account_id_, "refreshToken"); - // Check that refresh tokens for failed accounts are set in error. - EXPECT_EQ(token_service.GetFakeOAuth2TokenServiceDelegate() - ->GetAuthError(account_id_) - .state(), - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); - EXPECT_EQ(token_service.GetFakeOAuth2TokenServiceDelegate() - ->GetAuthError(account_id_2) - .state(), - GoogleServiceAuthError::NONE); - - token_service.GetFakeOAuth2TokenServiceDelegate()->RemoveObserver(&observer); -} - -TEST_F(OAuth2TokenServiceTest, InvalidateTokensForMultiloginMobile) { - FakeOAuth2TokenServiceObserver observer; - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->AddObserver(&observer); - EXPECT_CALL( - observer, - OnAuthErrorChanged(account_id_, - GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS))) - .Times(0); - - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - const std::string account_id_2 = "account_id_2"; - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_2, "refreshToken2"); - ; - oauth2_service_->InvalidateTokenForMultilogin(account_id_, "refreshToken"); - // Check that refresh tokens are not affected. - EXPECT_EQ(oauth2_service_->GetFakeOAuth2TokenServiceDelegate() - ->GetAuthError(account_id_) - .state(), - GoogleServiceAuthError::NONE); - EXPECT_EQ(oauth2_service_->GetFakeOAuth2TokenServiceDelegate() - ->GetAuthError(account_id_2) - .state(), - GoogleServiceAuthError::NONE); - - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->RemoveObserver( - &observer); -} - -TEST_F(OAuth2TokenServiceTest, InvalidateToken) { - OAuth2TokenService::ScopeSet scopes; - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - - // First request. - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Second request, should return the same token without needing a network - // request. - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); - base::RunLoop().RunUntilIdle(); - - // No new network fetcher. - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - - // Clear previous response so the token request will be pending and we can - // simulate a response after it started. - test_url_loader_factory_->ClearResponses(); - - // Invalidating the token should return a new token on the next request. - oauth2_service_->InvalidateAccessToken(account_id_, scopes, - consumer_.last_token_); - std::unique_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(account_id_, scopes, &consumer_)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(3, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token2", consumer_.last_token_); -} - -TEST_F(OAuth2TokenServiceTest, CancelAllRequests) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - "account_id_2", "refreshToken2"); - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - oauth2_service_->CancelAllRequestsForTest(); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(2, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, CancelRequestsForAccount) { - OAuth2TokenService::ScopeSet scope_set_1; - scope_set_1.insert("scope1"); - scope_set_1.insert("scope2"); - OAuth2TokenService::ScopeSet scope_set_2(scope_set_1.begin(), - scope_set_1.end()); - scope_set_2.insert("scope3"); - - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request1( - oauth2_service_->StartRequest(account_id_, scope_set_1, &consumer_)); - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequest(account_id_, scope_set_2, &consumer_)); - - std::string account_id_2("account_id_2"); - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_2, "refreshToken2"); - std::unique_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequest(account_id_2, scope_set_1, &consumer_)); - - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - oauth2_service_->CancelRequestsForAccountForTest(account_id_); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(2, consumer_.number_of_errors_); - - oauth2_service_->CancelRequestsForAccountForTest(account_id_2); - - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(3, consumer_.number_of_errors_); -} - -TEST_F(OAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) { - std::string client_id_1("client1"); - std::string client_secret_1("secret1"); - std::string client_id_2("client2"); - std::string client_secret_2("secret2"); - std::set<std::string> scope_set; - scope_set.insert("scope1"); - scope_set.insert("scope2"); - - std::string refresh_token("refreshToken"); - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, refresh_token); - - std::unique_ptr<OAuth2TokenService::Request> request1( - oauth2_service_->StartRequestForClient( - account_id_, client_id_1, client_secret_1, scope_set, &consumer_)); - std::unique_ptr<OAuth2TokenService::Request> request2( - oauth2_service_->StartRequestForClient( - account_id_, client_id_2, client_secret_2, scope_set, &consumer_)); - // Start a request that should be duplicate of |request1|. - std::unique_ptr<OAuth2TokenService::Request> request3( - oauth2_service_->StartRequestForClient( - account_id_, client_id_1, client_secret_1, scope_set, &consumer_)); - base::RunLoop().RunUntilIdle(); - - ASSERT_EQ(2U, - oauth2_service_->GetNumPendingRequestsForTesting( - client_id_1, - account_id_, - scope_set)); - ASSERT_EQ(1U, - oauth2_service_->GetNumPendingRequestsForTesting( - client_id_2, - account_id_, - scope_set)); -} - -TEST_F(OAuth2TokenServiceTest, RequestParametersOrderTest) { - OAuth2TokenService::ScopeSet set_0; - OAuth2TokenService::ScopeSet set_1; - set_1.insert("1"); - - OAuth2TokenService::RequestParameters params[] = { - OAuth2TokenService::RequestParameters("0", "0", set_0), - OAuth2TokenService::RequestParameters("0", "0", set_1), - OAuth2TokenService::RequestParameters("0", "1", set_0), - OAuth2TokenService::RequestParameters("0", "1", set_1), - OAuth2TokenService::RequestParameters("1", "0", set_0), - OAuth2TokenService::RequestParameters("1", "0", set_1), - OAuth2TokenService::RequestParameters("1", "1", set_0), - OAuth2TokenService::RequestParameters("1", "1", set_1), - }; - - for (size_t i = 0; i < base::size(params); i++) { - for (size_t j = 0; j < base::size(params); j++) { - if (i == j) { - EXPECT_FALSE(params[i] < params[j]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(params[j] < params[i]) << " i=" << i << ", j=" << j; - } else if (i < j) { - EXPECT_TRUE(params[i] < params[j]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(params[j] < params[i]) << " i=" << i << ", j=" << j; - } else { - EXPECT_TRUE(params[j] < params[i]) << " i=" << i << ", j=" << j; - EXPECT_FALSE(params[i] < params[j]) << " i=" << i << ", j=" << j; - } - } - } -} - -TEST_F(OAuth2TokenServiceTest, UpdateClearsCache) { - std::string kEmail = "test@gmail.com"; - std::set<std::string> scope_list; - scope_list.insert("scope"); - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - kEmail, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(kEmail, scope_list, &consumer_)); - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); - EXPECT_EQ(1, (int)oauth2_service_->token_cache_.size()); - - oauth2_service_->ClearCache(); - - EXPECT_EQ(0, (int)oauth2_service_->token_cache_.size()); - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - kEmail, "refreshToken"); - SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 3600)); - request = oauth2_service_->StartRequest(kEmail, scope_list, &consumer_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("another token", consumer_.last_token_); - EXPECT_EQ(1, (int)oauth2_service_->token_cache_.size()); -} - -TEST_F(OAuth2TokenServiceTest, FixRequestErrorIfPossible) { - oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials( - account_id_, "refreshToken"); - std::unique_ptr<OAuth2TokenService::Request> request( - oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(), - &consumer_)); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - delegate_ptr_->set_fix_request_if_possible(true); - SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - - SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600)); - base::RunLoop().RunUntilIdle(); - for (int max_reties = 5; - max_reties >= 0 && consumer_.number_of_successful_tokens_ != 1; - --max_reties) { - base::RunLoop().RunUntilIdle(); - base::PlatformThread::Sleep(TimeDelta::FromSeconds(1)); - } - - EXPECT_EQ(1, consumer_.number_of_successful_tokens_); - EXPECT_EQ(0, consumer_.number_of_errors_); - EXPECT_EQ("token", consumer_.last_token_); -} diff --git a/chromium/google_apis/gaia/oauth_multilogin_result.cc b/chromium/google_apis/gaia/oauth_multilogin_result.cc index 42d2b0c633d..312679e8bf7 100644 --- a/chromium/google_apis/gaia/oauth_multilogin_result.cc +++ b/chromium/google_apis/gaia/oauth_multilogin_result.cc @@ -39,14 +39,14 @@ OAuthMultiloginResult::OAuthMultiloginResult( const OAuthMultiloginResult& other) { status_ = other.status(); cookies_ = other.cookies(); - failed_accounts_ = other.failed_accounts(); + failed_gaia_ids_ = other.failed_gaia_ids(); } OAuthMultiloginResult& OAuthMultiloginResult::operator=( const OAuthMultiloginResult& other) { status_ = other.status(); cookies_ = other.cookies(); - failed_accounts_ = other.failed_accounts(); + failed_gaia_ids_ = other.failed_gaia_ids(); return *this; } @@ -74,9 +74,9 @@ void OAuthMultiloginResult::TryParseFailedAccountsFromValue( const std::string* gaia_id = account.FindStringKey("obfuscated_id"); const std::string* status = account.FindStringKey("status"); if (status && gaia_id && *status != "OK") - failed_accounts_.push_back(*gaia_id); + failed_gaia_ids_.push_back(*gaia_id); } - if (failed_accounts_.empty()) + if (failed_gaia_ids_.empty()) status_ = OAuthMultiloginResponseStatus::kUnknownStatus; } @@ -97,6 +97,7 @@ void OAuthMultiloginResult::TryParseCookiesFromValue(base::Value* json_value) { base::Optional<bool> is_http_only = cookie.FindBoolKey("isHttpOnly"); const std::string* priority = cookie.FindStringKey("priority"); base::Optional<double> expiration_delta = cookie.FindDoubleKey("maxAge"); + const std::string* same_site = cookie.FindStringKey("sameSite"); base::TimeDelta before_expiration = base::TimeDelta::FromSecondsD(expiration_delta.value_or(0.0)); @@ -113,7 +114,8 @@ void OAuthMultiloginResult::TryParseCookiesFromValue(base::Value* json_value) { path ? *path : "", /*creation=*/base::Time::Now(), base::Time::Now() + before_expiration, /*last_access=*/base::Time::Now(), is_secure.value_or(true), - is_http_only.value_or(true), net::CookieSameSite::NO_RESTRICTION, + is_http_only.value_or(true), + net::StringToCookieSameSite(same_site ? *same_site : ""), net::StringToCookiePriority(priority ? *priority : "medium")); if (new_cookie.IsCanonical()) { cookies_.push_back(std::move(new_cookie)); diff --git a/chromium/google_apis/gaia/oauth_multilogin_result.h b/chromium/google_apis/gaia/oauth_multilogin_result.h index 8fb264a61f9..dc019c099f8 100644 --- a/chromium/google_apis/gaia/oauth_multilogin_result.h +++ b/chromium/google_apis/gaia/oauth_multilogin_result.h @@ -67,7 +67,7 @@ class OAuthMultiloginResult { ~OAuthMultiloginResult(); std::vector<net::CanonicalCookie> cookies() const { return cookies_; } - std::vector<std::string> failed_accounts() const { return failed_accounts_; } + std::vector<std::string> failed_gaia_ids() const { return failed_gaia_ids_; } OAuthMultiloginResponseStatus status() const { return status_; } private: @@ -84,7 +84,7 @@ class OAuthMultiloginResult { void TryParseFailedAccountsFromValue(base::Value* json_value); std::vector<net::CanonicalCookie> cookies_; - std::vector<std::string> failed_accounts_; + std::vector<std::string> failed_gaia_ids_; OAuthMultiloginResponseStatus status_; }; diff --git a/chromium/google_apis/gaia/oauth_multilogin_result_unittest.cc b/chromium/google_apis/gaia/oauth_multilogin_result_unittest.cc index 674f0a13d4b..3cd83ed7cfc 100644 --- a/chromium/google_apis/gaia/oauth_multilogin_result_unittest.cc +++ b/chromium/google_apis/gaia/oauth_multilogin_result_unittest.cc @@ -45,17 +45,18 @@ TEST(OAuthMultiloginResultTest, TryParseCookiesFromValue) { "value":"vAlUe2", "host":"google.com", "path":"/", - "isSecure":true, - "isHttpOnly":false, + "isSecure":false, + "isHttpOnly":true, "priority":"HIGH", - "maxAge":63070000 + "maxAge":63070000, + "sameSite":"Lax" }, { "name":"SSID", "value":"vAlUe3", "domain":".google.de", "path":"path", - "sSecure":true, + "isSecure":true, "isHttpOnly":false, "priority":"HIGH", "maxAge":63070000 @@ -65,10 +66,9 @@ TEST(OAuthMultiloginResultTest, TryParseCookiesFromValue) { "value":"vAlUe4", "host":".google.fr", "path":"/", - "isSecure":true, - "isHttpOnly":false, "priority":"HIGH", - "maxAge":0 + "maxAge":0, + "sameSite":"Strict" } ] } @@ -85,15 +85,16 @@ TEST(OAuthMultiloginResultTest, TryParseCookiesFromValue) { double expiration = expiration_time.ToDoubleT(); const std::vector<CanonicalCookie> cookies = { CanonicalCookie("SID", "vAlUe1", ".google.ru", "/", time_now, time_now, - expiration_time, true, false, - net::CookieSameSite::NO_RESTRICTION, + expiration_time, /*is_secure=*/true, + /*is_http_only=*/false, net::CookieSameSite::UNSPECIFIED, net::CookiePriority::COOKIE_PRIORITY_HIGH), CanonicalCookie("APISID", "vAlUe2", "google.com", "/", time_now, time_now, - expiration_time, true, false, - net::CookieSameSite::NO_RESTRICTION, + expiration_time, /*is_secure=*/false, + /*is_http_only=*/true, net::CookieSameSite::LAX_MODE, net::CookiePriority::COOKIE_PRIORITY_HIGH), CanonicalCookie("HSID", "vAlUe4", "", "/", time_now, time_now, time_now, - true, false, net::CookieSameSite::NO_RESTRICTION, + /*is_secure=*/true, /*is_http_only=*/true, + net::CookieSameSite::STRICT_MODE, net::CookiePriority::COOKIE_PRIORITY_HIGH)}; EXPECT_EQ((int)result.cookies().size(), 3); @@ -117,19 +118,19 @@ TEST(OAuthMultiloginResultTest, TryParseCookiesFromValue) { Property(&CanonicalCookie::IsCanonical, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::IsHttpOnly, Eq(false)), - Property(&CanonicalCookie::IsHttpOnly, Eq(false)), - Property(&CanonicalCookie::IsHttpOnly, Eq(false)))); + Property(&CanonicalCookie::IsHttpOnly, Eq(true)), + Property(&CanonicalCookie::IsHttpOnly, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::IsSecure, Eq(true)), - Property(&CanonicalCookie::IsSecure, Eq(true)), + Property(&CanonicalCookie::IsSecure, Eq(false)), Property(&CanonicalCookie::IsSecure, Eq(true)))); EXPECT_THAT(result.cookies(), ElementsAre(Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)), + Eq(net::CookieSameSite::UNSPECIFIED)), Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)), + Eq(net::CookieSameSite::LAX_MODE)), Property(&CanonicalCookie::SameSite, - Eq(net::CookieSameSite::NO_RESTRICTION)))); + Eq(net::CookieSameSite::STRICT_MODE)))); EXPECT_THAT( result.cookies(), ElementsAre(Property(&CanonicalCookie::Priority, @@ -303,7 +304,7 @@ TEST(OAuthMultiloginResultTest, ProduceErrorFromResponseStatus) { )"; OAuthMultiloginResult result4(data_error_invalid_credentials); EXPECT_EQ(result4.status(), OAuthMultiloginResponseStatus::kInvalidTokens); - EXPECT_THAT(result4.failed_accounts(), ElementsAre(Eq("account1"))); + EXPECT_THAT(result4.failed_gaia_ids(), ElementsAre(Eq("account1"))); // Unknown status. OAuthMultiloginResult unknown_status(R"()]}' diff --git a/chromium/google_apis/gcm/engine/checkin_request.cc b/chromium/google_apis/gcm/engine/checkin_request.cc index 845b6b12e70..031a05fe1ea 100644 --- a/chromium/google_apis/gcm/engine/checkin_request.cc +++ b/chromium/google_apis/gcm/engine/checkin_request.cc @@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" -#include "base/threading/thread_task_runner_handle.h" #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" #include "google_apis/gcm/protocol/checkin.pb.h" #include "net/base/load_flags.h" @@ -103,18 +102,23 @@ CheckinRequest::CheckinRequest( const net::BackoffEntry::Policy& backoff_policy, const CheckinRequestCallback& callback, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder) : url_loader_factory_(url_loader_factory), callback_(callback), backoff_entry_(&backoff_policy), checkin_url_(checkin_url), request_info_(request_info), + io_task_runner_(std::move(io_task_runner)), recorder_(recorder), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + DCHECK(io_task_runner_); +} CheckinRequest::~CheckinRequest() {} void CheckinRequest::Start() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!url_loader_.get()); checkin_proto::AndroidCheckinRequest request; @@ -196,6 +200,8 @@ void CheckinRequest::Start() { } void CheckinRequest::RetryWithBackoff() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + backoff_entry_.InformOfRequest(false); url_loader_.reset(); @@ -205,7 +211,7 @@ void CheckinRequest::RetryWithBackoff() { recorder_->RecordCheckinDelayedDueToBackoff( backoff_entry_.GetTimeUntilRelease().InMilliseconds()); DCHECK(!weak_ptr_factory_.HasWeakPtrs()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&CheckinRequest::Start, weak_ptr_factory_.GetWeakPtr()), backoff_entry_.GetTimeUntilRelease()); @@ -259,10 +265,6 @@ void CheckinRequest::OnURLLoadComplete(const network::SimpleURLLoader* source, } RecordCheckinStatusAndReportUMA(SUCCESS, recorder_, false); - UMA_HISTOGRAM_COUNTS_1M("GCM.CheckinRetryCount", - backoff_entry_.failure_count()); - UMA_HISTOGRAM_TIMES("GCM.CheckinCompleteTime", - base::TimeTicks::Now() - request_start_time_); callback_.Run(response_status, response_proto); } diff --git a/chromium/google_apis/gcm/engine/checkin_request.h b/chromium/google_apis/gcm/engine/checkin_request.h index 0a9e5d64744..eb00a26cc6e 100644 --- a/chromium/google_apis/gcm/engine/checkin_request.h +++ b/chromium/google_apis/gcm/engine/checkin_request.h @@ -70,6 +70,7 @@ class GCM_EXPORT CheckinRequest { const net::BackoffEntry::Policy& backoff_policy, const CheckinRequestCallback& callback, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder); ~CheckinRequest(); @@ -92,6 +93,8 @@ class GCM_EXPORT CheckinRequest { const RequestInfo request_info_; base::TimeTicks request_start_time_; + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Recorder that records GCM activities for debugging purpose. Not owned. GCMStatsRecorder* recorder_; diff --git a/chromium/google_apis/gcm/engine/checkin_request_unittest.cc b/chromium/google_apis/gcm/engine/checkin_request_unittest.cc index 2a6f81d322f..13d31be721b 100644 --- a/chromium/google_apis/gcm/engine/checkin_request_unittest.cc +++ b/chromium/google_apis/gcm/engine/checkin_request_unittest.cc @@ -7,6 +7,7 @@ #include <string> #include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" #include "google_apis/gcm/engine/checkin_request.h" #include "google_apis/gcm/engine/gcm_request_test_base.h" #include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h" @@ -99,7 +100,7 @@ void CheckinRequestTest::CreateRequest(uint64_t android_id, request_.reset(new CheckinRequest( GURL(kCheckinURL), request_info, GetBackoffPolicy(), base::Bind(&CheckinRequestTest::FetcherCallback, base::Unretained(this)), - url_loader_factory(), &recorder_)); + url_loader_factory(), base::ThreadTaskRunnerHandle::Get(), &recorder_)); // Setting android_id_ and security_token_ to blank value, not used elsewhere // in the tests. diff --git a/chromium/google_apis/gcm/engine/connection_factory_impl.cc b/chromium/google_apis/gcm/engine/connection_factory_impl.cc index a8f40801623..790b9a88b0b 100644 --- a/chromium/google_apis/gcm/engine/connection_factory_impl.cc +++ b/chromium/google_apis/gcm/engine/connection_factory_impl.cc @@ -12,7 +12,6 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "base/threading/thread_task_runner_handle.h" #include "google_apis/gcm/engine/connection_handler_impl.h" #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" #include "google_apis/gcm/protocol/mcs.pb.h" @@ -54,6 +53,7 @@ ConnectionFactoryImpl::ConnectionFactoryImpl( const std::vector<GURL>& mcs_endpoints, const net::BackoffEntry::Policy& backoff_policy, GetProxyResolvingFactoryCallback get_socket_factory_callback, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, network::NetworkConnectionTracker* network_connection_tracker) : mcs_endpoints_(mcs_endpoints), @@ -65,11 +65,13 @@ ConnectionFactoryImpl::ConnectionFactoryImpl( waiting_for_backoff_(false), waiting_for_network_online_(false), handshake_in_progress_(false), + io_task_runner_(std::move(io_task_runner)), recorder_(recorder), network_connection_tracker_(network_connection_tracker), listener_(nullptr), weak_ptr_factory_(this) { DCHECK_GE(mcs_endpoints_.size(), 1U); + DCHECK(io_task_runner_); } ConnectionFactoryImpl::~ConnectionFactoryImpl() { @@ -128,6 +130,8 @@ ConnectionEventTracker* ConnectionFactoryImpl::GetEventTrackerForTesting() { } void ConnectionFactoryImpl::ConnectWithBackoff() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + // If a canary managed to connect while a backoff expiration was pending, // just cleanup the internal state. if (connecting_ || handshake_in_progress_ || IsEndpointReachable()) { @@ -142,7 +146,7 @@ void ConnectionFactoryImpl::ConnectWithBackoff() { waiting_for_backoff_ = true; recorder_->RecordConnectionDelayedDueToBackoff( backoff_entry_->GetTimeUntilRelease().InMilliseconds()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&ConnectionFactoryImpl::ConnectWithBackoff, weak_ptr_factory_.GetWeakPtr()), @@ -387,8 +391,9 @@ ConnectionFactoryImpl::CreateConnectionHandler( const ConnectionHandler::ProtoReceivedCallback& read_callback, const ConnectionHandler::ProtoSentCallback& write_callback, const ConnectionHandler::ConnectionChangedCallback& connection_callback) { - return base::WrapUnique<ConnectionHandler>(new ConnectionHandlerImpl( - read_timeout, read_callback, write_callback, connection_callback)); + return base::WrapUnique<ConnectionHandler>( + new ConnectionHandlerImpl(io_task_runner_, read_timeout, read_callback, + write_callback, connection_callback)); } base::TimeTicks ConnectionFactoryImpl::NowTicks() { diff --git a/chromium/google_apis/gcm/engine/connection_factory_impl.h b/chromium/google_apis/gcm/engine/connection_factory_impl.h index fc7b254f2de..bbce25fee1c 100644 --- a/chromium/google_apis/gcm/engine/connection_factory_impl.h +++ b/chromium/google_apis/gcm/engine/connection_factory_impl.h @@ -35,7 +35,7 @@ class GCM_EXPORT ConnectionFactoryImpl const std::vector<GURL>& mcs_endpoints, const net::BackoffEntry::Policy& backoff_policy, GetProxyResolvingFactoryCallback get_socket_factory_callback, - // need task runner here. + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, network::NetworkConnectionTracker* network_connection_tracker); ~ConnectionFactoryImpl() override; @@ -181,6 +181,9 @@ class GCM_EXPORT ConnectionFactoryImpl // Builder for generating new login requests. BuildLoginRequestCallback request_builder_; + // Task runner. + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Recorder that records GCM activities for debugging purpose. Not owned. GCMStatsRecorder* recorder_; diff --git a/chromium/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/chromium/google_apis/gcm/engine/connection_factory_impl_unittest.cc index f36b4c2ddd3..22e09f985a3 100644 --- a/chromium/google_apis/gcm/engine/connection_factory_impl_unittest.cc +++ b/chromium/google_apis/gcm/engine/connection_factory_impl_unittest.cc @@ -160,6 +160,7 @@ TestConnectionFactoryImpl::TestConnectionFactoryImpl( BuildEndpoints(), net::BackoffEntry::Policy(), get_socket_factory_callback, + base::ThreadTaskRunnerHandle::Get(), &dummy_recorder_, network::TestNetworkConnectionTracker::GetInstance()), connect_result_(net::ERR_UNEXPECTED), diff --git a/chromium/google_apis/gcm/engine/connection_handler_impl.cc b/chromium/google_apis/gcm/engine/connection_handler_impl.cc index ae4a0eaac91..b5e04813201 100644 --- a/chromium/google_apis/gcm/engine/connection_handler_impl.cc +++ b/chromium/google_apis/gcm/engine/connection_handler_impl.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/location.h" -#include "base/threading/thread_task_runner_handle.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google_apis/gcm/base/mcs_util.h" @@ -46,11 +45,13 @@ const int kMCSVersion = 41; } // namespace ConnectionHandlerImpl::ConnectionHandlerImpl( + scoped_refptr<base::SequencedTaskRunner> io_task_runner, base::TimeDelta read_timeout, const ProtoReceivedCallback& read_callback, const ProtoSentCallback& write_callback, const ConnectionChangedCallback& connection_callback) - : read_timeout_(read_timeout), + : io_task_runner_(std::move(io_task_runner)), + read_timeout_(read_timeout), handshake_complete_(false), message_tag_(0), message_size_(0), @@ -59,6 +60,8 @@ ConnectionHandlerImpl::ConnectionHandlerImpl( connection_callback_(connection_callback), size_packet_so_far_(0), weak_ptr_factory_(this) { + DCHECK(io_task_runner_); + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); } ConnectionHandlerImpl::~ConnectionHandlerImpl() { @@ -117,6 +120,7 @@ void ConnectionHandlerImpl::SendMessage( void ConnectionHandlerImpl::Login( const google::protobuf::MessageLite& login_request) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK_EQ(output_stream_->GetState(), SocketOutputStream::EMPTY); const char version_byte[1] = {kMCSVersion}; @@ -132,7 +136,7 @@ void ConnectionHandlerImpl::Login( if (output_stream_->Flush( base::Bind(&ConnectionHandlerImpl::OnMessageSent, weak_ptr_factory_.GetWeakPtr())) != net::ERR_IO_PENDING) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ConnectionHandlerImpl::OnMessageSent, weak_ptr_factory_.GetWeakPtr())); } @@ -175,6 +179,7 @@ void ConnectionHandlerImpl::GetNextMessage() { } void ConnectionHandlerImpl::WaitForData(ProcessingState state) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DVLOG(1) << "Waiting for MCS data: state == " << state; if (!input_stream_) { @@ -259,7 +264,7 @@ void ConnectionHandlerImpl::WaitForData(ProcessingState state) { DVLOG(1) << "Socket read finished prematurely. Waiting for " << min_bytes_needed - input_stream_->UnreadByteCount() << " more bytes."; - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ConnectionHandlerImpl::WaitForData, weak_ptr_factory_.GetWeakPtr(), MCS_PROTO_BYTES)); @@ -374,13 +379,15 @@ void ConnectionHandlerImpl::OnGotMessageSize() { } void ConnectionHandlerImpl::OnGotMessageBytes() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + read_timeout_timer_.Stop(); std::unique_ptr<google::protobuf::MessageLite> protobuf( BuildProtobufFromTag(message_tag_)); // Messages with no content are valid; just use the default protobuf for // that tag. if (protobuf.get() && message_size_ == 0) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ConnectionHandlerImpl::GetNextMessage, weak_ptr_factory_.GetWeakPtr())); read_callback_.Run(std::move(protobuf)); @@ -452,7 +459,7 @@ void ConnectionHandlerImpl::OnGotMessageBytes() { } input_stream_->RebuildBuffer(); - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ConnectionHandlerImpl::GetNextMessage, weak_ptr_factory_.GetWeakPtr())); if (message_tag_ == kLoginResponseTag) { diff --git a/chromium/google_apis/gcm/engine/connection_handler_impl.h b/chromium/google_apis/gcm/engine/connection_handler_impl.h index e88749ccafd..13a482cd97d 100644 --- a/chromium/google_apis/gcm/engine/connection_handler_impl.h +++ b/chromium/google_apis/gcm/engine/connection_handler_impl.h @@ -27,6 +27,11 @@ class SocketOutputStream; class GCM_EXPORT ConnectionHandlerImpl : public ConnectionHandler { public: + // Must be called on |io_task_runner|. + // |io_task_runner|: for running IO tasks. When provided, it could be a + // wrapper on top of base::ThreadTaskRunnerHandle::Get() to provide power + // management featueres so that a delayed task posted to it can wake the + // system up from sleep to perform the task. // |read_callback| will be invoked with the contents of any received protobuf // message. // |write_callback| will be invoked anytime a message has been successfully @@ -34,11 +39,11 @@ class GCM_EXPORT ConnectionHandlerImpl : public ConnectionHandler { // other end received it. // |connection_callback| will be invoked with any fatal read/write errors // encountered. - ConnectionHandlerImpl( - base::TimeDelta read_timeout, - const ProtoReceivedCallback& read_callback, - const ProtoSentCallback& write_callback, - const ConnectionChangedCallback& connection_callback); + ConnectionHandlerImpl(scoped_refptr<base::SequencedTaskRunner> io_task_runner, + base::TimeDelta read_timeout, + const ProtoReceivedCallback& read_callback, + const ProtoSentCallback& write_callback, + const ConnectionChangedCallback& connection_callback); ~ConnectionHandlerImpl() override; // ConnectionHandler implementation. @@ -94,6 +99,8 @@ class GCM_EXPORT ConnectionHandlerImpl : public ConnectionHandler { // Closes the current connection. void CloseConnection(); + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Timeout policy: the timeout is only enforced while waiting on the // handshake (version and/or LoginResponse) or once at least a tag packet has // been received. It is reset every time new data is received, and is diff --git a/chromium/google_apis/gcm/engine/connection_handler_impl_unittest.cc b/chromium/google_apis/gcm/engine/connection_handler_impl_unittest.cc index f8fe0f9d4cd..09774809095 100644 --- a/chromium/google_apis/gcm/engine/connection_handler_impl_unittest.cc +++ b/chromium/google_apis/gcm/engine/connection_handler_impl_unittest.cc @@ -17,6 +17,7 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_task_environment.h" #include "base/test/test_timeouts.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" @@ -269,7 +270,7 @@ void GCMConnectionHandlerImplTest::PumpLoop() { void GCMConnectionHandlerImplTest::Connect( ScopedMessage* dst_proto) { connection_handler_ = std::make_unique<ConnectionHandlerImpl>( - TestTimeouts::tiny_timeout(), + base::ThreadTaskRunnerHandle::Get(), TestTimeouts::tiny_timeout(), base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation, base::Unretained(this), dst_proto), base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation, diff --git a/chromium/google_apis/gcm/engine/gcm_registration_request_handler.cc b/chromium/google_apis/gcm/engine/gcm_registration_request_handler.cc index dff4b10072e..78e8c458cd9 100644 --- a/chromium/google_apis/gcm/engine/gcm_registration_request_handler.cc +++ b/chromium/google_apis/gcm/engine/gcm_registration_request_handler.cc @@ -28,19 +28,10 @@ void GCMRegistrationRequestHandler::BuildRequestBody(std::string* body){ } void GCMRegistrationRequestHandler::ReportUMAs( - RegistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) { + RegistrationRequest::Status status) { UMA_HISTOGRAM_ENUMERATION("GCM.RegistrationRequestStatus", status, RegistrationRequest::STATUS_COUNT); - - // Other UMAs are only reported when the request succeeds. - if (status != RegistrationRequest::SUCCESS) - return; - - UMA_HISTOGRAM_COUNTS_1M("GCM.RegistrationRetryCount", retry_count); - UMA_HISTOGRAM_TIMES("GCM.RegistrationCompleteTime", complete_time); } } // namespace gcm diff --git a/chromium/google_apis/gcm/engine/gcm_registration_request_handler.h b/chromium/google_apis/gcm/engine/gcm_registration_request_handler.h index 523bdc1adde..fb9a1279017 100644 --- a/chromium/google_apis/gcm/engine/gcm_registration_request_handler.h +++ b/chromium/google_apis/gcm/engine/gcm_registration_request_handler.h @@ -19,9 +19,7 @@ class GCM_EXPORT GCMRegistrationRequestHandler : // RegistrationRequest::RequestHandler overrides: void BuildRequestBody(std::string* body) override; - void ReportUMAs(RegistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) override; + void ReportUMAs(RegistrationRequest::Status status) override; private: std::string senders_; diff --git a/chromium/google_apis/gcm/engine/gcm_request_test_base.h b/chromium/google_apis/gcm/engine/gcm_request_test_base.h index 0c68b3019d5..a076e4d9338 100644 --- a/chromium/google_apis/gcm/engine/gcm_request_test_base.h +++ b/chromium/google_apis/gcm/engine/gcm_request_test_base.h @@ -62,7 +62,7 @@ class GCMRequestTestBase : public testing::Test { void FastForwardToTriggerNextRetry(); base::test::ScopedTaskEnvironment scoped_task_environment_{ - base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; + base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME}; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> shared_factory_; diff --git a/chromium/google_apis/gcm/engine/gcm_store_impl.cc b/chromium/google_apis/gcm/engine/gcm_store_impl.cc index bbf5300c8ac..cc333cdc0ba 100644 --- a/chromium/google_apis/gcm/engine/gcm_store_impl.cc +++ b/chromium/google_apis/gcm/engine/gcm_store_impl.cc @@ -18,6 +18,7 @@ #include "base/strings/string_piece.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" +#include "base/threading/scoped_thread_priority.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "google_apis/gcm/base/encryptor.h" @@ -924,6 +925,11 @@ bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64_t* android_id, s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result); } if (s.ok()) { + // Mitigate the issues caused by loading DLLs on a background thread + // (http://crbug/973868). + base::ScopedThreadMayLoadLibraryOnBackgroundThread priority_boost( + FROM_HERE); + std::string decrypted_token; encryptor_->DecryptString(result, &decrypted_token); if (!base::StringToUint64(decrypted_token, security_token)) { diff --git a/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.cc b/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.cc index 8374981adec..6394a9469b8 100644 --- a/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.cc +++ b/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.cc @@ -52,19 +52,10 @@ UnregistrationRequest::Status GCMUnregistrationRequestHandler::ParseResponse( } void GCMUnregistrationRequestHandler::ReportUMAs( - UnregistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) { + UnregistrationRequest::Status status) { UMA_HISTOGRAM_ENUMERATION("GCM.UnregistrationRequestStatus", status, UnregistrationRequest::UNREGISTRATION_STATUS_COUNT); - - // Other UMAs are only reported when the request succeeds. - if (status != UnregistrationRequest::SUCCESS) - return; - - UMA_HISTOGRAM_COUNTS_1M("GCM.UnregistrationRetryCount", retry_count); - UMA_HISTOGRAM_TIMES("GCM.UnregistrationCompleteTime", complete_time); } } // namespace gcm diff --git a/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.h b/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.h index 06c963b9dad..dead670a6a8 100644 --- a/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.h +++ b/chromium/google_apis/gcm/engine/gcm_unregistration_request_handler.h @@ -22,9 +22,7 @@ class GCM_EXPORT GCMUnregistrationRequestHandler : void BuildRequestBody(std::string* body) override; UnregistrationRequest::Status ParseResponse( const std::string& response) override; - void ReportUMAs(UnregistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) override; + void ReportUMAs(UnregistrationRequest::Status status) override; private: std::string app_id_; diff --git a/chromium/google_apis/gcm/engine/heartbeat_manager.cc b/chromium/google_apis/gcm/engine/heartbeat_manager.cc index dc5429672ec..71e3f0227a6 100644 --- a/chromium/google_apis/gcm/engine/heartbeat_manager.cc +++ b/chromium/google_apis/gcm/engine/heartbeat_manager.cc @@ -11,7 +11,6 @@ #include "base/location.h" #include "base/metrics/histogram_macros.h" #include "base/power_monitor/power_monitor.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "build/build_config.h" @@ -42,19 +41,28 @@ const int kHeartbeatMissedCheckMs = 1000 * 60 * 5; // 5 minutes. } // namespace -HeartbeatManager::HeartbeatManager() +HeartbeatManager::HeartbeatManager( + scoped_refptr<base::SequencedTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> maybe_power_wrapped_io_task_runner) : waiting_for_ack_(false), heartbeat_interval_ms_(0), server_interval_ms_(0), client_interval_ms_(0), + io_task_runner_(std::move(io_task_runner)), heartbeat_timer_(new base::RetainingOneShotTimer()), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + DCHECK(io_task_runner_); + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + // Set the heartbeat timer task runner to |maybe_power_wrapped_io_task_runner| + // so that a delayed task posted to it can wake the system up from sleep to + // perform the task. + heartbeat_timer_->SetTaskRunner( + std::move(maybe_power_wrapped_io_task_runner)); +} HeartbeatManager::~HeartbeatManager() { // Stop listening for system suspend and resume events. - base::PowerMonitor* monitor = base::PowerMonitor::Get(); - if (monitor) - monitor->RemoveObserver(this); + base::PowerMonitor::RemoveObserver(this); } void HeartbeatManager::Start( @@ -66,9 +74,7 @@ void HeartbeatManager::Start( trigger_reconnect_callback_ = trigger_reconnect_callback; // Listen for system suspend and resume events. - base::PowerMonitor* monitor = base::PowerMonitor::Get(); - if (monitor) - monitor->AddObserver(this); + base::PowerMonitor::AddObserver(this); // Calculated the heartbeat interval just before we start the timer. UpdateHeartbeatInterval(); @@ -84,9 +90,7 @@ void HeartbeatManager::Stop() { heartbeat_timer_->Stop(); waiting_for_ack_ = false; - base::PowerMonitor* monitor = base::PowerMonitor::Get(); - if (monitor) - monitor->RemoveObserver(this); + base::PowerMonitor::RemoveObserver(this); } void HeartbeatManager::OnHeartbeatAcked() { @@ -192,7 +196,7 @@ void HeartbeatManager::RestartTimer() { // Windows, Mac, Android, iOS, and Chrome OS all provide a way to be notified // when the system is suspending or resuming. The only one that does not is // Linux so we need to poll to check for missed heartbeats. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&HeartbeatManager::CheckForMissedHeartbeat, weak_ptr_factory_.GetWeakPtr()), @@ -215,7 +219,7 @@ void HeartbeatManager::CheckForMissedHeartbeat() { #if defined(OS_LINUX) && !defined(OS_CHROMEOS) // Otherwise check again later. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&HeartbeatManager::CheckForMissedHeartbeat, weak_ptr_factory_.GetWeakPtr()), diff --git a/chromium/google_apis/gcm/engine/heartbeat_manager.h b/chromium/google_apis/gcm/engine/heartbeat_manager.h index 938730419c2..a5171141f5b 100644 --- a/chromium/google_apis/gcm/engine/heartbeat_manager.h +++ b/chromium/google_apis/gcm/engine/heartbeat_manager.h @@ -32,7 +32,15 @@ class GCM_EXPORT HeartbeatManager : public base::PowerObserver { typedef base::Callback<void(ConnectionFactory::ConnectionResetReason)> ReconnectCallback; - HeartbeatManager(); + // |io_task_runner|: for running IO tasks. + // |maybe_power_wrapped_io_task_runner|: for running IO tasks, where if the + // feature is provided, it could be a wrapper on top of |io_task_runner| + // to provide power management featueres so that a delayed task posted to + // it can wake the system up from sleep to perform the task. + explicit HeartbeatManager( + scoped_refptr<base::SequencedTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> + maybe_power_wrapped_io_task_runner); ~HeartbeatManager() override; // Start the heartbeat logic. @@ -117,6 +125,8 @@ class GCM_EXPORT HeartbeatManager : public base::PowerObserver { // Custom interval requested by the client. int client_interval_ms_; + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Timer for triggering heartbeats. std::unique_ptr<base::RetainingOneShotTimer> heartbeat_timer_; diff --git a/chromium/google_apis/gcm/engine/heartbeat_manager_unittest.cc b/chromium/google_apis/gcm/engine/heartbeat_manager_unittest.cc index 02fcae33a45..feb1617d70c 100644 --- a/chromium/google_apis/gcm/engine/heartbeat_manager_unittest.cc +++ b/chromium/google_apis/gcm/engine/heartbeat_manager_unittest.cc @@ -28,7 +28,10 @@ mcs_proto::HeartbeatConfig BuildHeartbeatConfig(int interval_ms) { class TestHeartbeatManager : public HeartbeatManager { public: - TestHeartbeatManager() {} + TestHeartbeatManager(scoped_refptr<base::SequencedTaskRunner> io_task_runner, + scoped_refptr<base::SequencedTaskRunner> + maybe_power_wrapped_io_task_runner) + : HeartbeatManager(io_task_runner, maybe_power_wrapped_io_task_runner) {} ~TestHeartbeatManager() override {} // Bypass the heartbeat timer, and send the heartbeat now. @@ -63,22 +66,21 @@ class HeartbeatManagerTest : public testing::Test { void SendHeartbeatClosure(); void TriggerReconnectClosure(ConnectionFactory::ConnectionResetReason reason); + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle task_runner_handle_; + std::unique_ptr<TestHeartbeatManager> manager_; int heartbeats_sent_; int reconnects_triggered_; - - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle task_runner_handle_; }; HeartbeatManagerTest::HeartbeatManagerTest() - : manager_(new TestHeartbeatManager()), + : task_runner_(new base::TestSimpleTaskRunner()), + task_runner_handle_(task_runner_), + manager_(new TestHeartbeatManager(task_runner_, task_runner_)), heartbeats_sent_(0), - reconnects_triggered_(0), - task_runner_(new base::TestSimpleTaskRunner()), - task_runner_handle_(task_runner_) { -} + reconnects_triggered_(0) {} void HeartbeatManagerTest::StartManager() { manager_->Start(base::Bind(&HeartbeatManagerTest::SendHeartbeatClosure, diff --git a/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.cc b/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.cc index f001e841d25..fe186ce9f2d 100644 --- a/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.cc +++ b/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.cc @@ -61,19 +61,10 @@ InstanceIDDeleteTokenRequestHandler::ParseResponse( } void InstanceIDDeleteTokenRequestHandler::ReportUMAs( - UnregistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) { + UnregistrationRequest::Status status) { UMA_HISTOGRAM_ENUMERATION("InstanceID.DeleteToken.RequestStatus", status, UnregistrationRequest::UNREGISTRATION_STATUS_COUNT); - - // Other UMAs are only reported when the request succeeds. - if (status != UnregistrationRequest::SUCCESS) - return; - - UMA_HISTOGRAM_COUNTS_1M("InstanceID.DeleteToken.RetryCount", retry_count); - UMA_HISTOGRAM_TIMES("InstanceID.DeleteToken.CompleteTime", complete_time); } } // namespace gcm diff --git a/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.h b/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.h index 4783526cb34..73bf76c4317 100644 --- a/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.h +++ b/chromium/google_apis/gcm/engine/instance_id_delete_token_request_handler.h @@ -27,9 +27,7 @@ class GCM_EXPORT InstanceIDDeleteTokenRequestHandler : void BuildRequestBody(std::string* body) override; UnregistrationRequest::Status ParseResponse( const std::string& response) override; - void ReportUMAs(UnregistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) override; + void ReportUMAs(UnregistrationRequest::Status status) override; private: std::string instance_id_; diff --git a/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.cc b/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.cc index 7bde28aaa1e..9996641b3d6 100644 --- a/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.cc +++ b/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.cc @@ -53,19 +53,10 @@ void InstanceIDGetTokenRequestHandler::BuildRequestBody(std::string* body){ } void InstanceIDGetTokenRequestHandler::ReportUMAs( - RegistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) { + RegistrationRequest::Status status) { UMA_HISTOGRAM_ENUMERATION("InstanceID.GetToken.RequestStatus", status, RegistrationRequest::STATUS_COUNT); - - // Other UMAs are only reported when the request succeeds. - if (status != RegistrationRequest::SUCCESS) - return; - - UMA_HISTOGRAM_COUNTS_1M("InstanceID.GetToken.RetryCount", retry_count); - UMA_HISTOGRAM_TIMES("InstanceID.GetToken.CompleteTime", complete_time); } } // namespace gcm diff --git a/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.h b/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.h index b539c71221c..0acb3552f6a 100644 --- a/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.h +++ b/chromium/google_apis/gcm/engine/instance_id_get_token_request_handler.h @@ -27,9 +27,7 @@ class GCM_EXPORT InstanceIDGetTokenRequestHandler : // RegistrationRequest overrides: void BuildRequestBody(std::string* body) override; - void ReportUMAs(RegistrationRequest::Status status, - int retry_count, - base::TimeDelta complete_time) override; + void ReportUMAs(RegistrationRequest::Status status) override; private: std::string instance_id_; diff --git a/chromium/google_apis/gcm/engine/mcs_client.cc b/chromium/google_apis/gcm/engine/mcs_client.cc index a7c470bd084..16d98e60542 100644 --- a/chromium/google_apis/gcm/engine/mcs_client.cc +++ b/chromium/google_apis/gcm/engine/mcs_client.cc @@ -13,7 +13,6 @@ #include "base/location.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/clock.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -165,6 +164,7 @@ MCSClient::MCSClient(const std::string& version_string, base::Clock* clock, ConnectionFactory* connection_factory, GCMStore* gcm_store, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder) : version_string_(version_string), clock_(clock), @@ -178,8 +178,13 @@ MCSClient::MCSClient(const std::string& version_string, stream_id_out_(0), stream_id_in_(0), gcm_store_(gcm_store), + io_task_runner_(io_task_runner), + heartbeat_manager_(std::move(base::ThreadTaskRunnerHandle::Get()), + std::move(io_task_runner)), recorder_(recorder), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + DCHECK(io_task_runner_); +} MCSClient::~MCSClient() { } @@ -287,6 +292,7 @@ void MCSClient::Initialize( } void MCSClient::Login(uint64_t android_id, uint64_t security_token) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK_EQ(state_, LOADED); DCHECK(android_id_ == 0 || android_id_ == android_id); DCHECK(security_token_ == 0 || security_token_ == security_token); @@ -528,6 +534,7 @@ void MCSClient::OnGCMUpdateFinished(bool success) { } void MCSClient::MaybeSendMessage() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); if (to_send_.empty()) return; @@ -548,9 +555,9 @@ void MCSClient::MaybeSendMessage() { packet->persistent_id, base::Bind(&MCSClient::OnGCMUpdateFinished, weak_ptr_factory_.GetWeakPtr())); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&MCSClient::MaybeSendMessage, - weak_ptr_factory_.GetWeakPtr())); + io_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&MCSClient::MaybeSendMessage, + weak_ptr_factory_.GetWeakPtr())); return; } DVLOG(1) << "Pending output message found, sending."; @@ -721,13 +728,13 @@ void MCSClient::HandlePacketFromWire( DCHECK_EQ(1U, stream_id_out_); // Pass the login response on up. - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(message_received_callback_, MCSMessage(tag, std::move(protobuf)))); // If there are pending messages, attempt to send one. if (!to_send_.empty()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&MCSClient::MaybeSendMessage, weak_ptr_factory_.GetWeakPtr())); } @@ -790,7 +797,7 @@ void MCSClient::HandlePacketFromWire( } DCHECK(protobuf.get()); - base::ThreadTaskRunnerHandle::Get()->PostTask( + io_task_runner_->PostTask( FROM_HERE, base::BindOnce(message_received_callback_, MCSMessage(tag, std::move(protobuf)))); return; @@ -826,6 +833,8 @@ void MCSClient::HandleStreamAck(StreamId last_stream_id_received) { } void MCSClient::HandleSelectiveAck(const PersistentIdList& id_list) { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); + std::set<PersistentId> remaining_ids(id_list.begin(), id_list.end()); StreamId last_stream_id_received = 0; @@ -897,9 +906,9 @@ void MCSClient::HandleSelectiveAck(const PersistentIdList& id_list) { to_send_.push_front(std::move(to_resend_.back())); to_resend_.pop_back(); } - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&MCSClient::MaybeSendMessage, - weak_ptr_factory_.GetWeakPtr())); + io_task_runner_->PostTask(FROM_HERE, + base::BindOnce(&MCSClient::MaybeSendMessage, + weak_ptr_factory_.GetWeakPtr())); } void MCSClient::HandleServerConfirmedReceipt(StreamId device_stream_id) { diff --git a/chromium/google_apis/gcm/engine/mcs_client.h b/chromium/google_apis/gcm/engine/mcs_client.h index 1fecfa57b92..344855ae54c 100644 --- a/chromium/google_apis/gcm/engine/mcs_client.h +++ b/chromium/google_apis/gcm/engine/mcs_client.h @@ -102,6 +102,7 @@ class GCM_EXPORT MCSClient { base::Clock* clock, ConnectionFactory* connection_factory, GCMStore* gcm_store, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder); virtual ~MCSClient(); @@ -297,6 +298,8 @@ class GCM_EXPORT MCSClient { // The GCM persistent store. Not owned. GCMStore* gcm_store_; + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Manager to handle triggering/detecting heartbeats. HeartbeatManager heartbeat_manager_; diff --git a/chromium/google_apis/gcm/engine/mcs_client_unittest.cc b/chromium/google_apis/gcm/engine/mcs_client_unittest.cc index a03227db1da..39c7fd150f9 100644 --- a/chromium/google_apis/gcm/engine/mcs_client_unittest.cc +++ b/chromium/google_apis/gcm/engine/mcs_client_unittest.cc @@ -15,9 +15,9 @@ #include "base/command_line.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "base/timer/timer.h" #include "google_apis/gcm/base/fake_encryptor.h" @@ -90,10 +90,15 @@ class TestMCSClient : public MCSClient { TestMCSClient(base::Clock* clock, ConnectionFactory* connection_factory, GCMStore* gcm_store, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, gcm::GCMStatsRecorder* recorder) - : MCSClient("", clock, connection_factory, gcm_store, recorder), - next_id_(0) { - } + : MCSClient("", + clock, + connection_factory, + gcm_store, + io_task_runner, + recorder), + next_id_(0) {} std::string GetNextPersistentId() override { return base::NumberToString(++next_id_); @@ -168,7 +173,7 @@ class MCSClientTest : public testing::Test { base::SimpleTestClock clock_; base::ScopedTempDir temp_directory_; - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<GCMStore> gcm_store_; @@ -205,12 +210,12 @@ void MCSClientTest::SetUp() { void MCSClientTest::BuildMCSClient() { gcm_store_.reset( - new GCMStoreImpl(temp_directory_.GetPath(), message_loop_.task_runner(), + new GCMStoreImpl(temp_directory_.GetPath(), + scoped_task_environment_.GetMainThreadTaskRunner(), base::WrapUnique<Encryptor>(new FakeEncryptor))); - mcs_client_.reset(new TestMCSClient(&clock_, - &connection_factory_, - gcm_store_.get(), - &recorder_)); + mcs_client_.reset( + new TestMCSClient(&clock_, &connection_factory_, gcm_store_.get(), + base::ThreadTaskRunnerHandle::Get(), &recorder_)); } void MCSClientTest::InitializeClient() { diff --git a/chromium/google_apis/gcm/engine/registration_request.cc b/chromium/google_apis/gcm/engine/registration_request.cc index e5085607e3b..620e11551fb 100644 --- a/chromium/google_apis/gcm/engine/registration_request.cc +++ b/chromium/google_apis/gcm/engine/registration_request.cc @@ -12,7 +12,6 @@ #include "base/metrics/histogram.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "google_apis/gcm/base/gcm_util.h" #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" @@ -124,6 +123,7 @@ RegistrationRequest::RegistrationRequest( const RegistrationCallback& callback, int max_retry_count, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, const std::string& source_to_record) : callback_(callback), @@ -133,9 +133,11 @@ RegistrationRequest::RegistrationRequest( backoff_entry_(&backoff_policy), url_loader_factory_(std::move(url_loader_factory)), retries_left_(max_retry_count), + io_task_runner_(io_task_runner), recorder_(recorder), source_to_record_(source_to_record), weak_ptr_factory_(this) { + DCHECK(io_task_runner_); DCHECK_GE(max_retry_count, 0); } @@ -189,7 +191,6 @@ void RegistrationRequest::Start() { network::SimpleURLLoader::Create(std::move(request), traffic_annotation); url_loader_->AttachStringForUpload(body, kRegistrationRequestContentType); recorder_->RecordRegistrationSent(request_info_.app_id(), source_to_record_); - request_start_time_ = base::TimeTicks::Now(); url_loader_->SetAllowHttpErrorResults(true); url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_factory_.get(), @@ -218,6 +219,7 @@ void RegistrationRequest::BuildRequestBody(std::string* body) { } void RegistrationRequest::RetryWithBackoff() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK_GT(retries_left_, 0); --retries_left_; url_loader_.reset(); @@ -230,7 +232,7 @@ void RegistrationRequest::RetryWithBackoff() { request_info_.app_id(), source_to_record_, backoff_entry_.GetTimeUntilRelease().InMilliseconds(), retries_left_ + 1); DCHECK(!weak_ptr_factory_.HasWeakPtrs()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&RegistrationRequest::Start, weak_ptr_factory_.GetWeakPtr()), @@ -295,10 +297,7 @@ void RegistrationRequest::OnURLLoadComplete( source_to_record_, status); DCHECK(custom_request_handler_.get()); - custom_request_handler_->ReportUMAs( - status, - backoff_entry_.failure_count(), - base::TimeTicks::Now() - request_start_time_); + custom_request_handler_->ReportUMAs(status); if (ShouldRetryWithStatus(status)) { if (retries_left_ > 0) { @@ -310,10 +309,8 @@ void RegistrationRequest::OnURLLoadComplete( recorder_->RecordRegistrationResponse(request_info_.app_id(), source_to_record_, status); - // Only REACHED_MAX_RETRIES is reported because the function will skip - // reporting count and time when status is not SUCCESS. DCHECK(custom_request_handler_.get()); - custom_request_handler_->ReportUMAs(status, 0, base::TimeDelta()); + custom_request_handler_->ReportUMAs(status); } callback_.Run(status, token); diff --git a/chromium/google_apis/gcm/engine/registration_request.h b/chromium/google_apis/gcm/engine/registration_request.h index 7349e5a5d7d..650290c8898 100644 --- a/chromium/google_apis/gcm/engine/registration_request.h +++ b/chromium/google_apis/gcm/engine/registration_request.h @@ -16,7 +16,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/time/time.h" #include "google_apis/gcm/base/gcm_export.h" #include "net/base/backoff_entry.h" #include "url/gurl.h" @@ -107,10 +106,8 @@ class GCM_EXPORT RegistrationRequest { // |body|. Note that the request body is encoded in HTTP form format. virtual void BuildRequestBody(std::string* body) = 0; - // Reports various UMAs, including status, retry count and completion time. - virtual void ReportUMAs(Status status, - int retry_count, - base::TimeDelta complete_time) = 0; + // Reports various UMAs. + virtual void ReportUMAs(Status status) = 0; }; RegistrationRequest( @@ -121,6 +118,7 @@ class GCM_EXPORT RegistrationRequest { const RegistrationCallback& callback, int max_retry_count, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, const std::string& source_to_record); ~RegistrationRequest(); @@ -153,7 +151,8 @@ class GCM_EXPORT RegistrationRequest { scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; std::unique_ptr<network::SimpleURLLoader> url_loader_; int retries_left_; - base::TimeTicks request_start_time_; + + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; // Recorder that records GCM activities for debugging purpose. Not owned. GCMStatsRecorder* recorder_; diff --git a/chromium/google_apis/gcm/engine/registration_request_unittest.cc b/chromium/google_apis/gcm/engine/registration_request_unittest.cc index 1751e21f779..d325019a275 100644 --- a/chromium/google_apis/gcm/engine/registration_request_unittest.cc +++ b/chromium/google_apis/gcm/engine/registration_request_unittest.cc @@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" +#include "base/threading/thread_task_runner_handle.h" #include "google_apis/gcm/engine/gcm_registration_request_handler.h" #include "google_apis/gcm/engine/gcm_request_test_base.h" #include "google_apis/gcm/engine/instance_id_get_token_request_handler.h" @@ -107,7 +108,8 @@ void GCMRegistrationRequestTest::CreateRequest(const std::string& sender_ids) { GetBackoffPolicy(), base::Bind(&RegistrationRequestTest::RegistrationCallback, base::Unretained(this)), - max_retry_count_, url_loader_factory(), &recorder_, sender_ids)); + max_retry_count_, url_loader_factory(), + base::ThreadTaskRunnerHandle::Get(), &recorder_, sender_ids)); } TEST_F(GCMRegistrationRequestTest, RequestSuccessful) { @@ -430,7 +432,8 @@ void InstanceIDGetTokenRequestTest::CreateRequest( GetBackoffPolicy(), base::Bind(&RegistrationRequestTest::RegistrationCallback, base::Unretained(this)), - max_retry_count_, url_loader_factory(), &recorder_, authorized_entity)); + max_retry_count_, url_loader_factory(), + base::ThreadTaskRunnerHandle::Get(), &recorder_, authorized_entity)); } TEST_F(InstanceIDGetTokenRequestTest, RequestSuccessful) { diff --git a/chromium/google_apis/gcm/engine/unregistration_request.cc b/chromium/google_apis/gcm/engine/unregistration_request.cc index ee5d914d8ed..6bfa4ff697b 100644 --- a/chromium/google_apis/gcm/engine/unregistration_request.cc +++ b/chromium/google_apis/gcm/engine/unregistration_request.cc @@ -11,7 +11,6 @@ #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "google_apis/gcm/base/gcm_util.h" #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" @@ -109,6 +108,7 @@ UnregistrationRequest::UnregistrationRequest( const UnregistrationCallback& callback, int max_retry_count, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, const std::string& source_to_record) : callback_(callback), @@ -118,9 +118,11 @@ UnregistrationRequest::UnregistrationRequest( backoff_entry_(&backoff_policy), url_loader_factory_(std::move(url_loader_factory)), retries_left_(max_retry_count), + io_task_runner_(io_task_runner), recorder_(recorder), source_to_record_(source_to_record), weak_ptr_factory_(this) { + DCHECK(io_task_runner_); DCHECK_GE(max_retry_count, 0); } @@ -175,7 +177,6 @@ void UnregistrationRequest::Start() { DVLOG(1) << "Performing unregistration for: " << request_info_.app_id(); recorder_->RecordUnregistrationSent(request_info_.app_id(), source_to_record_); - request_start_time_ = base::TimeTicks::Now(); url_loader_->SetAllowHttpErrorResults(true); url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_factory_.get(), @@ -245,6 +246,7 @@ UnregistrationRequest::Status UnregistrationRequest::ParseResponse( } void UnregistrationRequest::RetryWithBackoff() { + DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK_GT(retries_left_, 0); --retries_left_; url_loader_.reset(); @@ -257,7 +259,7 @@ void UnregistrationRequest::RetryWithBackoff() { request_info_.app_id(), source_to_record_, backoff_entry_.GetTimeUntilRelease().InMilliseconds(), retries_left_ + 1); DCHECK(!weak_ptr_factory_.HasWeakPtrs()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + io_task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&UnregistrationRequest::Start, weak_ptr_factory_.GetWeakPtr()), @@ -272,10 +274,7 @@ void UnregistrationRequest::OnURLLoadComplete( DVLOG(1) << "UnregistrationRequestStatus: " << status; DCHECK(custom_request_handler_.get()); - custom_request_handler_->ReportUMAs( - status, - backoff_entry_.failure_count(), - base::TimeTicks::Now() - request_start_time_); + custom_request_handler_->ReportUMAs(status); recorder_->RecordUnregistrationResponse(request_info_.app_id(), source_to_record_, status); @@ -290,10 +289,8 @@ void UnregistrationRequest::OnURLLoadComplete( recorder_->RecordUnregistrationResponse(request_info_.app_id(), source_to_record_, status); - // Only REACHED_MAX_RETRIES is reported because the function will skip - // reporting count and time when status is not SUCCESS. DCHECK(custom_request_handler_.get()); - custom_request_handler_->ReportUMAs(status, 0, base::TimeDelta()); + custom_request_handler_->ReportUMAs(status); } callback_.Run(status); diff --git a/chromium/google_apis/gcm/engine/unregistration_request.h b/chromium/google_apis/gcm/engine/unregistration_request.h index bc74ef7663e..eb3ae4242f5 100644 --- a/chromium/google_apis/gcm/engine/unregistration_request.h +++ b/chromium/google_apis/gcm/engine/unregistration_request.h @@ -13,7 +13,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/time/time.h" #include "google_apis/gcm/base/gcm_export.h" #include "net/base/backoff_entry.h" #include "url/gurl.h" @@ -102,10 +101,8 @@ class GCM_EXPORT UnregistrationRequest { // UnregistrationRequest::ParseResponse to proceed the parsing. virtual Status ParseResponse(const std::string& response) = 0; - // Reports various UMAs, including status, retry count and completion time. - virtual void ReportUMAs(Status status, - int retry_count, - base::TimeDelta complete_time) = 0; + // Reports UMAs. + virtual void ReportUMAs(Status status) = 0; }; // Creates an instance of UnregistrationRequest. |callback| will be called @@ -119,6 +116,7 @@ class GCM_EXPORT UnregistrationRequest { const UnregistrationCallback& callback, int max_retry_count, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + scoped_refptr<base::SequencedTaskRunner> io_task_runner, GCMStatsRecorder* recorder, const std::string& source_to_record); ~UnregistrationRequest(); @@ -147,9 +145,10 @@ class GCM_EXPORT UnregistrationRequest { net::BackoffEntry backoff_entry_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; std::unique_ptr<network::SimpleURLLoader> url_loader_; - base::TimeTicks request_start_time_; int retries_left_; + const scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + // Recorder that records GCM activities for debugging purpose. Not owned. GCMStatsRecorder* recorder_; std::string source_to_record_; diff --git a/chromium/google_apis/gcm/engine/unregistration_request_unittest.cc b/chromium/google_apis/gcm/engine/unregistration_request_unittest.cc index 66b48c63152..16a354330ee 100644 --- a/chromium/google_apis/gcm/engine/unregistration_request_unittest.cc +++ b/chromium/google_apis/gcm/engine/unregistration_request_unittest.cc @@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" +#include "base/threading/thread_task_runner_handle.h" #include "google_apis/gcm/engine/gcm_request_test_base.h" #include "google_apis/gcm/engine/gcm_unregistration_request_handler.h" #include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h" @@ -102,7 +103,8 @@ void GCMUnregistrationRequestTest::CreateRequest() { GetBackoffPolicy(), base::Bind(&UnregistrationRequestTest::UnregistrationCallback, base::Unretained(this)), - max_retry_count_, url_loader_factory(), &recorder_, std::string())); + max_retry_count_, url_loader_factory(), + base::ThreadTaskRunnerHandle::Get(), &recorder_, std::string())); } TEST_F(GCMUnregistrationRequestTest, RequestDataPassedToFetcher) { @@ -318,7 +320,8 @@ void InstaceIDDeleteTokenRequestTest::CreateRequest( GetBackoffPolicy(), base::Bind(&UnregistrationRequestTest::UnregistrationCallback, base::Unretained(this)), - max_retry_count(), url_loader_factory(), &recorder_, std::string())); + max_retry_count(), url_loader_factory(), + base::ThreadTaskRunnerHandle::Get(), &recorder_, std::string())); } TEST_F(InstaceIDDeleteTokenRequestTest, RequestDataPassedToFetcher) { diff --git a/chromium/google_apis/gcm/tools/mcs_probe.cc b/chromium/google_apis/gcm/tools/mcs_probe.cc index 4c29c170337..85853170edb 100644 --- a/chromium/google_apis/gcm/tools/mcs_probe.cc +++ b/chromium/google_apis/gcm/tools/mcs_probe.cc @@ -22,9 +22,9 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/task/single_thread_task_executor.h" #include "base/task/thread_pool/thread_pool.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" @@ -282,14 +282,15 @@ void MCSProbe::Start() { endpoints, kDefaultBackoffPolicy, base::BindRepeating(&MCSProbe::RequestProxyResolvingSocketFactory, base::Unretained(this)), - &recorder_, network_connection_tracker_.get()); + base::ThreadTaskRunnerHandle::Get(), &recorder_, + network_connection_tracker_.get()); gcm_store_ = std::make_unique<GCMStoreImpl>( gcm_store_path_, file_thread_.task_runner(), std::make_unique<FakeEncryptor>()); - mcs_client_ = - std::make_unique<MCSClient>("probe", &clock_, connection_factory_.get(), - gcm_store_.get(), &recorder_); + mcs_client_ = std::make_unique<MCSClient>( + "probe", &clock_, connection_factory_.get(), gcm_store_.get(), + base::ThreadTaskRunnerHandle::Get(), &recorder_); run_loop_ = std::make_unique<base::RunLoop>(); gcm_store_->Load(GCMStore::CREATE_IF_MISSING, base::Bind(&MCSProbe::LoadCallback, @@ -334,7 +335,7 @@ void MCSProbe::InitializeNetworkState() { base::FilePath log_path = command_line_.GetSwitchValuePath(kLogFileSwitch); logger_ = net::FileNetLogObserver::CreateUnbounded(log_path, nullptr); net::NetLogCaptureMode capture_mode = - net::NetLogCaptureMode::IncludeCookiesAndCredentials(); + net::NetLogCaptureMode::kIncludeSensitive; logger_->StartObserving(&net_log_, capture_mode); } @@ -398,7 +399,8 @@ void MCSProbe::CheckIn() { checkin_request_ = std::make_unique<CheckinRequest>( GServicesSettings().GetCheckinURL(), request_info, kDefaultBackoffPolicy, base::Bind(&MCSProbe::OnCheckInCompleted, base::Unretained(this)), - shared_url_loader_factory_, &recorder_); + shared_url_loader_factory_, base::ThreadTaskRunnerHandle::Get(), + &recorder_); checkin_request_->Start(); } @@ -444,7 +446,7 @@ int MCSProbeMain(int argc, char* argv[]) { mojo::core::Init(); - base::MessageLoopForIO message_loop; + base::SingleThreadTaskExecutor io_task_executor(base::MessagePump::Type::IO); base::ThreadPoolInstance::CreateAndStartWithDefaultParams("MCSProbe"); const base::CommandLine& command_line = |