diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:20:33 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:28:57 +0000 |
commit | d17ea114e5ef69ad5d5d7413280a13e6428098aa (patch) | |
tree | 2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/google_apis | |
parent | 8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff) | |
download | qtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz |
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/google_apis')
25 files changed, 501 insertions, 483 deletions
diff --git a/chromium/google_apis/BUILD.gn b/chromium/google_apis/BUILD.gn index ced1cef4c71..0f966c6a50a 100644 --- a/chromium/google_apis/BUILD.gn +++ b/chromium/google_apis/BUILD.gn @@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/config/features.gni") -import("//extensions/features/features.gni") +import("//extensions/buildflags/buildflags.gni") import("//testing/test.gni") declare_args() { diff --git a/chromium/google_apis/drive/drive_api_url_generator_unittest.cc b/chromium/google_apis/drive/drive_api_url_generator_unittest.cc index f2f4523098c..cb5490e9c74 100644 --- a/chromium/google_apis/drive/drive_api_url_generator_unittest.cc +++ b/chromium/google_apis/drive/drive_api_url_generator_unittest.cc @@ -29,7 +29,11 @@ class DriveApiUrlGeneratorTest : public testing::Test { TEAM_DRIVES_INTEGRATION_DISABLED), team_drives_url_generator_(GURL(kBaseUrlForTesting), GURL(kBaseThumbnailUrlForTesting), - TEAM_DRIVES_INTEGRATION_ENABLED) {} + TEAM_DRIVES_INTEGRATION_ENABLED) { + url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST); + } + + ~DriveApiUrlGeneratorTest() override { url::Shutdown(); } protected: DriveApiUrlGenerator url_generator_; @@ -75,7 +79,6 @@ TEST_F(DriveApiUrlGeneratorTest, GetFilesGetUrl) { url_generator_.GetFilesGetUrl("0ADK06pfg", true, GURL()).spec()); // If |embed_origin| is not empty, it should be added as a query parameter. - url::AddStandardScheme("chrome-extension", url::SCHEME_WITHOUT_PORT); EXPECT_EQ( "https://www.example.com/drive/v2/files/0ADK06pfg" "?embedOrigin=chrome-extension%3A%2F%2Ftest", diff --git a/chromium/google_apis/gaia/account_tracker.cc b/chromium/google_apis/gaia/account_tracker.cc index bfab026090e..c859c2e97c7 100644 --- a/chromium/google_apis/gaia/account_tracker.cc +++ b/chromium/google_apis/gaia/account_tracker.cc @@ -52,8 +52,7 @@ std::vector<AccountIds> AccountTracker::GetAccounts() const { for (std::map<std::string, AccountState>::const_iterator it = accounts_.begin(); - it != accounts_.end(); - ++it) { + it != accounts_.end(); ++it) { const AccountState& state = it->second; bool is_visible = state.is_signed_in && !state.ids.gaia.empty(); @@ -71,10 +70,8 @@ std::vector<AccountIds> AccountTracker::GetAccounts() const { } void AccountTracker::OnRefreshTokenAvailable(const std::string& account_id) { - TRACE_EVENT1("identity", - "AccountTracker::OnRefreshTokenAvailable", - "account_key", - account_id); + TRACE_EVENT1("identity", "AccountTracker::OnRefreshTokenAvailable", + "account_key", account_id); // Ignore refresh tokens if there is no active account ID at all. if (identity_provider_->GetActiveAccountId().empty()) @@ -85,10 +82,8 @@ void AccountTracker::OnRefreshTokenAvailable(const std::string& account_id) { } void AccountTracker::OnRefreshTokenRevoked(const std::string& account_id) { - TRACE_EVENT1("identity", - "AccountTracker::OnRefreshTokenRevoked", - "account_key", - account_id); + TRACE_EVENT1("identity", "AccountTracker::OnRefreshTokenRevoked", + "account_key", account_id); DVLOG(1) << "REVOKED " << account_id; UpdateSignInState(account_id, false); @@ -103,8 +98,7 @@ void AccountTracker::OnActiveAccountLogin() { DVLOG(1) << "LOGIN " << accounts.size() << " accounts available."; for (std::vector<std::string>::const_iterator it = accounts.begin(); - it != accounts.end(); - ++it) { + it != accounts.end(); ++it) { OnRefreshTokenAvailable(*it); } } @@ -125,8 +119,7 @@ void AccountTracker::SetAccountStateForTest(AccountIds ids, bool is_signed_in) { if (VLOG_IS_ON(1)) { for (std::map<std::string, AccountState>::const_iterator it = accounts_.begin(); - it != accounts_.end(); - ++it) { + it != accounts_.end(); ++it) { DVLOG(1) << it->first << ":" << it->second.is_signed_in; } } @@ -191,9 +184,7 @@ void AccountTracker::StartFetchingUserInfo(const std::string& account_key) { DVLOG(1) << "StartFetching " << account_key; AccountIdFetcher* fetcher = new AccountIdFetcher(identity_provider_->GetTokenService(), - request_context_getter_.get(), - this, - account_key); + request_context_getter_.get(), this, account_key); user_info_requests_[account_key] = base::WrapUnique(fetcher); fetcher->Start(); } @@ -237,8 +228,8 @@ AccountIdFetcher::AccountIdFetcher( request_context_getter_(request_context_getter), tracker_(tracker), account_key_(account_key) { - TRACE_EVENT_ASYNC_BEGIN1( - "identity", "AccountIdFetcher", this, "account_key", account_key); + TRACE_EVENT_ASYNC_BEGIN1("identity", "AccountIdFetcher", this, "account_key", + account_key); } AccountIdFetcher::~AccountIdFetcher() { @@ -248,16 +239,16 @@ AccountIdFetcher::~AccountIdFetcher() { void AccountIdFetcher::Start() { OAuth2TokenService::ScopeSet scopes; scopes.insert("https://www.googleapis.com/auth/userinfo.profile"); - login_token_request_ = token_service_->StartRequest( - account_key_, scopes, this); + login_token_request_ = + token_service_->StartRequest(account_key_, scopes, this); } void AccountIdFetcher::OnGetTokenSuccess( const OAuth2TokenService::Request* request, const std::string& access_token, const base::Time& expiration_time) { - TRACE_EVENT_ASYNC_STEP_PAST0( - "identity", "AccountIdFetcher", this, "OnGetTokenSuccess"); + TRACE_EVENT_ASYNC_STEP_PAST0("identity", "AccountIdFetcher", this, + "OnGetTokenSuccess"); DCHECK_EQ(request, login_token_request_.get()); gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter_)); @@ -269,11 +260,8 @@ void AccountIdFetcher::OnGetTokenSuccess( void AccountIdFetcher::OnGetTokenFailure( const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) { - TRACE_EVENT_ASYNC_STEP_PAST1("identity", - "AccountIdFetcher", - this, - "OnGetTokenFailure", - "google_service_auth_error", + TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this, + "OnGetTokenFailure", "google_service_auth_error", error.ToString()); LOG(ERROR) << "OnGetTokenFailure: " << error.ToString(); DCHECK_EQ(request, login_token_request_.get()); @@ -281,28 +269,21 @@ void AccountIdFetcher::OnGetTokenFailure( } void AccountIdFetcher::OnGetUserIdResponse(const std::string& gaia_id) { - TRACE_EVENT_ASYNC_STEP_PAST1("identity", - "AccountIdFetcher", - this, - "OnGetUserIdResponse", - "gaia_id", - gaia_id); + TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this, + "OnGetUserIdResponse", "gaia_id", gaia_id); tracker_->OnUserInfoFetchSuccess(this, gaia_id); } void AccountIdFetcher::OnOAuthError() { - TRACE_EVENT_ASYNC_STEP_PAST0( - "identity", "AccountIdFetcher", this, "OnOAuthError"); + TRACE_EVENT_ASYNC_STEP_PAST0("identity", "AccountIdFetcher", this, + "OnOAuthError"); LOG(ERROR) << "OnOAuthError"; tracker_->OnUserInfoFetchFailure(this); } void AccountIdFetcher::OnNetworkError(int response_code) { - TRACE_EVENT_ASYNC_STEP_PAST1("identity", - "AccountIdFetcher", - this, - "OnNetworkError", - "response_code", + TRACE_EVENT_ASYNC_STEP_PAST1("identity", "AccountIdFetcher", this, + "OnNetworkError", "response_code", response_code); LOG(ERROR) << "OnNetworkError " << response_code; tracker_->OnUserInfoFetchFailure(this); diff --git a/chromium/google_apis/gaia/account_tracker.h b/chromium/google_apis/gaia/account_tracker.h index 19aa28f54e1..99cbaf6e6de 100644 --- a/chromium/google_apis/gaia/account_tracker.h +++ b/chromium/google_apis/gaia/account_tracker.h @@ -148,6 +148,6 @@ class AccountIdFetcher : public OAuth2TokenService::Consumer, std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; }; -} // namespace extensions +} // namespace gaia #endif // GOOGLE_APIS_GAIA_ACCOUNT_TRACKER_H_ diff --git a/chromium/google_apis/gaia/account_tracker_unittest.cc b/chromium/google_apis/gaia/account_tracker_unittest.cc index c4451c180a8..a3a999a7d24 100644 --- a/chromium/google_apis/gaia/account_tracker_unittest.cc +++ b/chromium/google_apis/gaia/account_tracker_unittest.cc @@ -22,10 +22,7 @@ namespace { const char kPrimaryAccountKey[] = "primary_account@example.com"; -enum TrackingEventType { - SIGN_IN, - SIGN_OUT -}; +enum TrackingEventType { SIGN_IN, SIGN_OUT }; std::string AccountKeyToObfuscatedId(const std::string& email) { return "obfid-" + email; @@ -36,23 +33,20 @@ class TrackingEvent { TrackingEvent(TrackingEventType type, const std::string& account_key, const std::string& gaia_id) - : type_(type), - account_key_(account_key), - gaia_id_(gaia_id) {} + : type_(type), account_key_(account_key), gaia_id_(gaia_id) {} - TrackingEvent(TrackingEventType type, - const std::string& account_key) + TrackingEvent(TrackingEventType type, const std::string& account_key) : type_(type), account_key_(account_key), gaia_id_(AccountKeyToObfuscatedId(account_key)) {} bool operator==(const TrackingEvent& event) const { return type_ == event.type_ && account_key_ == event.account_key_ && - gaia_id_ == event.gaia_id_; + gaia_id_ == event.gaia_id_; } std::string ToString() const { - const char * typestr = "INVALID"; + const char* typestr = "INVALID"; switch (type_) { case SIGN_IN: typestr = " IN"; @@ -61,10 +55,8 @@ class TrackingEvent { typestr = "OUT"; break; } - return base::StringPrintf("{ type: %s, email: %s, gaia: %s }", - typestr, - account_key_.c_str(), - gaia_id_.c_str()); + return base::StringPrintf("{ type: %s, email: %s, gaia: %s }", typestr, + account_key_.c_str(), gaia_id_.c_str()); } private: @@ -82,8 +74,8 @@ bool CompareByUser(TrackingEvent a, TrackingEvent b) { std::string Str(const std::vector<TrackingEvent>& events) { std::string str = "["; bool needs_comma = false; - for (std::vector<TrackingEvent>::const_iterator it = - events.begin(); it != events.end(); ++it) { + for (std::vector<TrackingEvent>::const_iterator it = events.begin(); + it != events.end(); ++it) { if (needs_comma) str += ",\n "; needs_comma = true; @@ -254,10 +246,9 @@ class IdentityAccountTrackerTest : public testing::Test { fake_identity_provider_.reset( new FakeIdentityProvider(fake_oauth2_token_service_.get())); - account_tracker_.reset( - new AccountTracker(fake_identity_provider_.get(), - new net::TestURLRequestContextGetter( - message_loop_.task_runner()))); + account_tracker_.reset(new AccountTracker( + fake_identity_provider_.get(), + new net::TestURLRequestContextGetter(message_loop_.task_runner()))); account_tracker_->AddObserver(&observer_); } @@ -266,13 +257,9 @@ class IdentityAccountTrackerTest : public testing::Test { account_tracker_->Shutdown(); } - AccountTrackerObserver* observer() { - return &observer_; - } + AccountTrackerObserver* observer() { return &observer_; } - AccountTracker* account_tracker() { - return account_tracker_.get(); - } + AccountTracker* account_tracker() { return account_tracker_.get(); } // Helpers to pass fake events to the tracker. @@ -338,8 +325,7 @@ class IdentityAccountTrackerTest : public testing::Test { void IdentityAccountTrackerTest::ReturnOAuthUrlFetchResults( int fetcher_id, net::HttpStatusCode response_code, - const std::string& response_string) { - + const std::string& response_string) { net::TestURLFetcher* fetcher = test_fetcher_factory_.GetFetcherByID(fetcher_id); ASSERT_TRUE(fetcher); @@ -351,16 +337,15 @@ void IdentityAccountTrackerTest::ReturnOAuthUrlFetchResults( void IdentityAccountTrackerTest::ReturnOAuthUrlFetchSuccess( const std::string& account_key) { IssueAccessToken(account_key); - ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, - net::HTTP_OK, + ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_OK, GetValidTokenInfoResponse(account_key)); } void IdentityAccountTrackerTest::ReturnOAuthUrlFetchFailure( const std::string& account_key) { IssueAccessToken(account_key); - ReturnOAuthUrlFetchResults( - gaia::GaiaOAuthClient::kUrlFetcherId, net::HTTP_BAD_REQUEST, ""); + ReturnOAuthUrlFetchResults(gaia::GaiaOAuthClient::kUrlFetcherId, + net::HTTP_BAD_REQUEST, ""); } // Primary tests just involve the Active account @@ -460,8 +445,8 @@ TEST_F(IdentityAccountTrackerTest, PrimaryLogoutFetchCancelAvailable) { NotifyLogin(kPrimaryAccountKey); NotifyTokenAvailable(kPrimaryAccountKey); ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, kPrimaryAccountKey))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey))); } // Non-primary accounts @@ -473,8 +458,8 @@ TEST_F(IdentityAccountTrackerTest, Available) { EXPECT_TRUE(observer()->CheckEvents()); ReturnOAuthUrlFetchSuccess("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"))); } TEST_F(IdentityAccountTrackerTest, Revoke) { @@ -490,13 +475,13 @@ TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyTokenRevoked("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"), - TrackingEvent(SIGN_OUT, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"), + TrackingEvent(SIGN_OUT, "user@example.com"))); NotifyTokenAvailable("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) { @@ -508,8 +493,8 @@ TEST_F(IdentityAccountTrackerTest, AvailableRevokeAvailableWithPendingFetch) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"))); } TEST_F(IdentityAccountTrackerTest, AvailableRevokeRevoke) { @@ -518,9 +503,9 @@ TEST_F(IdentityAccountTrackerTest, AvailableRevokeRevoke) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); NotifyTokenRevoked("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"), - TrackingEvent(SIGN_OUT, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"), + TrackingEvent(SIGN_OUT, "user@example.com"))); NotifyTokenRevoked("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); @@ -531,8 +516,8 @@ TEST_F(IdentityAccountTrackerTest, AvailableAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"))); NotifyTokenAvailable("user@example.com"); EXPECT_TRUE(observer()->CheckEvents()); @@ -543,21 +528,21 @@ TEST_F(IdentityAccountTrackerTest, TwoAccounts) { NotifyTokenAvailable("alpha@example.com"); ReturnOAuthUrlFetchSuccess("alpha@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "alpha@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "alpha@example.com"))); NotifyTokenAvailable("beta@example.com"); ReturnOAuthUrlFetchSuccess("beta@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "beta@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "beta@example.com"))); NotifyTokenRevoked("alpha@example.com"); EXPECT_TRUE( observer()->CheckEvents(TrackingEvent(SIGN_OUT, "alpha@example.com"))); NotifyTokenRevoked("beta@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_OUT, "beta@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_OUT, "beta@example.com"))); } TEST_F(IdentityAccountTrackerTest, AvailableTokenFetchFailAvailable) { @@ -569,8 +554,8 @@ TEST_F(IdentityAccountTrackerTest, AvailableTokenFetchFailAvailable) { NotifyTokenAvailable("user@example.com"); ReturnOAuthUrlFetchSuccess("user@example.com"); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "user@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "user@example.com"))); } TEST_F(IdentityAccountTrackerTest, MultiSignOutSignIn) { @@ -582,9 +567,9 @@ TEST_F(IdentityAccountTrackerTest, MultiSignOutSignIn) { ReturnOAuthUrlFetchSuccess("beta@example.com"); observer()->SortEventsByUser(); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "alpha@example.com"), - TrackingEvent(SIGN_IN, "beta@example.com"))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "alpha@example.com"), + TrackingEvent(SIGN_IN, "beta@example.com"))); NotifyLogout(); observer()->SortEventsByUser(); @@ -605,19 +590,19 @@ TEST_F(IdentityAccountTrackerTest, MultiSignOutSignIn) { ReturnOAuthUrlFetchSuccess("gamma@example.com"); ReturnOAuthUrlFetchSuccess(kPrimaryAccountKey); observer()->SortEventsByUser(); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, "beta@example.com"), - TrackingEvent(SIGN_IN, "gamma@example.com"), - TrackingEvent(SIGN_IN, kPrimaryAccountKey))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, "beta@example.com"), + TrackingEvent(SIGN_IN, "gamma@example.com"), + TrackingEvent(SIGN_IN, kPrimaryAccountKey))); // Revoking the primary token does not affect other accounts. NotifyTokenRevoked(kPrimaryAccountKey); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_OUT, kPrimaryAccountKey))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_OUT, kPrimaryAccountKey))); NotifyTokenAvailable(kPrimaryAccountKey); - EXPECT_TRUE(observer()->CheckEvents( - TrackingEvent(SIGN_IN, kPrimaryAccountKey))); + EXPECT_TRUE( + observer()->CheckEvents(TrackingEvent(SIGN_IN, kPrimaryAccountKey))); } // Primary/non-primary interactions diff --git a/chromium/google_apis/gaia/fake_gaia.cc b/chromium/google_apis/gaia/fake_gaia.cc index 5c130de2186..1e76b22b39a 100644 --- a/chromium/google_apis/gaia/fake_gaia.cc +++ b/chromium/google_apis/gaia/fake_gaia.cc @@ -149,6 +149,7 @@ void FakeGaia::MergeSessionParams::Update(const MergeSessionParams& update) { maybe_update_field(&MergeSessionParams::auth_code); maybe_update_field(&MergeSessionParams::refresh_token); maybe_update_field(&MergeSessionParams::access_token); + maybe_update_field(&MergeSessionParams::id_token); maybe_update_field(&MergeSessionParams::gaia_uber_token); maybe_update_field(&MergeSessionParams::session_sid_cookie); maybe_update_field(&MergeSessionParams::session_lsid_cookie); @@ -709,6 +710,8 @@ void FakeGaia::HandleAuthToken(const HttpRequest& request, device_id; response_dict.SetString("access_token", merge_session_params_.access_token); + if (!merge_session_params_.id_token.empty()) + response_dict.SetString("id_token", merge_session_params_.id_token); response_dict.SetInteger("expires_in", 3600); FormatJSONResponse(response_dict, http_response); return; diff --git a/chromium/google_apis/gaia/fake_gaia.h b/chromium/google_apis/gaia/fake_gaia.h index 9909539e7c1..fbb5ff9fcb0 100644 --- a/chromium/google_apis/gaia/fake_gaia.h +++ b/chromium/google_apis/gaia/fake_gaia.h @@ -67,10 +67,11 @@ class FakeGaia { // auth_code cookie value response for /o/oauth2/programmatic_auth call. std::string auth_code; - // OAuth2 refresh and access token generated by /oauth2/v4/token call + // OAuth2 refresh access and id token generated by /oauth2/v4/token call // with "...&grant_type=authorization_code". std::string refresh_token; std::string access_token; + std::string id_token; // Uber token response from /OAuthLogin call. std::string gaia_uber_token; diff --git a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc b/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc index 1ce991cb20a..4ae2b786524 100644 --- a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc +++ b/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.cc @@ -34,11 +34,11 @@ bool FakeOAuth2TokenServiceDelegate::RefreshTokenIsAvailable( return !GetRefreshToken(account_id).empty(); } -bool FakeOAuth2TokenServiceDelegate::RefreshTokenHasError( +GoogleServiceAuthError FakeOAuth2TokenServiceDelegate::GetAuthError( const std::string& account_id) const { auto it = refresh_tokens_.find(account_id); - // TODO(rogerta): should we distinguish between transient and persistent? - return it == refresh_tokens_.end() ? false : IsError(it->second->error); + return (it == refresh_tokens_.end()) ? GoogleServiceAuthError::AuthErrorNone() + : it->second->error; } std::string FakeOAuth2TokenServiceDelegate::GetRefreshToken( @@ -101,10 +101,14 @@ FakeOAuth2TokenServiceDelegate::GetRequestContext() const { return request_context_.get(); } -void FakeOAuth2TokenServiceDelegate::SetLastErrorForAccount( +void FakeOAuth2TokenServiceDelegate::UpdateAuthError( const std::string& account_id, const GoogleServiceAuthError& error) { + 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 index 0000f697469..45a80def350 100644 --- a/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.h +++ b/chromium/google_apis/gaia/fake_oauth2_token_service_delegate.h @@ -23,7 +23,10 @@ class FakeOAuth2TokenServiceDelegate : public OAuth2TokenServiceDelegate { // Overriden to make sure it works on Android. bool RefreshTokenIsAvailable(const std::string& account_id) const override; - bool RefreshTokenHasError(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; @@ -40,9 +43,6 @@ class FakeOAuth2TokenServiceDelegate : public OAuth2TokenServiceDelegate { request_context_ = request_context; } - void SetLastErrorForAccount(const std::string& account_id, - const GoogleServiceAuthError& error); - std::string GetRefreshToken(const std::string& account_id) const; private: diff --git a/chromium/google_apis/gaia/gaia_auth_consumer.h b/chromium/google_apis/gaia/gaia_auth_consumer.h index 542c145f89c..1ec5bde5560 100644 --- a/chromium/google_apis/gaia/gaia_auth_consumer.h +++ b/chromium/google_apis/gaia/gaia_auth_consumer.h @@ -65,6 +65,29 @@ class GaiaAuthConsumer { bool is_child_account; }; + // Possible server responses to a token revocation request. + // Used in UMA, do not delete or reorder values. + enum class TokenRevocationStatus { + // Token revocation succeeded. + kSuccess = 0, + // Network connection was canceled, no response was received. + kConnectionCanceled = 1, + // Network connection failed, no response was received. + kConnectionFailed = 2, + // Network connection timed out, no response was received. + kConnectionTimeout = 3, + // The token is unknown or invalid. + kInvalidToken = 4, + // The request was malformed. + kInvalidRequest = 5, + // Internal server error. + kServerError = 6, + // Other error. + kUnknownError = 7, + + kMaxValue = kUnknownError + }; + virtual ~GaiaAuthConsumer() {} virtual void OnClientLoginSuccess(const ClientLoginResult& result) {} @@ -79,7 +102,7 @@ class GaiaAuthConsumer { virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) {} virtual void OnClientOAuthFailure(const GoogleServiceAuthError& error) {} - virtual void OnOAuth2RevokeTokenCompleted() {} + virtual void OnOAuth2RevokeTokenCompleted(TokenRevocationStatus status) {} virtual void OnGetUserInfoSuccess(const UserInfoMap& data) {} virtual void OnGetUserInfoFailure(const GoogleServiceAuthError& error) {} diff --git a/chromium/google_apis/gaia/gaia_auth_fetcher.cc b/chromium/google_apis/gaia/gaia_auth_fetcher.cc index b15f2fec173..f4039e49bed 100644 --- a/chromium/google_apis/gaia/gaia_auth_fetcher.cc +++ b/chromium/google_apis/gaia/gaia_auth_fetcher.cc @@ -33,6 +33,7 @@ #include "net/url_request/url_request_status.h" namespace { + const int kLoadFlagsIgnoreCookies = net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES; @@ -89,6 +90,34 @@ void GetCookiesFromResponse(const net::HttpResponseHeaders* headers, } } +// Parses server responses for token revocation. +GaiaAuthConsumer::TokenRevocationStatus +GetTokenRevocationStatusFromResponseData(const std::string& data, + int response_code) { + if (response_code == net::HTTP_OK) + return GaiaAuthConsumer::TokenRevocationStatus::kSuccess; + + if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) + return GaiaAuthConsumer::TokenRevocationStatus::kServerError; + + std::unique_ptr<base::Value> value = base::JSONReader::Read(data); + if (!value.get() || value->type() != base::Value::Type::DICTIONARY) + return GaiaAuthConsumer::TokenRevocationStatus::kUnknownError; + + base::DictionaryValue* dict = + static_cast<base::DictionaryValue*>(value.get()); + std::string error; + if (!dict->GetStringWithoutPathExpansion("error", &error)) + return GaiaAuthConsumer::TokenRevocationStatus::kUnknownError; + + if (error == "invalid_token") + return GaiaAuthConsumer::TokenRevocationStatus::kInvalidToken; + if (error == "invalid_request") + return GaiaAuthConsumer::TokenRevocationStatus::kInvalidRequest; + + return GaiaAuthConsumer::TokenRevocationStatus::kUnknownError; +} + } // namespace // static @@ -900,7 +929,9 @@ GoogleServiceAuthError GaiaAuthFetcher::GenerateAuthError( return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED); if (error == kBadAuthenticationError) { return GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); + GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER)); } if (error == kServiceUnavailableError) { return GoogleServiceAuthError( @@ -969,7 +1000,30 @@ void GaiaAuthFetcher::OnOAuth2RevokeTokenFetched( const std::string& data, const net::URLRequestStatus& status, int response_code) { - consumer_->OnOAuth2RevokeTokenCompleted(); + GaiaAuthConsumer::TokenRevocationStatus revocation_status = + GaiaAuthConsumer::TokenRevocationStatus::kUnknownError; + + switch (status.status()) { + case net::URLRequestStatus::SUCCESS: + revocation_status = + GetTokenRevocationStatusFromResponseData(data, response_code); + break; + case net::URLRequestStatus::IO_PENDING: + NOTREACHED(); + break; + case net::URLRequestStatus::FAILED: + revocation_status = + (status.ToNetError() == net::ERR_TIMED_OUT) + ? GaiaAuthConsumer::TokenRevocationStatus::kConnectionTimeout + : GaiaAuthConsumer::TokenRevocationStatus::kConnectionFailed; + break; + case net::URLRequestStatus::CANCELED: + revocation_status = + GaiaAuthConsumer::TokenRevocationStatus::kConnectionCanceled; + break; + } + + consumer_->OnOAuth2RevokeTokenCompleted(revocation_status); } void GaiaAuthFetcher::OnListAccountsFetched(const std::string& data, diff --git a/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc b/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc index 68340c049a9..9f47cc81da7 100644 --- a/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc +++ b/chromium/google_apis/gaia/gaia_auth_fetcher_unittest.cc @@ -187,6 +187,8 @@ class MockGaiaConsumer : public GaiaAuthConsumer { const GoogleServiceAuthError& error)); MOCK_METHOD1(OnClientOAuthFailure, void(const GoogleServiceAuthError& error)); + MOCK_METHOD1(OnOAuth2RevokeTokenCompleted, + void(GaiaAuthConsumer::TokenRevocationStatus status)); MOCK_METHOD1(OnMergeSessionFailure, void( const GoogleServiceAuthError& error)); MOCK_METHOD1(OnUberAuthTokenFailure, void( @@ -685,3 +687,110 @@ TEST_F(GaiaAuthFetcherTest, GetCheckConnectionInfo) { status, net::HTTP_OK, data, net::URLFetcher::GET, &auth); auth.OnURLFetchComplete(&mock_fetcher); } + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenSuccess) { + std::string data("{}"); + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kSuccess)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + net::HTTP_OK, data, net::URLFetcher::GET, &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenCanceled) { + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kConnectionCanceled)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + net::URLRequestStatus status(net::URLRequestStatus::CANCELED, + net::ERR_ABORTED); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + 0, std::string(), net::URLFetcher::GET, &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenFailed) { + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kConnectionFailed)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + int error_no = net::ERR_CERT_CONTAINS_ERRORS; + net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + 0, std::string(), net::URLFetcher::GET, &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenTimeout) { + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kConnectionTimeout)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + int error_no = net::ERR_TIMED_OUT; + net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + 0, std::string(), net::URLFetcher::GET, &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenInvalidToken) { + std::string data("{\"error\" : \"invalid_token\"}"); + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kInvalidToken)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + net::HTTP_BAD_REQUEST, data, net::URLFetcher::GET, + &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenInvalidRequest) { + std::string data("{\"error\" : \"invalid_request\"}"); + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kInvalidRequest)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + net::HTTP_BAD_REQUEST, data, net::URLFetcher::GET, + &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} + +TEST_F(GaiaAuthFetcherTest, RevokeOAuth2TokenServerError) { + std::string data("{}"); + MockGaiaConsumer consumer; + EXPECT_CALL(consumer, + OnOAuth2RevokeTokenCompleted( + GaiaAuthConsumer::TokenRevocationStatus::kServerError)) + .Times(1); + + GaiaAuthFetcher auth(&consumer, std::string(), GetRequestContext()); + net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); + MockFetcher mock_fetcher(GaiaUrls::GetInstance()->oauth2_revoke_url(), status, + net::HTTP_INTERNAL_SERVER_ERROR, data, + net::URLFetcher::GET, &auth); + auth.OnURLFetchComplete(&mock_fetcher); +} diff --git a/chromium/google_apis/gaia/google_service_auth_error.cc b/chromium/google_apis/gaia/google_service_auth_error.cc index 79f445caf88..d28bc258fb9 100644 --- a/chromium/google_apis/gaia/google_service_auth_error.cc +++ b/chromium/google_apis/gaia/google_service_auth_error.cc @@ -8,11 +8,8 @@ #include <string> #include <utility> -#include "base/json/json_reader.h" #include "base/logging.h" -#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/values.h" #include "net/base/net_errors.h" GoogleServiceAuthError::Captcha::Captcha() : image_width(0), image_height(0) { @@ -77,23 +74,17 @@ bool GoogleServiceAuthError::operator!=( } GoogleServiceAuthError::GoogleServiceAuthError() - : state_(NONE), network_error_(0) {} + : GoogleServiceAuthError(NONE) {} GoogleServiceAuthError::GoogleServiceAuthError(State s) - : state_(s), - network_error_(0) { - // If the caller has no idea, then we just set it to a generic failure. - if (s == CONNECTION_FAILED) { - network_error_ = net::ERR_FAILED; - } -} - -GoogleServiceAuthError::GoogleServiceAuthError( - State state, - const std::string& error_message) - : state_(state), - network_error_(0), - error_message_(error_message) { + : GoogleServiceAuthError(s, std::string()) {} + +GoogleServiceAuthError::GoogleServiceAuthError(State state, + const std::string& error_message) + : GoogleServiceAuthError( + state, + (state == CONNECTION_FAILED) ? net::ERR_FAILED : 0) { + error_message_ = error_message; } GoogleServiceAuthError::GoogleServiceAuthError( @@ -106,6 +97,14 @@ GoogleServiceAuthError } // static +GoogleServiceAuthError GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + InvalidGaiaCredentialsReason reason) { + GoogleServiceAuthError error(INVALID_GAIA_CREDENTIALS); + error.invalid_gaia_credentials_reason_ = reason; + return error; +} + +// static GoogleServiceAuthError GoogleServiceAuthError::FromClientLoginCaptchaChallenge( const std::string& captcha_token, const GURL& captcha_image_url, @@ -171,53 +170,10 @@ const std::string& GoogleServiceAuthError::error_message() const { return error_message_; } -base::DictionaryValue* GoogleServiceAuthError::ToValue() const { - base::DictionaryValue* value = new base::DictionaryValue(); - std::string state_str; - switch (state_) { -#define STATE_CASE(x) case x: state_str = #x; break - STATE_CASE(NONE); - STATE_CASE(INVALID_GAIA_CREDENTIALS); - STATE_CASE(USER_NOT_SIGNED_UP); - STATE_CASE(CONNECTION_FAILED); - STATE_CASE(CAPTCHA_REQUIRED); - STATE_CASE(ACCOUNT_DELETED); - STATE_CASE(ACCOUNT_DISABLED); - STATE_CASE(SERVICE_UNAVAILABLE); - STATE_CASE(TWO_FACTOR); - STATE_CASE(REQUEST_CANCELED); - STATE_CASE(UNEXPECTED_SERVICE_RESPONSE); - STATE_CASE(SERVICE_ERROR); - STATE_CASE(WEB_LOGIN_REQUIRED); -#undef STATE_CASE - default: - NOTREACHED(); - break; - } - value->SetString("state", state_str); - if (!error_message_.empty()) { - value->SetString("errorMessage", error_message_); - } - if (state_ == CAPTCHA_REQUIRED) { - auto captcha_value = std::make_unique<base::DictionaryValue>(); - captcha_value->SetString("token", captcha_.token); - captcha_value->SetString("audioUrl", captcha_.audio_url.spec()); - captcha_value->SetString("imageUrl", captcha_.image_url.spec()); - captcha_value->SetString("unlockUrl", captcha_.unlock_url.spec()); - captcha_value->SetInteger("imageWidth", captcha_.image_width); - captcha_value->SetInteger("imageHeight", captcha_.image_height); - value->Set("captcha", std::move(captcha_value)); - } else if (state_ == CONNECTION_FAILED) { - value->SetString("networkError", net::ErrorToString(network_error_)); - } else if (state_ == TWO_FACTOR) { - auto two_factor_value = std::make_unique<base::DictionaryValue>(); - two_factor_value->SetString("token", second_factor_.token); - two_factor_value->SetString("promptText", second_factor_.prompt_text); - two_factor_value->SetString("alternateText", second_factor_.alternate_text); - two_factor_value->SetInteger("fieldLength", second_factor_.field_length); - value->Set("two_factor", std::move(two_factor_value)); - } - return value; +GoogleServiceAuthError::InvalidGaiaCredentialsReason +GoogleServiceAuthError::GetInvalidGaiaCredentialsReason() const { + DCHECK_EQ(INVALID_GAIA_CREDENTIALS, state()); + return invalid_gaia_credentials_reason_; } std::string GoogleServiceAuthError::ToString() const { @@ -225,7 +181,9 @@ std::string GoogleServiceAuthError::ToString() const { case NONE: return std::string(); case INVALID_GAIA_CREDENTIALS: - return "Invalid credentials."; + return base::StringPrintf( + "Invalid credentials (%d).", + static_cast<int>(invalid_gaia_credentials_reason_)); case USER_NOT_SIGNED_UP: return "Not authorized."; case CONNECTION_FAILED: @@ -280,19 +238,22 @@ bool GoogleServiceAuthError::IsTransientError() const { GoogleServiceAuthError::GoogleServiceAuthError(State s, int error) : state_(s), - network_error_(error) { -} - -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) + 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_(0) { -} + 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 5e845991543..8ed19a90b82 100644 --- a/chromium/google_apis/gaia/google_service_auth_error.h +++ b/chromium/google_apis/gaia/google_service_auth_error.h @@ -8,17 +8,6 @@ // Accounts (e.g expired credentials). It may contain additional data such as // captcha or OTP challenges. -// A GoogleServiceAuthError without additional data is just a State, defined -// below. A case could be made to have this relation implicit, to allow raising -// error events concisely by doing OnAuthError(GoogleServiceAuthError::NONE), -// for example. But the truth is this class is ever so slightly more than a -// transparent wrapper around 'State' due to additional Captcha data -// (e.g consider operator=), and this would violate the style guide. Thus, -// you must explicitly use the constructor when all you have is a State. -// The good news is the implementation nests the enum inside a class, so you -// may forward declare and typedef GoogleServiceAuthError to something shorter -// in the comfort of your own translation unit. - #ifndef GOOGLE_APIS_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ #define GOOGLE_APIS_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ @@ -34,10 +23,6 @@ class GoogleServiceAuthErrorDataView; } } -namespace base { -class DictionaryValue; -} - class GoogleServiceAuthError { public: // @@ -101,6 +86,23 @@ class GoogleServiceAuthError { NUM_STATES = 14, }; + // 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 + // the end. + enum class InvalidGaiaCredentialsReason { + // The error was not specified. + UNKNOWN = 0, + // Credentials were rejectedby the Gaia server. + CREDENTIALS_REJECTED_BY_SERVER, + // Credentials were invalidated locally by Chrome. + CREDENTIALS_REJECTED_BY_CLIENT, + // Credentials are missing (e.g. could not be loaded from disk). + CREDENTIALS_MISSING, + + NUM_REASONS + }; + // Additional data for CAPTCHA_REQUIRED errors. struct Captcha { Captcha(); @@ -164,6 +166,9 @@ class GoogleServiceAuthError { // It will be created with CONNECTION_FAILED set. static GoogleServiceAuthError FromConnectionError(int error); + 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 @@ -198,9 +203,8 @@ class GoogleServiceAuthError { const std::string& token() const; const std::string& error_message() const; - // Returns info about this object in a dictionary. Caller takes - // ownership of returned dictionary. - base::DictionaryValue* ToValue() const; + // Should only be used when the error state is INVALID_GAIA_CREDENTIALS. + InvalidGaiaCredentialsReason GetInvalidGaiaCredentialsReason() const; // Returns a message describing the error. std::string ToString() const; @@ -234,6 +238,7 @@ class GoogleServiceAuthError { SecondFactor second_factor_; int network_error_; std::string error_message_; + InvalidGaiaCredentialsReason invalid_gaia_credentials_reason_; }; #endif // GOOGLE_APIS_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ 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 2fec3ead4d0..4035256cf54 100644 --- a/chromium/google_apis/gaia/google_service_auth_error_unittest.cc +++ b/chromium/google_apis/gaia/google_service_auth_error_unittest.cc @@ -7,49 +7,73 @@ #include <memory> #include <string> -#include "base/test/values_test_util.h" -#include "base/values.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -using base::ExpectDictStringValue; +TEST(GoogleServiceAuthErrorTest, State) { + for (GoogleServiceAuthError::State i = GoogleServiceAuthError::NONE; + i < GoogleServiceAuthError::NUM_STATES; + i = GoogleServiceAuthError::State(i + 1)) { + GoogleServiceAuthError error(i); + EXPECT_EQ(i, error.state()); + EXPECT_TRUE(error.error_message().empty()); -class GoogleServiceAuthErrorTest : public testing::Test {}; + if (i == GoogleServiceAuthError::CONNECTION_FAILED) + EXPECT_EQ(net::ERR_FAILED, error.network_error()); + else + EXPECT_EQ(net::OK, error.network_error()); -void TestSimpleState(GoogleServiceAuthError::State state) { - GoogleServiceAuthError error(state); - std::unique_ptr<base::DictionaryValue> value(error.ToValue()); - EXPECT_EQ(1u, value->size()); - std::string state_str; - EXPECT_TRUE(value->GetString("state", &state_str)); - EXPECT_FALSE(state_str.empty()); - EXPECT_NE("CONNECTION_FAILED", state_str); - EXPECT_NE("CAPTCHA_REQUIRED", state_str); -} + if (i == GoogleServiceAuthError::NONE) { + EXPECT_FALSE(error.IsTransientError()); + EXPECT_FALSE(error.IsPersistentError()); + } else if ((i == GoogleServiceAuthError::CONNECTION_FAILED) || + (i == GoogleServiceAuthError::SERVICE_UNAVAILABLE) || + (i == GoogleServiceAuthError::REQUEST_CANCELED)) { + EXPECT_TRUE(error.IsTransientError()); + EXPECT_FALSE(error.IsPersistentError()); + } else { + EXPECT_FALSE(error.IsTransientError()); + EXPECT_TRUE(error.IsPersistentError()); + } -TEST_F(GoogleServiceAuthErrorTest, SimpleToValue) { - for (int i = GoogleServiceAuthError::NONE; - i <= GoogleServiceAuthError::USER_NOT_SIGNED_UP; ++i) { - TestSimpleState(static_cast<GoogleServiceAuthError::State>(i)); + if (i == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) { + EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::UNKNOWN, + error.GetInvalidGaiaCredentialsReason()); + } } } -TEST_F(GoogleServiceAuthErrorTest, None) { - GoogleServiceAuthError error(GoogleServiceAuthError::AuthErrorNone()); - std::unique_ptr<base::DictionaryValue> value(error.ToValue()); - EXPECT_EQ(1u, value->size()); - ExpectDictStringValue("NONE", *value, "state"); +TEST(GoogleServiceAuthErrorTest, FromConnectionError) { + GoogleServiceAuthError error = + GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT); + EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error.state()); + EXPECT_EQ(net::ERR_TIMED_OUT, error.network_error()); +} + +TEST(GoogleServiceAuthErrorTest, FromServiceError) { + GoogleServiceAuthError error = + GoogleServiceAuthError::FromServiceError("Foo"); + EXPECT_EQ(GoogleServiceAuthError::SERVICE_ERROR, error.state()); + EXPECT_EQ("Foo", error.error_message()); +} + +TEST(GoogleServiceAuthErrorTest, FromInvalidGaiaCredentialsReason) { + GoogleServiceAuthError error = + GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER); + EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error.state()); + EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER, + error.GetInvalidGaiaCredentialsReason()); + EXPECT_EQ("Invalid credentials (1).", error.ToString()); } -TEST_F(GoogleServiceAuthErrorTest, ConnectionFailed) { - GoogleServiceAuthError error( - GoogleServiceAuthError::FromConnectionError(net::OK)); - std::unique_ptr<base::DictionaryValue> value(error.ToValue()); - EXPECT_EQ(2u, value->size()); - ExpectDictStringValue("CONNECTION_FAILED", *value, "state"); - ExpectDictStringValue("net::OK", *value, "networkError"); +TEST(GoogleServiceAuthErrorTest, AuthErrorNone) { + EXPECT_EQ(GoogleServiceAuthError(GoogleServiceAuthError::NONE), + GoogleServiceAuthError::AuthErrorNone()); } } // namespace diff --git a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc index ac1aabe0760..32d762aa61c 100644 --- a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc +++ b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc @@ -236,8 +236,9 @@ void OAuth2AccessTokenFetcherImpl::EndGetAccessToken( OnGetTokenFailure( access_error == OAUTH2_ACCESS_ERROR_INVALID_GRANT - ? GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) + ? GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER) : GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR)); return; } @@ -250,8 +251,10 @@ void OAuth2AccessTokenFetcherImpl::EndGetAccessToken( // The other errors are treated as permanent error. DLOG(ERROR) << "Unexpected persistent error: http_status=" << source->GetResponseCode(); - OnGetTokenFailure(GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + OnGetTokenFailure( + GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER)); } return; } 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 c95a14ae5f6..04666db9ca6 100644 --- a/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc +++ b/chromium/google_apis/gaia/oauth2_api_call_flow_unittest.cc @@ -8,7 +8,7 @@ #include <memory> #include <string> -#include <vector> +#include <utility> #include "base/message_loop/message_loop.h" #include "base/time/time.h" @@ -39,6 +39,7 @@ using net::URLFetcherFactory; using net::URLRequestContextGetter; using net::URLRequestStatus; using testing::_; +using testing::ByMove; using testing::Return; using testing::StrictMock; @@ -64,13 +65,13 @@ class MockUrlFetcherFactory : public ScopedURLFetcherFactory, } virtual ~MockUrlFetcherFactory() {} - MOCK_METHOD5( - CreateURLFetcherMock, - URLFetcher*(int id, - const GURL& url, - URLFetcher::RequestType request_type, - URLFetcherDelegate* d, - net::NetworkTrafficAnnotationTag traffic_annotation)); + MOCK_METHOD5(CreateURLFetcherMock, + std::unique_ptr<URLFetcher>( + int id, + const GURL& url, + URLFetcher::RequestType request_type, + URLFetcherDelegate* d, + net::NetworkTrafficAnnotationTag traffic_annotation)); std::unique_ptr<URLFetcher> CreateURLFetcher( int id, @@ -78,8 +79,7 @@ class MockUrlFetcherFactory : public ScopedURLFetcherFactory, URLFetcher::RequestType request_type, URLFetcherDelegate* d, net::NetworkTrafficAnnotationTag traffic_annotation) override { - return std::unique_ptr<URLFetcher>( - CreateURLFetcherMock(id, url, request_type, d, traffic_annotation)); + return CreateURLFetcherMock(id, url, request_type, d, traffic_annotation); } }; @@ -88,16 +88,13 @@ class MockApiCallFlow : public OAuth2ApiCallFlow { MockApiCallFlow() {} ~MockApiCallFlow() {} - MOCK_METHOD0(CreateApiCallUrl, GURL ()); - MOCK_METHOD0(CreateApiCallBody, std::string ()); - MOCK_METHOD1(ProcessApiCallSuccess, - void (const URLFetcher* source)); - MOCK_METHOD1(ProcessApiCallFailure, - void (const URLFetcher* source)); - MOCK_METHOD1(ProcessNewAccessToken, - void (const std::string& access_token)); + MOCK_METHOD0(CreateApiCallUrl, GURL()); + MOCK_METHOD0(CreateApiCallBody, std::string()); + MOCK_METHOD1(ProcessApiCallSuccess, void(const URLFetcher* source)); + MOCK_METHOD1(ProcessApiCallFailure, void(const URLFetcher* source)); + MOCK_METHOD1(ProcessNewAccessToken, void(const std::string& access_token)); MOCK_METHOD1(ProcessMintAccessTokenFailure, - void (const GoogleServiceAuthError& error)); + void(const GoogleServiceAuthError& error)); net::PartialNetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag() { return PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS; @@ -109,13 +106,15 @@ class MockApiCallFlow : public OAuth2ApiCallFlow { class OAuth2ApiCallFlowTest : public testing::Test { protected: OAuth2ApiCallFlowTest() - : request_context_getter_(new net::TestURLRequestContextGetter( - message_loop_.task_runner())) {} - - TestURLFetcher* CreateURLFetcher( - const GURL& url, bool fetch_succeeds, - int response_code, const std::string& body) { - TestURLFetcher* url_fetcher = new TestURLFetcher(0, url, &flow_); + : request_context_getter_( + base::MakeRefCounted<net::TestURLRequestContextGetter>( + message_loop_.task_runner())) {} + + std::unique_ptr<TestURLFetcher> CreateURLFetcher(const GURL& url, + bool fetch_succeeds, + int response_code, + const std::string& body) { + auto url_fetcher = std::make_unique<TestURLFetcher>(0, url, &flow_); net::Error error = fetch_succeeds ? net::OK : net::ERR_FAILED; url_fetcher->set_status(URLRequestStatus::FromError(error)); @@ -133,11 +132,12 @@ class OAuth2ApiCallFlowTest : public testing::Test { GURL url(CreateApiUrl()); EXPECT_CALL(flow_, CreateApiCallBody()).WillOnce(Return(body)); EXPECT_CALL(flow_, CreateApiCallUrl()).WillOnce(Return(url)); - TestURLFetcher* url_fetcher = + std::unique_ptr<TestURLFetcher> url_fetcher = CreateURLFetcher(url, succeeds, status, std::string()); + TestURLFetcher* url_fetcher_ptr = url_fetcher.get(); EXPECT_CALL(factory_, CreateURLFetcherMock(_, url, _, _, _)) - .WillOnce(Return(url_fetcher)); - return url_fetcher; + .WillOnce(Return(ByMove(std::move(url_fetcher)))); + return url_fetcher_ptr; } base::MessageLoop message_loop_; diff --git a/chromium/google_apis/gaia/oauth2_token_service.cc b/chromium/google_apis/gaia/oauth2_token_service.cc index c75a1407dd4..542435cbb90 100644 --- a/chromium/google_apis/gaia/oauth2_token_service.cc +++ b/chromium/google_apis/gaia/oauth2_token_service.cc @@ -574,7 +574,14 @@ bool OAuth2TokenService::RefreshTokenIsAvailable( bool OAuth2TokenService::RefreshTokenHasError( const std::string& account_id) const { - return delegate_->RefreshTokenHasError(account_id); + 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::RevokeAllCredentials() { diff --git a/chromium/google_apis/gaia/oauth2_token_service.h b/chromium/google_apis/gaia/oauth2_token_service.h index f1e0f88107c..9f279c52502 100644 --- a/chromium/google_apis/gaia/oauth2_token_service.h +++ b/chromium/google_apis/gaia/oauth2_token_service.h @@ -110,6 +110,11 @@ class OAuth2TokenService { virtual void OnStartBatchChanges() {} // 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) {} protected: virtual ~Observer() {} @@ -186,10 +191,14 @@ class OAuth2TokenService { // |StartRequest| will result in a Consumer::OnGetTokenFailure callback. bool RefreshTokenIsAvailable(const std::string& account_id) const; - // Returns true if a refresh token exists for |account_id| and it is in an - // error state. + // 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; + // This method cancels all token requests, revoke all refresh tokens and // cached access tokens. void RevokeAllCredentials(); diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc b/chromium/google_apis/gaia/oauth2_token_service_delegate.cc index ce2f37ef6f9..aa143e02e6a 100644 --- a/chromium/google_apis/gaia/oauth2_token_service_delegate.cc +++ b/chromium/google_apis/gaia/oauth2_token_service_delegate.cc @@ -51,11 +51,6 @@ void OAuth2TokenServiceDelegate::RemoveObserver( observer_list_.RemoveObserver(observer); } -// static -bool OAuth2TokenServiceDelegate::IsError(const GoogleServiceAuthError& error) { - return error.IsPersistentError(); -} - void OAuth2TokenServiceDelegate::StartBatchChanges() { ++batch_change_depth_; if (batch_change_depth_ == 1) { @@ -90,14 +85,21 @@ void OAuth2TokenServiceDelegate::FireRefreshTokensLoaded() { observer.OnRefreshTokensLoaded(); } +void OAuth2TokenServiceDelegate::FireAuthErrorChanged( + const std::string& account_id, + const GoogleServiceAuthError& error) { + for (auto& observer : observer_list_) + observer.OnAuthErrorChanged(account_id, error); +} + net::URLRequestContextGetter* OAuth2TokenServiceDelegate::GetRequestContext() const { return nullptr; } -bool OAuth2TokenServiceDelegate::RefreshTokenHasError( +GoogleServiceAuthError OAuth2TokenServiceDelegate::GetAuthError( const std::string& account_id) const { - return false; + return GoogleServiceAuthError::AuthErrorNone(); } std::vector<std::string> OAuth2TokenServiceDelegate::GetAccounts() { diff --git a/chromium/google_apis/gaia/oauth2_token_service_delegate.h b/chromium/google_apis/gaia/oauth2_token_service_delegate.h index 283d4f25f0f..101fb8e2c98 100644 --- a/chromium/google_apis/gaia/oauth2_token_service_delegate.h +++ b/chromium/google_apis/gaia/oauth2_token_service_delegate.h @@ -40,7 +40,8 @@ class OAuth2TokenServiceDelegate { OAuth2AccessTokenConsumer* consumer) = 0; virtual bool RefreshTokenIsAvailable(const std::string& account_id) const = 0; - virtual bool RefreshTokenHasError(const std::string& account_id) const; + virtual GoogleServiceAuthError GetAuthError( + const std::string& account_id) const; virtual void UpdateAuthError(const std::string& account_id, const GoogleServiceAuthError& error) {} @@ -75,10 +76,13 @@ class OAuth2TokenServiceDelegate { virtual LoadCredentialsState GetLoadCredentialsState() const; protected: - // Called by subclasses to notify observers. + // 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 { @@ -91,12 +95,6 @@ class OAuth2TokenServiceDelegate { DISALLOW_COPY_AND_ASSIGN(ScopedBatchChange); }; - // This function is called by derived classes to help implement - // RefreshTokenHasError(). It centralizes the code for determining if - // |error| is worthy of being reported as an error for purposes of - // RefreshTokenHasError(). - static bool IsError(const GoogleServiceAuthError& error); - private: // List of observers to notify when refresh token availability changes. // Makes sure list is empty on destruction. diff --git a/chromium/google_apis/gcm/BUILD.gn b/chromium/google_apis/gcm/BUILD.gn index 298b5de84a2..0a6ccbb80d5 100644 --- a/chromium/google_apis/gcm/BUILD.gn +++ b/chromium/google_apis/gcm/BUILD.gn @@ -67,6 +67,7 @@ component("gcm") { "//base", "//base/third_party/dynamic_annotations", "//net", + "//services/network:network_service", "//third_party/leveldatabase", "//url", ] diff --git a/chromium/google_apis/gcm/DEPS b/chromium/google_apis/gcm/DEPS index 047dc1564b5..a044cbe8349 100644 --- a/chromium/google_apis/gcm/DEPS +++ b/chromium/google_apis/gcm/DEPS @@ -10,4 +10,5 @@ include_rules = [ "+google", # For third_party/protobuf/src. "+net", "+third_party/leveldatabase", + "+services/network", ] diff --git a/chromium/google_apis/gcm/engine/connection_factory_impl.cc b/chromium/google_apis/gcm/engine/connection_factory_impl.cc index cfffcb20ba7..31942daa297 100644 --- a/chromium/google_apis/gcm/engine/connection_factory_impl.cc +++ b/chromium/google_apis/gcm/engine/connection_factory_impl.cc @@ -18,11 +18,13 @@ #include "net/base/net_errors.h" #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" +#include "net/http/proxy_fallback.h" #include "net/log/net_log_source_type.h" #include "net/proxy_resolution/proxy_info.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_manager.h" #include "net/ssl/ssl_config_service.h" +#include "services/network/proxy_resolving_client_socket.h" namespace gcm { @@ -60,9 +62,6 @@ ConnectionFactoryImpl::ConnectionFactoryImpl( backoff_policy_(backoff_policy), gcm_network_session_(gcm_network_session), http_network_session_(http_network_session), - net_log_( - net::NetLogWithSource::Make(net_log, net::NetLogSourceType::SOCKET)), - proxy_resolve_request_(NULL), connecting_(false), waiting_for_backoff_(false), waiting_for_network_online_(false), @@ -78,11 +77,6 @@ ConnectionFactoryImpl::ConnectionFactoryImpl( ConnectionFactoryImpl::~ConnectionFactoryImpl() { CloseSocket(); net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); - if (proxy_resolve_request_) { - gcm_network_session_->proxy_resolution_service()->CancelRequest( - proxy_resolve_request_); - proxy_resolve_request_ = NULL; - } } void ConnectionFactoryImpl::Initialize( @@ -298,11 +292,11 @@ GURL ConnectionFactoryImpl::GetCurrentEndpoint() const { } net::IPEndPoint ConnectionFactoryImpl::GetPeerIP() { - if (!socket_handle_.socket()) + if (!socket_) return net::IPEndPoint(); net::IPEndPoint ip_endpoint; - int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); + int result = socket_->GetPeerAddress(&ip_endpoint); if (result != net::OK) return net::IPEndPoint(); @@ -317,7 +311,7 @@ void ConnectionFactoryImpl::ConnectImpl() { void ConnectionFactoryImpl::StartConnection() { DCHECK(!IsEndpointReachable()); // TODO(zea): Make this a dcheck again. crbug.com/462319 - CHECK(!socket_handle_.socket()); + CHECK(!socket_); // TODO(zea): if the network is offline, don't attempt to connect. // See crbug.com/396687 @@ -326,13 +320,14 @@ void ConnectionFactoryImpl::StartConnection() { GURL current_endpoint = GetCurrentEndpoint(); recorder_->RecordConnectionInitiated(current_endpoint.host()); UpdateFromHttpNetworkSession(); - int status = gcm_network_session_->proxy_resolution_service()->ResolveProxy( - current_endpoint, std::string(), &proxy_info_, - base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, - weak_ptr_factory_.GetWeakPtr()), - &proxy_resolve_request_, NULL, net_log_); + net::SSLConfig ssl_config; + gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); + socket_ = std::make_unique<network::ProxyResolvingClientSocket>( + gcm_network_session_, ssl_config, current_endpoint, true /*use_tls*/); + int status = socket_->Connect(base::BindRepeating( + &ConnectionFactoryImpl::OnConnectDone, weak_ptr_factory_.GetWeakPtr())); if (status != net::ERR_IO_PENDING) - OnProxyResolveDone(status); + OnConnectDone(status); } void ConnectionFactoryImpl::InitHandler() { @@ -380,8 +375,7 @@ void ConnectionFactoryImpl::InitHandler() { "but does not have any effect on other Google Cloud messages." )"); - connection_handler_->Init(login_request, traffic_annotation, - socket_handle_.socket()); + connection_handler_->Init(login_request, traffic_annotation, socket_.get()); } std::unique_ptr<net::BackoffEntry> ConnectionFactoryImpl::CreateBackoffEntry( @@ -404,15 +398,8 @@ base::TimeTicks ConnectionFactoryImpl::NowTicks() { } void ConnectionFactoryImpl::OnConnectDone(int result) { + DCHECK_NE(net::ERR_IO_PENDING, result); if (result != net::OK) { - // If the connection fails, try another proxy. - result = ReconsiderProxyAfterError(result); - // ReconsiderProxyAfterError either returns an error (in which case it is - // not reconsidering a proxy) or returns ERR_IO_PENDING if it is considering - // another proxy. - DCHECK_NE(result, net::OK); - if (result == net::ERR_IO_PENDING) - return; // Proxy reconsideration pending. Return. LOG(ERROR) << "Failed to connect to MCS endpoint with error " << result; UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", false); recorder_->RecordConnectionFailure(result); @@ -435,9 +422,6 @@ void ConnectionFactoryImpl::OnConnectDone(int result) { UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true); UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_); - UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy", - !(proxy_info_.is_empty() || proxy_info_.is_direct())); - ReportSuccessfulProxyConnection(); recorder_->RecordConnectionSuccess(); // Reset the endpoint back to the default. @@ -477,143 +461,15 @@ void ConnectionFactoryImpl::ConnectionHandlerCallback(int result) { listener_->OnConnected(GetCurrentEndpoint(), GetPeerIP()); } -// This has largely been copied from -// HttpStreamFactoryImpl::Job::DoResolveProxyComplete. This should be -// refactored into some common place. -void ConnectionFactoryImpl::OnProxyResolveDone(int status) { - proxy_resolve_request_ = NULL; - DVLOG(1) << "Proxy resolution status: " << status; - - DCHECK_NE(status, net::ERR_IO_PENDING); - if (status == net::OK) { - // Remove unsupported proxies from the list. - proxy_info_.RemoveProxiesWithoutScheme( - net::ProxyServer::SCHEME_DIRECT | - net::ProxyServer::SCHEME_HTTP | net::ProxyServer::SCHEME_HTTPS | - net::ProxyServer::SCHEME_SOCKS4 | net::ProxyServer::SCHEME_SOCKS5); - - if (proxy_info_.is_empty()) { - // No proxies/direct to choose from. This happens when we don't support - // any of the proxies in the returned list. - status = net::ERR_NO_SUPPORTED_PROXIES; - } - } - - if (status != net::OK) { - // Failed to resolve proxy. Retry later. - OnConnectDone(status); - return; - } - - DVLOG(1) << "Resolved proxy with PAC:" << proxy_info_.ToPacString(); - - net::SSLConfig ssl_config; - gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); - status = net::InitSocketHandleForTlsConnect( - net::HostPortPair::FromURL(GetCurrentEndpoint()), - gcm_network_session_, - proxy_info_, - ssl_config, - ssl_config, - net::PRIVACY_MODE_DISABLED, - net_log_, - &socket_handle_, - base::Bind(&ConnectionFactoryImpl::OnConnectDone, - weak_ptr_factory_.GetWeakPtr())); - if (status != net::ERR_IO_PENDING) - OnConnectDone(status); -} - -// This has largely been copied from -// HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError. This should be -// refactored into some common place. -// This method reconsiders the proxy on certain errors. If it does reconsider -// a proxy it always returns ERR_IO_PENDING and posts a call to -// OnProxyResolveDone with the result of the reconsideration. -int ConnectionFactoryImpl::ReconsiderProxyAfterError(int error) { - DCHECK(!proxy_resolve_request_); - DCHECK_NE(error, net::OK); - DCHECK_NE(error, net::ERR_IO_PENDING); - // A failure to resolve the hostname or any error related to establishing a - // TCP connection could be grounds for trying a new proxy configuration. - // - // Why do this when a hostname cannot be resolved? Some URLs only make sense - // to proxy servers. The hostname in those URLs might fail to resolve if we - // are still using a non-proxy config. We need to check if a proxy config - // now exists that corresponds to a proxy server that could load the URL. - // - switch (error) { - case net::ERR_PROXY_CONNECTION_FAILED: - case net::ERR_NAME_NOT_RESOLVED: - case net::ERR_INTERNET_DISCONNECTED: - case net::ERR_ADDRESS_UNREACHABLE: - case net::ERR_CONNECTION_CLOSED: - case net::ERR_CONNECTION_TIMED_OUT: - case net::ERR_CONNECTION_RESET: - case net::ERR_CONNECTION_REFUSED: - case net::ERR_CONNECTION_ABORTED: - case net::ERR_TIMED_OUT: - case net::ERR_TUNNEL_CONNECTION_FAILED: - case net::ERR_SOCKS_CONNECTION_FAILED: - // This can happen in the case of trying to talk to a proxy using SSL, and - // ending up talking to a captive portal that supports SSL instead. - case net::ERR_PROXY_CERTIFICATE_INVALID: - // This can happen when trying to talk SSL to a non-SSL server (Like a - // captive portal). - case net::ERR_SSL_PROTOCOL_ERROR: - break; - case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: - // Remap the SOCKS-specific "host unreachable" error to a more - // generic error code (this way consumers like the link doctor - // know to substitute their error page). - // - // Note that if the host resolving was done by the SOCKS5 proxy, we can't - // differentiate between a proxy-side "host not found" versus a proxy-side - // "address unreachable" error, and will report both of these failures as - // ERR_ADDRESS_UNREACHABLE. - return net::ERR_ADDRESS_UNREACHABLE; - default: - return error; - } - - net::SSLConfig ssl_config; - gcm_network_session_->ssl_config_service()->GetSSLConfig(&ssl_config); - if (proxy_info_.is_https() && ssl_config.send_client_cert) { - gcm_network_session_->ssl_client_auth_cache()->Remove( - proxy_info_.proxy_server().host_port_pair()); - } - - if (!proxy_info_.Fallback(error, net_log_)) { - // There was nothing left to fall-back to, so fail the transaction - // with the last connection error we got. - return error; - } - - CloseSocket(); - - // If there is new proxy info, post OnProxyResolveDone to retry it. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone, - weak_ptr_factory_.GetWeakPtr(), net::OK)); - - return net::ERR_IO_PENDING; -} - -void ConnectionFactoryImpl::ReportSuccessfulProxyConnection() { - if (gcm_network_session_ && gcm_network_session_->proxy_resolution_service()) - gcm_network_session_->proxy_resolution_service()->ReportSuccess(proxy_info_, - NULL); -} - void ConnectionFactoryImpl::CloseSocket() { // The connection handler needs to be reset, else it'll attempt to keep using // the destroyed socket. if (connection_handler_) connection_handler_->Reset(); - if (socket_handle_.socket() && socket_handle_.socket()->IsConnected()) - socket_handle_.socket()->Disconnect(); - socket_handle_.Reset(); + if (socket_) + socket_->Disconnect(); + socket_ = nullptr; } void ConnectionFactoryImpl::UpdateFromHttpNetworkSession() { diff --git a/chromium/google_apis/gcm/engine/connection_factory_impl.h b/chromium/google_apis/gcm/engine/connection_factory_impl.h index 4fa1456a4d7..2b718aa9eaa 100644 --- a/chromium/google_apis/gcm/engine/connection_factory_impl.h +++ b/chromium/google_apis/gcm/engine/connection_factory_impl.h @@ -18,11 +18,12 @@ #include "net/base/backoff_entry.h" #include "net/base/network_change_notifier.h" #include "net/log/net_log_with_source.h" -#include "net/proxy_resolution/proxy_info.h" -#include "net/proxy_resolution/proxy_service.h" -#include "net/socket/client_socket_handle.h" #include "url/gurl.h" +namespace network { +class ProxyResolvingClientSocket; +} + namespace net { class HttpNetworkSession; class NetLog; @@ -123,12 +124,6 @@ class GCM_EXPORT ConnectionFactoryImpl : // handshake. On connection/handshake failure, goes into backoff. void ConnectImpl(); - // Proxy resolution and connection functions. - void OnProxyResolveDone(int status); - void OnProxyConnectDone(int status); - int ReconsiderProxyAfterError(int error); - void ReportSuccessfulProxyConnection(); - // Closes the local socket if one is present, and resets connection handler. void CloseSocket(); @@ -157,15 +152,8 @@ class GCM_EXPORT ConnectionFactoryImpl : // HTTP Network session. If set, is used for extracting proxy auth // credentials. If nullptr, is ignored. net::HttpNetworkSession* http_network_session_; - // Net log to use in connection attempts. - net::NetLogWithSource net_log_; - // The current proxy resolution request, if one exists. Owned by the proxy - // service. - net::ProxyResolutionService::Request* proxy_resolve_request_; - // The current proxy info. - net::ProxyInfo proxy_info_; // The handle to the socket for the current connection, if one exists. - net::ClientSocketHandle socket_handle_; + std::unique_ptr<network::ProxyResolvingClientSocket> socket_; // Current backoff entry. std::unique_ptr<net::BackoffEntry> backoff_entry_; // Backoff entry from previous connection attempt. Updated on each login |