diff options
-rw-r--r-- | chrome/browser/sync/profile_sync_service.cc | 4 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service.h | 3 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service_harness.cc | 6 | ||||
-rw-r--r-- | chrome/browser/sync/test/integration/sync_auth_test.cc | 54 | ||||
-rw-r--r-- | chrome/browser/sync/test/integration/sync_errors_test.cc | 36 | ||||
-rw-r--r-- | chrome/browser/sync/test/integration/sync_test.cc | 33 | ||||
-rw-r--r-- | chrome/browser/sync/test/integration/sync_test.h | 26 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
8 files changed, 109 insertions, 54 deletions
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index f2e0c4e..bc576b9 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -2144,6 +2144,10 @@ void ProfileSyncService::OnInternalUnrecoverableError( OnUnrecoverableErrorImpl(from_here, message, delete_sync_database); } +bool ProfileSyncService::IsRetryingAccessTokenFetchForTest() const { + return request_access_token_retry_timer_.IsRunning(); +} + std::string ProfileSyncService::GetEffectiveUsername() { if (profile_->IsManaged()) { #if defined(ENABLE_MANAGED_USERS) diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 4dd851a..f64f8ea 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -495,6 +495,9 @@ class ProfileSyncService : public ProfileSyncServiceBase, // Used by ProfileSyncServiceHarness. May return NULL. browser_sync::BackendMigrator* GetBackendMigratorForTest(); + // Used by tests to inspect interaction with OAuth2TokenService. + bool IsRetryingAccessTokenFetchForTest() const; + // TODO(sync): This is only used in tests. Can we remove it? void GetModelSafeRoutingInfo(syncer::ModelSafeRoutingInfo* out) const; diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc index 800d1bb..f90f791 100644 --- a/chrome/browser/sync/profile_sync_service_harness.cc +++ b/chrome/browser/sync/profile_sync_service_harness.cc @@ -349,6 +349,12 @@ bool ProfileSyncServiceHarness::RunStateChangeMachine() { } case WAITING_FOR_FULL_SYNC: { DVLOG(1) << GetClientInfoString("WAITING_FOR_FULL_SYNC"); + if (service()->GetAuthError().state() == + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS) { + // Our credentials were rejected. Do not wait any more. + SignalStateCompleteWithNextState(CREDENTIALS_REJECTED); + break; + } if (IsFullySynced()) { // The sync cycle we were waiting for is complete. SignalStateCompleteWithNextState(FULLY_SYNCED); diff --git a/chrome/browser/sync/test/integration/sync_auth_test.cc b/chrome/browser/sync/test/integration/sync_auth_test.cc new file mode 100644 index 0000000..7393cfb --- /dev/null +++ b/chrome/browser/sync/test/integration/sync_auth_test.cc @@ -0,0 +1,54 @@ +// 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 "base/threading/platform_thread.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/profile_sync_service_harness.h" +#include "chrome/browser/sync/test/integration/bookmarks_helper.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_request_status.h" + +using bookmarks_helper::AddURL; + +const char kValidOAuth2Token[] = "{" + " \"refresh_token\": \"rt1\"," + " \"access_token\": \"at1\"," + " \"expires_in\": 3600," // 1 hour. + " \"token_type\": \"Bearer\"" + "}"; + +const char kInvalidOAuth2Token[] = "{" + " \"error\": \"invalid_grant\"" + "}"; + +class SyncAuthTest : public SyncTest { + public: + SyncAuthTest() : SyncTest(SINGLE_CLIENT) {} + virtual ~SyncAuthTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(SyncAuthTest); +}; + +IN_PROC_BROWSER_TEST_F(SyncAuthTest, Sanity) { + ASSERT_TRUE(SetupSync()); + + TriggerAuthState(AUTHENTICATED_TRUE); + SetOAuth2TokenResponse(kValidOAuth2Token, net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + ASSERT_TRUE(AddURL(0, L"Bookmark 1", GURL("http://www.foo1.com")) != NULL); + ASSERT_TRUE(GetClient(0)->AwaitFullSyncCompletion("Added a bookmark.")); + + TriggerAuthState(AUTHENTICATED_FALSE); + SetOAuth2TokenResponse(kInvalidOAuth2Token, net::HTTP_BAD_REQUEST, + net::URLRequestStatus::SUCCESS); + + ASSERT_TRUE(AddURL(0, L"Bookmark 2", GURL("http://www.foo2.com")) != NULL); + ASSERT_FALSE(GetClient(0)->AwaitFullSyncCompletion("Added second bookmark.")); + ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, + GetClient(0)->service()->GetAuthError().state()); +} diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc index 698f18d..d093d54 100644 --- a/chrome/browser/sync/test/integration/sync_errors_test.cc +++ b/chrome/browser/sync/test/integration/sync_errors_test.cc @@ -140,42 +140,6 @@ IN_PROC_BROWSER_TEST_F(SyncErrorTest, protocol_error.error_description); } -// TODO(pavely): Fix this test. Test needs to successfully setup sync. Then -// setup server to trigger auth error and setup FakeURLFetcher to return -// INVALID_CREDENTIALS failure for access token request. Then it should -// trigger sync and verify that error surfaced through -// ProfileSyncService::GetAuthError() -// -// Trigger an auth error and make sure the sync client displays a warning in the -// UI. -IN_PROC_BROWSER_TEST_F(SyncErrorTest, DISABLED_AuthErrorTest) { - ASSERT_TRUE(SetupClients()); - TriggerAuthError(); - - ASSERT_FALSE(GetClient(0)->SetupSync()); - ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, - GetClient(0)->service()->GetAuthError().state()); -} - -// TODO(pavely): Fix this test. Test needs to successfully setup sync. Then -// setup server to trigger xmpp auth error and setup FakeURLFetcher to return -// INVALID_CREDENTIALS failure for access token request. Then it should -// trigger sync and verify that error surfaced through -// ProfileSyncService::GetAuthError() -// -// Trigger an XMPP auth error, and make sure sync treats it like any -// other auth error. -IN_PROC_BROWSER_TEST_F(SyncErrorTest, DISABLED_XmppAuthErrorTest) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - - TriggerXmppAuthError(); - - ASSERT_FALSE(GetClient(0)->SetupSync()); - - ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, - GetClient(0)->service()->GetAuthError().state()); -} - // TODO(lipalani): Fix the typed_url dtc so this test case can pass. IN_PROC_BROWSER_TEST_F(SyncErrorTest, DISABLED_DisableDatatypeWhileRunning) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index be97945..4ca0158 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc @@ -48,7 +48,6 @@ #include "net/base/escape.h" #include "net/base/load_flags.h" #include "net/base/network_change_notifier.h" -#include "net/http/http_status_code.h" #include "net/proxy/proxy_config.h" #include "net/proxy/proxy_config_service_fixed.h" #include "net/proxy/proxy_service.h" @@ -58,7 +57,6 @@ #include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" -#include "net/url_request/url_request_status.h" #include "sync/engine/sync_scheduler_impl.h" #include "sync/notifier/p2p_invalidator.h" #include "sync/protocol/sync.pb.h" @@ -141,7 +139,8 @@ void SyncTest::SetUp() { username_ = cl->GetSwitchValueASCII(switches::kSyncUserForTest); password_ = cl->GetSwitchValueASCII(switches::kSyncPasswordForTest); } else { - SetupMockGaiaResponses(); + username_ = "user@gmail.com"; + password_ = "password"; } if (!cl->HasSwitch(switches::kSyncServiceURL) && @@ -178,6 +177,11 @@ void SyncTest::SetUp() { Encryptor::UseMockKeychain(true); #endif + // Start up a sync test server if one is needed and setup mock gaia responses. + // Note: This must be done prior to the call to SetupClients() because we want + // the mock gaia responses to be available before GaiaUrls is initialized. + SetUpTestServerIfRequired(); + // Yield control back to the InProcessBrowserTest framework. InProcessBrowserTest::SetUp(); } @@ -274,9 +278,6 @@ bool SyncTest::SetupClients() { if (!profiles_.empty() || !browsers_.empty() || !clients_.empty()) LOG(FATAL) << "SetupClients() has already been called."; - // Start up a sync test server if one is needed. - SetUpTestServerIfRequired(); - // Create the required number of sync profiles, browsers and clients. profiles_.resize(num_clients_); browsers_.resize(num_clients_); @@ -423,16 +424,9 @@ void SyncTest::ReadPasswordFile() { } void SyncTest::SetupMockGaiaResponses() { - username_ = "user@gmail.com"; - password_ = "password"; factory_.reset(new net::URLFetcherImplFactory()); fake_factory_.reset(new net::FakeURLFetcherFactory(factory_.get())); fake_factory_->SetFakeResponse( - GaiaUrls::GetInstance()->client_login_url(), - "SID=sid\nLSID=lsid", - net::HTTP_OK, - net::URLRequestStatus::SUCCESS); - fake_factory_->SetFakeResponse( GaiaUrls::GetInstance()->get_user_info_url(), "email=user@gmail.com\ndisplayEmail=user@gmail.com", net::HTTP_OK, @@ -469,6 +463,14 @@ void SyncTest::SetupMockGaiaResponses() { net::URLRequestStatus::SUCCESS); } +void SyncTest::SetOAuth2TokenResponse(const std::string& response_data, + net::HttpStatusCode response_code, + net::URLRequestStatus::Status status) { + ASSERT_TRUE(NULL != fake_factory_.get()); + fake_factory_->SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), + response_data, response_code, status); +} + void SyncTest::ClearMockGaiaResponses() { // Clear any mock gaia responses that might have been set. if (fake_factory_) { @@ -488,6 +490,7 @@ void SyncTest::SetUpTestServerIfRequired() { if (server_type_ == LOCAL_PYTHON_SERVER) { if (!SetUpLocalPythonTestServer()) LOG(FATAL) << "Failed to set up local python sync and XMPP servers"; + SetupMockGaiaResponses(); } else if (server_type_ == LOCAL_LIVE_SERVER) { // Using mock gaia credentials requires the use of a mock XMPP server. if (username_ == "user@gmail.com" && !SetUpLocalPythonTestServer()) @@ -738,9 +741,11 @@ void SyncTest::TriggerTransientError() { GetTitle())); } -void SyncTest::TriggerAuthError() { +void SyncTest::TriggerAuthState(PythonServerAuthState auth_state) { ASSERT_TRUE(ServerSupportsErrorTriggering()); std::string path = "chromiumsync/cred"; + path.append(auth_state == AUTHENTICATED_TRUE ? "?valid=True" : + "?valid=False"); ui_test_utils::NavigateToURL(browser(), sync_server_.GetURL(path)); } diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index 0aae307..7a80b28 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h @@ -14,6 +14,8 @@ #include "base/memory/scoped_vector.h" #include "chrome/test/base/in_process_browser_test.h" #include "net/dns/mock_host_resolver.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_request_status.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync_protocol_error.h" #include "sync/test/local_sync_test_server.h" @@ -80,6 +82,15 @@ class SyncTest : public InProcessBrowserTest { ERROR_FREQUENCY_TWO_THIRDS }; + // Authentication state used by the python sync server. + enum PythonServerAuthState { + // Python server processes sync requests normally. + AUTHENTICATED_TRUE, + + // Python server responds to sync requests with an authentication error. + AUTHENTICATED_FALSE + }; + // A SyncTest must be associated with a particular test type. explicit SyncTest(TestType test_type); @@ -162,6 +173,12 @@ class SyncTest : public InProcessBrowserTest { // only if ServerSupportsNotificationControl() returned true. void EnableNotifications(); + // Sets the mock gaia response for when an OAuth2 token is requested. + // Each call to this method will overwrite responses that were previously set. + void SetOAuth2TokenResponse(const std::string& response_data, + net::HttpStatusCode response_code, + net::URLRequestStatus::Status status); + // Trigger a notification to be sent to all clients. This operation // is available only if ServerSupportsNotificationControl() returned // true. @@ -183,10 +200,11 @@ class SyncTest : public InProcessBrowserTest { // this state until shut down. void TriggerTransientError(); - // Triggers an auth error on the server, simulating the case when the gaia - // password is changed at another location. Note the server will stay in - // this state until shut down. - void TriggerAuthError(); + // Sets / unsets an auth error on the server. Can be used to simulate the case + // when the user's gaia password is changed at another location, or their + // OAuth2 tokens have expired. The server will stay in this state until + // this method is called with a different value. + void TriggerAuthState(PythonServerAuthState auth_state); // Triggers an XMPP auth error on the server. Note the server will // stay in this state until shut down. diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 0df22e2..6d764f7 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2386,6 +2386,7 @@ 'browser/sync/test/integration/single_client_typed_urls_sync_test.cc', 'browser/sync/test/integration/sync_app_helper.cc', 'browser/sync/test/integration/sync_app_helper.h', + 'browser/sync/test/integration/sync_auth_test.cc', 'browser/sync/test/integration/sync_datatype_helper.cc', 'browser/sync/test/integration/sync_datatype_helper.h', 'browser/sync/test/integration/sync_errors_test.cc', |