summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc4
-rw-r--r--chrome/browser/cocoa/preferences_window_controller.mm2
-rw-r--r--chrome/browser/dom_ui/new_tab_page_sync_handler.cc2
-rw-r--r--chrome/browser/gtk/options/content_page_gtk.cc2
-rw-r--r--chrome/browser/net/gaia/token_service.cc30
-rw-r--r--chrome/browser/net/gaia/token_service.h19
-rw-r--r--chrome/browser/net/gaia/token_service_unittest.cc126
-rw-r--r--chrome/browser/net/gaia/token_service_unittest.h130
-rw-r--r--chrome/browser/prefs/browser_prefs.cc2
-rw-r--r--chrome/browser/profile.cc5
-rw-r--r--chrome/browser/profile.h5
-rw-r--r--chrome/browser/profile_impl.cc13
-rw-r--r--chrome/browser/profile_impl.h4
-rw-r--r--chrome/browser/sync/abstract_profile_sync_service_test.h4
-rw-r--r--chrome/browser/sync/engine/all_status.cc47
-rw-r--r--chrome/browser/sync/engine/all_status.h3
-rw-r--r--chrome/browser/sync/engine/auth_watcher.cc352
-rw-r--r--chrome/browser/sync/engine/auth_watcher.h222
-rw-r--r--chrome/browser/sync/engine/auth_watcher_unittest.cc235
-rw-r--r--chrome/browser/sync/engine/authenticator.cc110
-rw-r--r--chrome/browser/sync/engine/authenticator.h105
-rw-r--r--chrome/browser/sync/engine/net/server_connection_manager.cc13
-rw-r--r--chrome/browser/sync/engine/net/server_connection_manager.h18
-rw-r--r--chrome/browser/sync/engine/net/syncapi_server_connection_manager.h4
-rw-r--r--chrome/browser/sync/engine/syncapi.cc450
-rw-r--r--chrome/browser/sync/engine/syncapi.h63
-rw-r--r--chrome/browser/sync/engine/syncapi_unittest.cc2
-rw-r--r--chrome/browser/sync/engine/syncer_proto_util.cc15
-rw-r--r--chrome/browser/sync/engine/syncer_proto_util.h2
-rw-r--r--chrome/browser/sync/engine/syncer_proto_util_unittest.cc2
-rw-r--r--chrome/browser/sync/engine/syncer_thread.cc38
-rw-r--r--chrome/browser/sync/engine/syncer_thread.h11
-rw-r--r--chrome/browser/sync/engine/syncer_thread_unittest.cc21
-rw-r--r--chrome/browser/sync/engine/syncer_types.h5
-rw-r--r--chrome/browser/sync/engine/syncer_unittest.cc2
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc61
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h54
-rw-r--r--chrome/browser/sync/profile_sync_factory.h5
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.cc6
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.h5
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl_unittest.cc14
-rw-r--r--chrome/browser/sync/profile_sync_factory_mock.h4
-rw-r--r--chrome/browser/sync/profile_sync_service.cc275
-rw-r--r--chrome/browser/sync/profile_sync_service.h53
-rw-r--r--chrome/browser/sync/profile_sync_service_autofill_unittest.cc10
-rw-r--r--chrome/browser/sync/profile_sync_service_mock.h1
-rw-r--r--chrome/browser/sync/profile_sync_service_password_unittest.cc10
-rw-r--r--chrome/browser/sync/profile_sync_service_preference_unittest.cc5
-rw-r--r--chrome/browser/sync/profile_sync_service_session_unittest.cc5
-rw-r--r--chrome/browser/sync/profile_sync_service_startup_unittest.cc64
-rw-r--r--chrome/browser/sync/profile_sync_service_typed_url_unittest.cc10
-rw-r--r--chrome/browser/sync/profile_sync_service_unittest.cc35
-rw-r--r--chrome/browser/sync/sessions/sync_session_context.h7
-rw-r--r--chrome/browser/sync/sessions/sync_session_unittest.cc8
-rw-r--r--chrome/browser/sync/signin_manager.cc95
-rw-r--r--chrome/browser/sync/signin_manager.h81
-rw-r--r--chrome/browser/sync/signin_manager_unittest.cc93
-rw-r--r--chrome/browser/sync/sync_setup_wizard_unittest.cc2
-rw-r--r--chrome/browser/sync/sync_ui_util.cc4
-rw-r--r--chrome/browser/sync/syncable/directory_manager.cc11
-rw-r--r--chrome/browser/sync/syncable/directory_manager.h3
-rw-r--r--chrome/browser/sync/test_profile_sync_service.h9
-rw-r--r--chrome/browser/sync/token_migrator.cc53
-rw-r--r--chrome/browser/sync/token_migrator.h53
-rw-r--r--chrome/browser/views/options/content_page_view.cc2
-rw-r--r--chrome/chrome.gyp4
-rw-r--r--chrome/chrome_browser.gypi26
-rw-r--r--chrome/chrome_tests.gypi4
-rw-r--r--chrome/common/notification_type.h31
-rw-r--r--chrome/common/pref_names.cc7
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--chrome/test/live_sync/live_sync_test.cc10
-rw-r--r--chrome/test/live_sync/offline_sync_test.cc29
-rw-r--r--chrome/test/live_sync/profile_sync_service_test_harness.cc71
-rw-r--r--chrome/test/live_sync/profile_sync_service_test_harness.h12
-rw-r--r--chrome/test/live_sync/single_client_live_bookmarks_sync_test.cc31
-rw-r--r--chrome/test/profile_mock.h1
-rw-r--r--chrome/test/sync/engine/mock_connection_manager.cc2
-rw-r--r--chrome/test/sync/engine/syncer_command_test.h5
-rw-r--r--chrome/test/testing_profile.cc5
-rw-r--r--chrome/test/testing_profile.h3
81 files changed, 1314 insertions, 2035 deletions
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index 9ec92d02..c371880 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -181,6 +181,10 @@ void LoginUtilsImpl::CompleteLogin(const std::string& username,
token_service->StartFetchingTokens();
}
+ // Set the CrOS user by getting this constructor run with the
+ // user's email on first retrieval.
+ profile->GetProfileSyncService(username);
+
// Attempt to take ownership; this will fail if device is already owned.
OwnershipService::GetSharedInstance()->StartTakeOwnershipAttempt(
UserManager::Get()->logged_in_user().email());
diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm
index a2ab751..58df847 100644
--- a/chrome/browser/cocoa/preferences_window_controller.mm
+++ b/chrome/browser/cocoa/preferences_window_controller.mm
@@ -1350,7 +1350,7 @@ const int kDisabledIndex = 1;
} else {
// Otherwise, the sync button was a "sync my bookmarks" button.
// Kick off the sync setup process.
- syncService_->EnableForUser(NULL);
+ syncService_->ShowLoginDialog(NULL);
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
}
}
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
index 6970816..3ecd267 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
@@ -168,7 +168,7 @@ void NewTabPageSyncHandler::HandleSyncLinkClicked(const ListValue* args) {
} else {
// User clicked the 'Start now' link to begin syncing.
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_NTP);
- sync_service_->EnableForUser(NULL);
+ sync_service_->ShowLoginDialog(NULL);
}
}
diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc
index 13b2cea..9d6d72b 100644
--- a/chrome/browser/gtk/options/content_page_gtk.cc
+++ b/chrome/browser/gtk/options/content_page_gtk.cc
@@ -595,7 +595,7 @@ void ContentPageGtk::OnSyncStartStopButtonClicked(GtkWidget* widget) {
gtk_util::ShowDialog(dialog);
return;
} else {
- sync_service_->EnableForUser(NULL);
+ sync_service_->ShowLoginDialog(NULL);
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
}
}
diff --git a/chrome/browser/net/gaia/token_service.cc b/chrome/browser/net/gaia/token_service.cc
index b46868f..b61ab62 100644
--- a/chrome/browser/net/gaia/token_service.cc
+++ b/chrome/browser/net/gaia/token_service.cc
@@ -13,6 +13,8 @@
#include "chrome/common/notification_service.h"
// Unfortunately kNumServices must be defined in the .h.
+// TODO(chron): Sync doesn't use the TalkToken anymore so we can stop
+// requesting it.
const char* TokenService::kServices[] = {GaiaConstants::kSyncService,
GaiaConstants::kTalkService};
TokenService::TokenService()
@@ -29,12 +31,18 @@ void TokenService::Initialize(const char* const source,
Profile* profile) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
-
+ if (!source_.empty()) {
+ // Already initialized.
+ return;
+ }
getter_ = profile->GetRequestContext();
// Since the user can create a bookmark in incognito, sync may be running.
// Thus we have to go for explicit access.
web_data_service_ = profile->GetWebDataService(Profile::EXPLICIT_ACCESS);
source_ = std::string(source);
+ registrar_.Add(this,
+ NotificationType::TOKEN_UPDATED,
+ NotificationService::AllSources());
}
void TokenService::ResetCredentialsInMemory() {
@@ -147,6 +155,12 @@ void TokenService::FireTokenRequestFailedNotification(
Details<const TokenRequestFailedDetails>(&details));
}
+void TokenService::IssueAuthTokenForTest(const std::string& service,
+ const std::string& auth_token) {
+ token_map_[service] = auth_token;
+ FireTokenAvailableNotification(service, auth_token);
+}
+
void TokenService::OnIssueAuthTokenSuccess(const std::string& service,
const std::string& auth_token) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
@@ -178,6 +192,11 @@ void TokenService::OnWebDataServiceRequestDone(WebDataService::Handle h,
result);
LoadTokensIntoMemory(token_result->GetValue(), &token_map_);
}
+
+ NotificationService::current()->Notify(
+ NotificationType::TOKEN_LOADING_FINISHED,
+ Source<TokenService>(this),
+ NotificationService::NoDetails());
}
// Load tokens from the db_token map into the in memory token map.
@@ -207,3 +226,12 @@ void TokenService::LoadTokensIntoMemory(
}
}
}
+
+void TokenService::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::TOKEN_UPDATED);
+ TokenAvailableDetails* tok_details =
+ Details<TokenAvailableDetails>(details).ptr();
+ OnIssueAuthTokenSuccess(tok_details->service(), tok_details->token());
+}
diff --git a/chrome/browser/net/gaia/token_service.h b/chrome/browser/net/gaia/token_service.h
index 20ca12d..006423f 100644
--- a/chrome/browser/net/gaia/token_service.h
+++ b/chrome/browser/net/gaia/token_service.h
@@ -37,12 +37,15 @@
#include <map>
#include <string>
+
+#include "base/gtest_prod_util.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
#include "chrome/common/net/gaia/gaia_authenticator2.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
-#include "base/gtest_prod_util.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
class URLRequestContextGetter;
class Profile;
@@ -50,7 +53,8 @@ class Profile;
// The TokenService is a Profile member, so all calls are expected
// from the UI thread.
class TokenService : public GaiaAuthConsumer,
- public WebDataServiceConsumer {
+ public WebDataServiceConsumer,
+ public NotificationObserver {
public:
TokenService();
virtual ~TokenService();
@@ -123,6 +127,10 @@ class TokenService : public GaiaAuthConsumer,
const bool HasTokenForService(const char* const service) const;
const std::string& GetTokenForService(const char* const service) const;
+ // For tests only. Doesn't save to the WebDB.
+ void IssueAuthTokenForTest(const std::string& service,
+ const std::string& auth_token);
+
// GaiaAuthConsumer implementation.
virtual void OnIssueAuthTokenSuccess(const std::string& service,
const std::string& auth_token);
@@ -133,6 +141,11 @@ class TokenService : public GaiaAuthConsumer,
virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
const WDTypedResult* result);
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
void FireTokenAvailableNotification(const std::string& service,
@@ -169,6 +182,8 @@ class TokenService : public GaiaAuthConsumer,
// Map from service to token.
std::map<std::string, std::string> token_map_;
+ NotificationRegistrar registrar_;
+
FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryBasic);
FRIEND_TEST_ALL_PREFIXES(TokenServiceTest, LoadTokensIntoMemoryAdvanced);
diff --git a/chrome/browser/net/gaia/token_service_unittest.cc b/chrome/browser/net/gaia/token_service_unittest.cc
index 512efff..ce0096b 100644
--- a/chrome/browser/net/gaia/token_service_unittest.cc
+++ b/chrome/browser/net/gaia/token_service_unittest.cc
@@ -4,127 +4,18 @@
//
// This file defines a unit test for the profile's token service.
-#include "chrome/browser/net/gaia/token_service.h"
-#include "chrome/browser/password_manager/encryptor.h"
-#include "chrome/browser/webdata/web_data_service.h"
-#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/browser/net/gaia/token_service_unittest.h"
+
#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/test_url_fetcher_factory.h"
-#include "chrome/test/signaling_task.h"
-#include "chrome/test/test_notification_tracker.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// TestNotificationTracker doesn't do a deep copy on the notification details.
-// We have to in order to read it out, or we have a bad ptr, since the details
-// are a reference on the stack.
-class TokenAvailableTracker : public TestNotificationTracker {
- public:
- const TokenService::TokenAvailableDetails& get_last_token_details() {
- return details_;
- }
-
- private:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- TestNotificationTracker::Observe(type, source, details);
- if (type == NotificationType::TOKEN_AVAILABLE) {
- Details<const TokenService::TokenAvailableDetails> full = details;
- details_ = *full.ptr();
- }
- }
-
- TokenService::TokenAvailableDetails details_;
-};
-
-class TokenFailedTracker : public TestNotificationTracker {
- public:
- const TokenService::TokenRequestFailedDetails& get_last_token_details() {
- return details_;
- }
-
- private:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- TestNotificationTracker::Observe(type, source, details);
- if (type == NotificationType::TOKEN_REQUEST_FAILED) {
- Details<const TokenService::TokenRequestFailedDetails> full = details;
- details_ = *full.ptr();
- }
- }
- TokenService::TokenRequestFailedDetails details_;
-};
-
-class TokenServiceTest : public testing::Test {
+class TokenServiceTest : public TokenServiceTestHarness {
public:
- TokenServiceTest()
- : ui_thread_(ChromeThread::UI, &message_loop_),
- db_thread_(ChromeThread::DB) {
- }
-
virtual void SetUp() {
-#if defined(OS_MACOSX)
- Encryptor::UseMockKeychain(true);
-#endif
- credentials_.sid = "sid";
- credentials_.lsid = "lsid";
- credentials_.token = "token";
- credentials_.data = "data";
-
- ASSERT_TRUE(db_thread_.Start());
-
- profile_.reset(new TestingProfile());
- profile_->CreateWebDataService(false);
- WaitForDBLoadCompletion();
-
- success_tracker_.ListenFor(NotificationType::TOKEN_AVAILABLE,
- Source<TokenService>(&service_));
- failure_tracker_.ListenFor(NotificationType::TOKEN_REQUEST_FAILED,
- Source<TokenService>(&service_));
-
- service_.Initialize("test", profile_.get());
+ TokenServiceTestHarness::SetUp();
service_.UpdateCredentials(credentials_);
-
- URLFetcher::set_factory(NULL);
- }
-
- virtual void TearDown() {
- // You have to destroy the profile before the db_thread_ stops.
- if (profile_.get()) {
- profile_.reset(NULL);
- }
-
- db_thread_.Stop();
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
- MessageLoop::current()->Run();
- }
-
- void WaitForDBLoadCompletion() {
- // The WebDB does all work on the DB thread. This will add an event
- // to the end of the DB thread, so when we reach this task, all DB
- // operations should be complete.
- WaitableEvent done(false, false);
- ChromeThread::PostTask(
- ChromeThread::DB, FROM_HERE, new SignalingTask(&done));
- done.Wait();
-
- // Notifications should be returned from the DB thread onto the UI thread.
- message_loop_.RunAllPending();
}
-
- MessageLoopForUI message_loop_;
- ChromeThread ui_thread_; // Mostly so DCHECKS pass.
- ChromeThread db_thread_; // WDS on here
-
- TokenService service_;
- TokenAvailableTracker success_tracker_;
- TokenFailedTracker failure_tracker_;
- GaiaAuthConsumer::ClientLoginResult credentials_;
- scoped_ptr<TestingProfile> profile_;
};
TEST_F(TokenServiceTest, SanityCheck) {
@@ -145,8 +36,7 @@ TEST_F(TokenServiceTest, NotificationSuccess) {
EXPECT_EQ(1U, success_tracker_.size());
EXPECT_EQ(0U, failure_tracker_.size());
- TokenService::TokenAvailableDetails details =
- success_tracker_.get_last_token_details();
+ TokenService::TokenAvailableDetails details = success_tracker_.details();
// MSVC doesn't like this comparison as EQ.
EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
EXPECT_EQ(details.token(), "token");
@@ -160,8 +50,7 @@ TEST_F(TokenServiceTest, NotificationFailed) {
EXPECT_EQ(0U, success_tracker_.size());
EXPECT_EQ(1U, failure_tracker_.size());
- TokenService::TokenRequestFailedDetails details =
- failure_tracker_.get_last_token_details();
+ TokenService::TokenRequestFailedDetails details = failure_tracker_.details();
// MSVC doesn't like this comparison as EQ.
EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
@@ -275,8 +164,7 @@ TEST_F(TokenServiceTest, LoadTokensIntoMemoryBasic) {
service_.LoadTokensIntoMemory(db_tokens, &memory_tokens);
EXPECT_EQ(1U, success_tracker_.size());
- TokenService::TokenAvailableDetails details =
- success_tracker_.get_last_token_details();
+ TokenService::TokenAvailableDetails details = success_tracker_.details();
// MSVC doesn't like this comparison as EQ.
EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
EXPECT_EQ(details.token(), "token");
diff --git a/chrome/browser/net/gaia/token_service_unittest.h b/chrome/browser/net/gaia/token_service_unittest.h
new file mode 100644
index 0000000..ad46138
--- /dev/null
+++ b/chrome/browser/net/gaia/token_service_unittest.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 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.
+//
+// This file defines a unit test harness for the profile's token service.
+
+#ifndef CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_UNITTEST_H_
+#define CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_UNITTEST_H_
+#pragma once
+
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/password_manager/encryptor.h"
+#include "chrome/browser/webdata/web_data_service.h"
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/test/signaling_task.h"
+#include "chrome/test/test_notification_tracker.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TestNotificationTracker doesn't do a deep copy on the notification details.
+// We have to in order to read it out, or we have a bad ptr, since the details
+// are a reference on the stack.
+class TokenAvailableTracker : public TestNotificationTracker {
+ public:
+ const TokenService::TokenAvailableDetails& details() {
+ return details_;
+ }
+
+ private:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ TestNotificationTracker::Observe(type, source, details);
+ if (type == NotificationType::TOKEN_AVAILABLE) {
+ Details<const TokenService::TokenAvailableDetails> full = details;
+ details_ = *full.ptr();
+ }
+ }
+
+ TokenService::TokenAvailableDetails details_;
+};
+
+class TokenFailedTracker : public TestNotificationTracker {
+ public:
+ const TokenService::TokenRequestFailedDetails& details() {
+ return details_;
+ }
+
+ private:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ TestNotificationTracker::Observe(type, source, details);
+ if (type == NotificationType::TOKEN_REQUEST_FAILED) {
+ Details<const TokenService::TokenRequestFailedDetails> full = details;
+ details_ = *full.ptr();
+ }
+ }
+
+ TokenService::TokenRequestFailedDetails details_;
+};
+
+class TokenServiceTestHarness : public testing::Test {
+ public:
+ TokenServiceTestHarness()
+ : ui_thread_(ChromeThread::UI, &message_loop_),
+ db_thread_(ChromeThread::DB) {
+ }
+
+ virtual void SetUp() {
+#if defined(OS_MACOSX)
+ Encryptor::UseMockKeychain(true);
+#endif
+ credentials_.sid = "sid";
+ credentials_.lsid = "lsid";
+ credentials_.token = "token";
+ credentials_.data = "data";
+
+ ASSERT_TRUE(db_thread_.Start());
+
+ profile_.reset(new TestingProfile());
+ profile_->CreateWebDataService(false);
+ WaitForDBLoadCompletion();
+
+ success_tracker_.ListenFor(NotificationType::TOKEN_AVAILABLE,
+ Source<TokenService>(&service_));
+ failure_tracker_.ListenFor(NotificationType::TOKEN_REQUEST_FAILED,
+ Source<TokenService>(&service_));
+
+ service_.Initialize("test", profile_.get());
+
+ URLFetcher::set_factory(NULL);
+ }
+
+ virtual void TearDown() {
+ // You have to destroy the profile before the db_thread_ stops.
+ if (profile_.get()) {
+ profile_.reset(NULL);
+ }
+
+ db_thread_.Stop();
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+ MessageLoop::current()->Run();
+ }
+
+ void WaitForDBLoadCompletion() {
+ // The WebDB does all work on the DB thread. This will add an event
+ // to the end of the DB thread, so when we reach this task, all DB
+ // operations should be complete.
+ WaitableEvent done(false, false);
+ ChromeThread::PostTask(
+ ChromeThread::DB, FROM_HERE, new SignalingTask(&done));
+ done.Wait();
+
+ // Notifications should be returned from the DB thread onto the UI thread.
+ message_loop_.RunAllPending();
+ }
+
+ MessageLoopForUI message_loop_;
+ ChromeThread ui_thread_; // Mostly so DCHECKS pass.
+ ChromeThread db_thread_; // WDS on here
+
+ TokenService service_;
+ TokenAvailableTracker success_tracker_;
+ TokenFailedTracker failure_tracker_;
+ GaiaAuthConsumer::ClientLoginResult credentials_;
+ scoped_ptr<TestingProfile> profile_;
+};
+
+#endif // CHROME_BROWSER_NET_GAIA_TOKEN_SERVICE_UNITTEST_H_
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 2b37c26..075cbf1 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -42,6 +42,7 @@
#include "chrome/browser/search_engines/keyword_editor_controller.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/ssl/ssl_manager.h"
+#include "chrome/browser/sync/signin_manager.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/pinned_tab_codec.h"
#include "chrome/browser/task_manager.h"
@@ -139,6 +140,7 @@ void RegisterUserPrefs(PrefService* user_prefs) {
#endif
BackgroundContentsService::RegisterUserPrefs(user_prefs);
CookiePromptModalDialog::RegisterUserPrefs(user_prefs);
+ SigninManager::RegisterUserPrefs(user_prefs);
}
} // namespace browser
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 5c3669c..b2d7eba 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -444,6 +444,11 @@ class OffTheRecordProfileImpl : public Profile,
return NULL;
}
+ virtual ProfileSyncService* GetProfileSyncService(
+ const std::string& cros_user) {
+ return NULL;
+ }
+
virtual CloudPrintProxyService* GetCloudPrintProxyService() {
return NULL;
}
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index d876d8c..68eec93 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -377,6 +377,11 @@ class Profile {
// Returns the ProfileSyncService, creating if not yet created.
virtual ProfileSyncService* GetProfileSyncService() = 0;
+ // Returns the ProfileSyncService, creating if not yet created, with
+ // the specified CrOS username.
+ virtual ProfileSyncService* GetProfileSyncService(
+ const std::string& cros_user) = 0;
+
// Returns the CloudPrintProxyService, creating if not yet created.
virtual CloudPrintProxyService* GetCloudPrintProxyService() = 0;
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 6a7cb51..ff6a8da 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -479,6 +479,7 @@ ProfileImpl::~ProfileImpl() {
// Delete the NTP resource cache so we can unregister pref observers.
ntp_resource_cache_.reset();
+ // The sync service needs to be deleted before the services it calls.
sync_service_.reset();
// Both HistoryService and WebDataService maintain threads for background
@@ -1235,10 +1236,16 @@ TokenService* ProfileImpl::GetTokenService() {
}
ProfileSyncService* ProfileImpl::GetProfileSyncService() {
+ return GetProfileSyncService("");
+}
+
+ProfileSyncService* ProfileImpl::GetProfileSyncService(
+ const std::string& cros_user) {
+
if (!ProfileSyncService::IsSyncEnabled())
return NULL;
if (!sync_service_.get())
- InitSyncService();
+ InitSyncService(cros_user);
return sync_service_.get();
}
@@ -1248,11 +1255,11 @@ CloudPrintProxyService* ProfileImpl::GetCloudPrintProxyService() {
return cloud_print_proxy_service_.get();
}
-void ProfileImpl::InitSyncService() {
+void ProfileImpl::InitSyncService(const std::string& cros_user) {
profile_sync_factory_.reset(
new ProfileSyncFactoryImpl(this, CommandLine::ForCurrentProcess()));
sync_service_.reset(
- profile_sync_factory_->CreateProfileSyncService());
+ profile_sync_factory_->CreateProfileSyncService(cros_user));
sync_service_->Initialize();
}
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index d3831cb..79e4438 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -100,8 +100,10 @@ class ProfileImpl : public Profile,
virtual FilePath last_selected_directory();
virtual void set_last_selected_directory(const FilePath& path);
virtual ProfileSyncService* GetProfileSyncService();
+ virtual ProfileSyncService* GetProfileSyncService(
+ const std::string& cros_user);
virtual TokenService* GetTokenService();
- void InitSyncService();
+ void InitSyncService(const std::string& cros_user);
virtual CloudPrintProxyService* GetCloudPrintProxyService();
void InitCloudPrintProxyService();
virtual ChromeBlobStorageContext* GetBlobStorageContext();
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.h b/chrome/browser/sync/abstract_profile_sync_service_test.h
index 7f81ca2..73d59ef 100644
--- a/chrome/browser/sync/abstract_profile_sync_service_test.h
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.h
@@ -12,6 +12,7 @@
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/autofill_model_associator.h"
#include "chrome/browser/sync/glue/password_model_associator.h"
@@ -55,7 +56,7 @@ class ProfileSyncServiceTestHelper {
UserShare* user_share = service->backend()->GetUserShareHandle();
DirectoryManager* dir_manager = user_share->dir_manager.get();
- ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
+ ScopedDirLookup dir(dir_manager, user_share->name);
if (!dir.good())
return false;
@@ -120,6 +121,7 @@ class AbstractProfileSyncServiceTest : public testing::Test {
MessageLoopForUI message_loop_;
ChromeThread ui_thread_;
ProfileSyncFactoryMock factory_;
+ TokenService token_service_;
scoped_ptr<TestProfileSyncService> service_;
TestIdFactory ids_;
};
diff --git a/chrome/browser/sync/engine/all_status.cc b/chrome/browser/sync/engine/all_status.cc
index 178fe7f..72e1f6d 100644
--- a/chrome/browser/sync/engine/all_status.cc
+++ b/chrome/browser/sync/engine/all_status.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
#include "base/port.h"
-#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
#include "chrome/browser/sync/engine/syncer_thread.h"
@@ -48,11 +47,6 @@ AllStatus::~AllStatus() {
delete channel_;
}
-void AllStatus::WatchConnectionManager(ServerConnectionManager* conn_mgr) {
- conn_mgr_hookup_.reset(NewEventListenerHookup(conn_mgr->channel(), this,
- &AllStatus::HandleServerConnectionEvent));
-}
-
void AllStatus::WatchSyncerThread(SyncerThread* syncer_thread) {
syncer_thread_hookup_.reset(syncer_thread == NULL ? NULL :
syncer_thread->relay_channel()->AddObserver(this));
@@ -99,10 +93,6 @@ AllStatus::Status AllStatus::CalcSyncing(const SyncerEvent &event) const {
return status;
}
-AllStatus::Status AllStatus::CalcSyncing() const {
- return CreateBlankStatus();
-}
-
int AllStatus::CalcStatusChanges(Status* old_status) {
int what_changed = 0;
@@ -153,34 +143,6 @@ int AllStatus::CalcStatusChanges(Status* old_status) {
return what_changed;
}
-void AllStatus::HandleAuthWatcherEvent(const AuthWatcherEvent& auth_event) {
- ScopedStatusLockWithNotify lock(this);
- switch (auth_event.what_happened) {
- case AuthWatcherEvent::GAIA_AUTH_FAILED:
- case AuthWatcherEvent::SERVICE_AUTH_FAILED:
- case AuthWatcherEvent::SERVICE_CONNECTION_FAILED:
- case AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START:
- status_.authenticated = false;
- break;
- case AuthWatcherEvent::AUTH_SUCCEEDED:
- // If we've already calculated that the server is reachable, since we've
- // successfully authenticated, we can be confident that the server is up.
- if (status_.server_reachable)
- status_.server_up = true;
-
- if (!status_.authenticated) {
- status_.authenticated = true;
- status_ = CalcSyncing();
- } else {
- lock.set_notify_plan(DONT_NOTIFY);
- }
- break;
- default:
- lock.set_notify_plan(DONT_NOTIFY);
- break;
- }
-}
-
void AllStatus::HandleChannelEvent(const SyncerEvent& event) {
ScopedStatusLockWithNotify lock(this);
switch (event.what_happened) {
@@ -222,6 +184,15 @@ void AllStatus::HandleServerConnectionEvent(
ScopedStatusLockWithNotify lock(this);
status_.server_up = IsGoodReplyFromServer(event.connection_code);
status_.server_reachable = event.server_reachable;
+
+ if (event.connection_code == HttpResponse::SERVER_CONNECTION_OK) {
+ if (!status_.authenticated) {
+ status_ = CreateBlankStatus();
+ }
+ status_.authenticated = true;
+ } else {
+ status_.authenticated = false;
+ }
}
}
diff --git a/chrome/browser/sync/engine/all_status.h b/chrome/browser/sync/engine/all_status.h
index 772f40d..b843a1a 100644
--- a/chrome/browser/sync/engine/all_status.h
+++ b/chrome/browser/sync/engine/all_status.h
@@ -89,7 +89,6 @@ class AllStatus : public ChannelEventHandler<SyncerEvent> {
AllStatus();
~AllStatus();
- void WatchConnectionManager(ServerConnectionManager* conn_mgr);
void HandleServerConnectionEvent(const ServerConnectionEvent& event);
void HandleAuthWatcherEvent(const AuthWatcherEvent& event);
@@ -116,7 +115,6 @@ class AllStatus : public ChannelEventHandler<SyncerEvent> {
// Examines syncer to calculate syncing and the unsynced count,
// and returns a Status with new values.
- Status CalcSyncing() const;
Status CalcSyncing(const SyncerEvent& event) const;
Status CreateBlankStatus() const;
@@ -125,7 +123,6 @@ class AllStatus : public ChannelEventHandler<SyncerEvent> {
Status status_;
Channel* const channel_;
- scoped_ptr<EventListenerHookup> conn_mgr_hookup_;
scoped_ptr<ChannelHookup<SyncerEvent> > syncer_thread_hookup_;
scoped_ptr<EventListenerHookup> diskfull_hookup_;
scoped_ptr<EventListenerHookup> talk_mediator_hookup_;
diff --git a/chrome/browser/sync/engine/auth_watcher.cc b/chrome/browser/sync/engine/auth_watcher.cc
deleted file mode 100644
index b414e18..0000000
--- a/chrome/browser/sync/engine/auth_watcher.cc
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (c) 2006-2009 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 "chrome/browser/sync/engine/auth_watcher.h"
-
-#include "base/file_util.h"
-#include "base/string_util.h"
-#include "chrome/browser/sync/engine/all_status.h"
-#include "chrome/browser/sync/engine/authenticator.h"
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
-#include "chrome/browser/sync/syncable/directory_manager.h"
-#include "chrome/browser/sync/syncable/syncable.h"
-#include "chrome/browser/sync/util/user_settings.h"
-#include "chrome/common/deprecated/event_sys-inl.h"
-#include "chrome/common/net/gaia/gaia_authenticator.h"
-
-// How authentication happens:
-//
-// Kick Off:
-// The sync API looks to see if the user's name and
-// password are stored. If so, it calls authwatcher.Authenticate() with
-// them. Otherwise it fires an error event.
-//
-// On failed Gaia Auth:
-// The AuthWatcher attempts to use saved hashes to authenticate
-// locally, and on success opens the share.
-// On failure, fires an error event.
-//
-// On successful Gaia Auth:
-// AuthWatcher launches a thread to open the share and to get the
-// authentication token from the sync server.
-
-using std::pair;
-using std::string;
-using std::vector;
-
-namespace browser_sync {
-
-AuthWatcher::AuthWatcher(DirectoryManager* dirman,
- ServerConnectionManager* scm,
- const string& user_agent,
- const string& service_id,
- const string& gaia_url,
- UserSettings* user_settings,
- gaia::GaiaAuthenticator* gaia_auth)
- : gaia_(gaia_auth),
- dirman_(dirman),
- scm_(scm),
- status_(NOT_AUTHENTICATED),
- user_settings_(user_settings),
- auth_backend_thread_("SyncEngine_AuthWatcherThread"),
- current_attempt_trigger_(AuthWatcherEvent::USER_INITIATED) {
-
- if (!auth_backend_thread_.Start())
- NOTREACHED() << "Couldn't start SyncEngine_AuthWatcherThread";
-
- gaia_->set_message_loop(message_loop());
- loop_proxy_ = auth_backend_thread_.message_loop_proxy();
-
- connmgr_hookup_.reset(
- NewEventListenerHookup(scm->channel(), this,
- &AuthWatcher::HandleServerConnectionEvent));
- AuthWatcherEvent done = { AuthWatcherEvent::AUTHWATCHER_DESTROYED };
- channel_.reset(new Channel(done));
-}
-
-void AuthWatcher::PersistCredentials() {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- gaia::GaiaAuthenticator::AuthResults results = gaia_->results();
-
- // We just successfully signed in again, let's clear out any residual cached
- // login data from earlier sessions.
- ClearAuthenticationData();
-
- user_settings_->StoreEmailForSignin(results.email, results.primary_email);
- results.email = results.primary_email;
- gaia_->SetUsernamePassword(results.primary_email, results.password);
- if (!user_settings_->VerifyAgainstStoredHash(results.email, results.password))
- user_settings_->StoreHashedPassword(results.email, results.password);
-
- user_settings_->SetAuthTokenForService(results.email,
- SYNC_SERVICE_NAME,
- gaia_->auth_token());
-}
-
-// TODO(chron): Full integration test suite needed. http://crbug.com/35429
-void AuthWatcher::RenewAuthToken(const std::string& updated_token) {
- message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &AuthWatcher::DoRenewAuthToken, updated_token));
-}
-
-void AuthWatcher::DoRenewAuthToken(const std::string& updated_token) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- // TODO(chron): We should probably only store auth token in one place.
- if (scm_->auth_token() == updated_token) {
- return; // This thread is the only one writing to the SCM's auth token.
- }
- LOG(INFO) << "Updating auth token:" << updated_token;
- scm_->set_auth_token(updated_token);
- gaia_->RenewAuthToken(updated_token); // Must be on AuthWatcher thread
- user_settings_->SetAuthTokenForService(user_settings_->email(),
- SYNC_SERVICE_NAME,
- updated_token);
-
- NotifyAuthChanged(user_settings_->email(), updated_token, true);
-}
-
-void AuthWatcher::AuthenticateWithLsid(const std::string& lsid) {
- message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &AuthWatcher::DoAuthenticateWithLsid, lsid));
-}
-
-void AuthWatcher::DoAuthenticateWithLsid(const std::string& lsid) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
-
- AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START };
- NotifyListeners(&event);
-
- if (gaia_->AuthenticateWithLsid(lsid)) {
- PersistCredentials();
- DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token());
- } else {
- ProcessGaiaAuthFailure();
- }
-}
-
-const char kAuthWatcher[] = "AuthWatcher";
-
-void AuthWatcher::AuthenticateWithToken(const std::string& gaia_email,
- const std::string& auth_token) {
- message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &AuthWatcher::DoAuthenticateWithToken, gaia_email, auth_token));
-}
-
-void AuthWatcher::DoAuthenticateWithToken(const std::string& gaia_email,
- const std::string& auth_token) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
-
- Authenticator auth(scm_, user_settings_);
- Authenticator::AuthenticationResult result =
- auth.AuthenticateToken(auth_token);
- string email = gaia_email;
- if (auth.display_email() && *auth.display_email()) {
- email = auth.display_email();
- LOG(INFO) << "Auth returned email " << email << " for gaia email " <<
- gaia_email;
- }
-
- AuthWatcherEvent event = {AuthWatcherEvent::ILLEGAL_VALUE , 0};
- gaia_->SetUsername(email);
- gaia_->SetAuthToken(auth_token);
- const bool was_authenticated = NOT_AUTHENTICATED != status_;
- switch (result) {
- case Authenticator::SUCCESS:
- {
- status_ = GAIA_AUTHENTICATED;
- const std::string& share_name = email;
- user_settings_->SwitchUser(email);
- scm_->set_auth_token(auth_token);
-
- if (!was_authenticated) {
- LOG(INFO) << "Opening DB for AuthenticateWithToken ("
- << share_name << ")";
- dirman_->Open(share_name);
- }
- NotifyAuthChanged(email, auth_token, false);
- return;
- }
- case Authenticator::BAD_AUTH_TOKEN:
- event.what_happened = AuthWatcherEvent::SERVICE_AUTH_FAILED;
- break;
- case Authenticator::CORRUPT_SERVER_RESPONSE:
- case Authenticator::SERVICE_DOWN:
- event.what_happened = AuthWatcherEvent::SERVICE_CONNECTION_FAILED;
- break;
- case Authenticator::USER_NOT_ACTIVATED:
- event.what_happened = AuthWatcherEvent::SERVICE_USER_NOT_SIGNED_UP;
- break;
- default:
- LOG(FATAL) << "Illegal return from AuthenticateToken";
- return;
- }
- // Always fall back to local authentication.
- if (was_authenticated || AuthenticateLocally(email)) {
- if (AuthWatcherEvent::SERVICE_CONNECTION_FAILED == event.what_happened)
- return;
- }
- DCHECK_NE(event.what_happened, AuthWatcherEvent::ILLEGAL_VALUE);
- NotifyListeners(&event);
-}
-
-bool AuthWatcher::AuthenticateLocally(string email) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- user_settings_->GetEmailForSignin(&email);
- if (file_util::PathExists(FilePath(dirman_->GetSyncDataDatabasePath()))) {
- gaia_->SetUsername(email);
- status_ = LOCALLY_AUTHENTICATED;
- user_settings_->SwitchUser(email);
- LOG(INFO) << "Opening DB for AuthenticateLocally (" << email << ")";
- dirman_->Open(email);
- NotifyAuthChanged(email, "", false);
- return true;
- } else {
- return false;
- }
-}
-
-bool AuthWatcher::AuthenticateLocally(string email, const string& password) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- user_settings_->GetEmailForSignin(&email);
- return user_settings_->VerifyAgainstStoredHash(email, password)
- && AuthenticateLocally(email);
-}
-
-void AuthWatcher::ProcessGaiaAuthFailure() {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- gaia::GaiaAuthenticator::AuthResults results = gaia_->results();
- if (LOCALLY_AUTHENTICATED != status_ &&
- AuthenticateLocally(results.email, results.password)) {
- // TODO(chron): Do we really want a bogus token?
- const string auth_token("bogus");
- user_settings_->SetAuthTokenForService(results.email,
- SYNC_SERVICE_NAME,
- auth_token);
- }
- AuthWatcherEvent myevent = { AuthWatcherEvent::GAIA_AUTH_FAILED, &results };
- NotifyListeners(&myevent);
-}
-
-void AuthWatcher::DoAuthenticate(const AuthRequest& request) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
-
- AuthWatcherEvent event = { AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START };
- NotifyListeners(&event);
-
- current_attempt_trigger_ = request.trigger;
-
- // We let the caller be lazy and try using the last captcha token seen by
- // the gaia authenticator if they haven't provided a token but have sent
- // a challenge response. Of course, if the captcha token is specified,
- // we use that one instead.
- std::string captcha_token(request.captcha_token);
- if (!request.captcha_value.empty() && captcha_token.empty())
- captcha_token = gaia_->captcha_token();
-
- if (!request.password.empty()) {
- bool authenticated = false;
- if (!captcha_token.empty()) {
- authenticated = gaia_->Authenticate(request.email, request.password,
- captcha_token,
- request.captcha_value);
- } else {
- authenticated = gaia_->Authenticate(request.email, request.password);
- }
- if (authenticated) {
- PersistCredentials();
- DoAuthenticateWithToken(gaia_->email(), gaia_->auth_token());
- } else {
- ProcessGaiaAuthFailure();
- }
- } else if (!request.auth_token.empty()) {
- DoAuthenticateWithToken(request.email, request.auth_token);
- } else {
- LOG(ERROR) << "Attempt to authenticate with no credentials.";
- }
-}
-
-void AuthWatcher::NotifyAuthChanged(const string& email,
- const string& auth_token,
- bool renewed) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- LOG(INFO) << "NotifyAuthSucceeded";
- AuthWatcherEvent event = {
- renewed ?
- AuthWatcherEvent::AUTH_RENEWED :
- AuthWatcherEvent::AUTH_SUCCEEDED
- };
- event.user_email = email;
- event.auth_token = auth_token;
-
- NotifyListeners(&event);
-}
-
-void AuthWatcher::HandleServerConnectionEvent(
- const ServerConnectionEvent& event) {
- message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &AuthWatcher::DoHandleServerConnectionEvent, event,
- scm_->auth_token()));
-}
-
-void AuthWatcher::DoHandleServerConnectionEvent(
- const ServerConnectionEvent& event,
- const std::string& auth_token_snapshot) {
- DCHECK_EQ(MessageLoop::current(), message_loop());
- if (event.server_reachable &&
- // If the auth_token at the time of the event differs from the current
- // one, we have authenticated since then and don't need to re-try.
- (auth_token_snapshot == gaia_->auth_token()) &&
- (event.connection_code == HttpResponse::SYNC_AUTH_ERROR ||
- status_ == LOCALLY_AUTHENTICATED)) {
- // We're either online or just got reconnected and want to try to
- // authenticate. If we've got a saved token this should just work. If not
- // the auth failure should trigger UI indications that we're not logged in.
-
- // METRIC: If we get a SYNC_AUTH_ERROR, our token expired.
- gaia::GaiaAuthenticator::AuthResults authresults = gaia_->results();
- AuthRequest request = { authresults.email, authresults.password,
- authresults.auth_token, std::string(),
- std::string(),
- AuthWatcherEvent::EXPIRED_CREDENTIALS };
- DoAuthenticate(request);
- }
-}
-
-AuthWatcher::~AuthWatcher() {
- auth_backend_thread_.Stop();
- // The gaia authenticator takes a const MessageLoop* because it only uses it
- // to ensure all methods are invoked on the given loop. Once our thread has
- // stopped, the current message loop will be NULL, and no methods should be
- // invoked on |gaia_| after this point. We could set it to NULL, but
- // abstaining allows for even more sanity checking that nothing is invoked on
- // it from now on.
-}
-
-void AuthWatcher::Authenticate(const string& email, const string& password,
- const string& captcha_token, const string& captcha_value) {
- LOG(INFO) << "AuthWatcher::Authenticate called";
-
- string empty;
- AuthRequest request = { FormatAsEmailAddress(email), password, empty,
- captcha_token, captcha_value,
- AuthWatcherEvent::USER_INITIATED };
- message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(this,
- &AuthWatcher::DoAuthenticate, request));
-}
-
-void AuthWatcher::ClearAuthenticationData() {
- scm_->set_auth_token(std::string());
- user_settings_->ClearAllServiceTokens();
-}
-
-string AuthWatcher::email() const {
- return gaia_->email();
-}
-
-void AuthWatcher::NotifyListeners(AuthWatcherEvent* event) {
- event->trigger = current_attempt_trigger_;
- channel_->NotifyListeners(*event);
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/auth_watcher.h b/chrome/browser/sync/engine/auth_watcher.h
deleted file mode 100644
index da90f95..0000000
--- a/chrome/browser/sync/engine/auth_watcher.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2010 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.
-//
-// AuthWatcher watches authentication events and user open and close
-// events and accordingly opens and closes shares.
-
-#ifndef CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_
-#define CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_
-#pragma once
-
-#include <string>
-
-#include "base/gtest_prod_util.h"
-#include "base/message_loop_proxy.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "base/thread.h"
-#include "chrome/browser/sync/protocol/service_constants.h"
-#include "chrome/common/deprecated/event_sys.h"
-#include "chrome/common/net/gaia/gaia_authenticator.h"
-
-namespace syncable {
-struct DirectoryManagerEvent;
-class DirectoryManager;
-}
-
-namespace browser_sync {
-
-class AuthWatcher;
-class ServerConnectionManager;
-class URLFactory;
-class UserSettings;
-struct ServerConnectionEvent;
-
-struct AuthWatcherEvent {
- enum WhatHappened {
- AUTHENTICATION_ATTEMPT_START,
- AUTHWATCHER_DESTROYED,
- AUTH_RENEWED, // Currently only used in testing.
- AUTH_SUCCEEDED,
- GAIA_AUTH_FAILED,
- SERVICE_USER_NOT_SIGNED_UP,
- SERVICE_AUTH_FAILED,
- SERVICE_CONNECTION_FAILED,
- // Used in a safety check in AuthWatcher::AuthenticateWithToken()
- ILLEGAL_VALUE,
- };
- WhatHappened what_happened;
- const gaia::GaiaAuthenticator::AuthResults* auth_results;
- // use AuthWatcherEvent as its own traits type in hookups.
- typedef AuthWatcherEvent EventType;
- static inline bool IsChannelShutdownEvent(const AuthWatcherEvent& event) {
- return event.what_happened == AUTHWATCHER_DESTROYED;
- }
-
- // Used for AUTH_SUCCEEDED/AUTH_RENEWED notification.
- std::string user_email;
- // May be empty if we're only locally authenticated.
- std::string auth_token;
-
- // How was this auth attempt initiated?
- enum AuthenticationTrigger {
- USER_INITIATED = 0, // default value.
- EXPIRED_CREDENTIALS,
- };
-
- AuthenticationTrigger trigger;
-};
-
-// The mother-class of Authentication for the sync backend. Handles both gaia
-// and sync service authentication via asynchronous Authenticate* methods,
-// raising AuthWatcherEvents on success/failure. The implementation currently
-// runs its own backend thread for the actual auth processing, which means
-// the AuthWatcherEvents can be raised on a different thread than the one that
-// invoked authentication.
-class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
- friend class AuthWatcherTest;
- FRIEND_TEST_ALL_PREFIXES(AuthWatcherTest, Construction);
- public:
- // Normal progression is local -> gaia -> token.
- enum Status { LOCALLY_AUTHENTICATED, GAIA_AUTHENTICATED, NOT_AUTHENTICATED };
- typedef syncable::DirectoryManagerEvent DirectoryManagerEvent;
- typedef syncable::DirectoryManager DirectoryManager;
-
- AuthWatcher(DirectoryManager* dirman,
- ServerConnectionManager* scm,
- const std::string& user_agent,
- const std::string& service_id,
- const std::string& gaia_url,
- UserSettings* user_settings,
- gaia::GaiaAuthenticator* gaia_auth);
- ~AuthWatcher();
-
- typedef EventChannel<AuthWatcherEvent, Lock> Channel;
-
- inline Channel* channel() const {
- return channel_.get();
- }
-
- // The following 3 flavors of authentication routines are asynchronous and can
- // be called from any thread.
- // If |captcha_value| is specified but |captcha_token| is not, this will
- // attempt authentication using the last observed captcha token out of
- // convenience in the common case so the token doesn't have to be plumbed
- // everywhere.
- void Authenticate(const std::string& email, const std::string& password,
- const std::string& captcha_token, const std::string& captcha_value);
-
- void Authenticate(const std::string& email, const std::string& password,
- bool persist_creds_to_disk) {
- Authenticate(email, password, "", "");
- }
-
- // Use this to update only the token of the current email address.
- void RenewAuthToken(const std::string& updated_token);
-
- // Use this version when you don't need the gaia authentication step because
- // you already have a valid LSID cookie for |gaia_email|.
- void AuthenticateWithLsid(const std::string& lsid);
-
- // Use this version when you don't need the gaia authentication step because
- // you already have a valid token for |gaia_email|.
- void AuthenticateWithToken(const std::string& gaia_email,
- const std::string& auth_token);
-
- // Joins on the backend thread. The AuthWatcher is useless after this and
- // should be destroyed.
- void Shutdown() { auth_backend_thread_.Stop(); }
-
- std::string email() const;
- syncable::DirectoryManager* dirman() const { return dirman_; }
- ServerConnectionManager* scm() const { return scm_; }
- UserSettings* settings() const { return user_settings_; }
- Status status() const { return (Status)status_; }
-
- private:
- void ClearAuthenticationData();
-
- void NotifyAuthChanged(const std::string& email,
- const std::string& auth_token,
- bool renewed);
- void HandleServerConnectionEvent(const ServerConnectionEvent& event);
-
- void SaveUserSettings(const std::string& username,
- const std::string& auth_token);
-
- MessageLoop* message_loop() { return auth_backend_thread_.message_loop(); }
-
- base::MessageLoopProxy* message_loop_proxy() {
- return loop_proxy_;
- }
-
- void DoRenewAuthToken(const std::string& updated_token);
-
- // These two helpers should only be called from the auth function.
- // Called when authentication with gaia succeeds, to save credential info.
- void PersistCredentials();
- // Called when authentication with gaia fails.
- void ProcessGaiaAuthFailure();
-
- // Just checks that the user has at least one local share cache.
- bool AuthenticateLocally(std::string email);
- // Also checks the user's password against stored password hash.
- bool AuthenticateLocally(std::string email, const std::string& password);
-
- // Sets the trigger member of the event and sends the event on channel_.
- void NotifyListeners(AuthWatcherEvent* event);
-
- inline std::string FormatAsEmailAddress(const std::string& email) const {
- std::string mail(email);
- if (email.find('@') == std::string::npos) {
- mail.push_back('@');
- // TODO(chron): Should this be done only at the UI level?
- mail.append(DEFAULT_SIGNIN_DOMAIN);
- }
- return mail;
- }
-
- // A struct to marshal various data across to the auth_backend_thread_ on
- // Authenticate() and AuthenticateWithToken calls.
- struct AuthRequest {
- std::string email;
- std::string password;
- std::string auth_token;
- std::string captcha_token;
- std::string captcha_value;
- bool persist_creds_to_disk;
- AuthWatcherEvent::AuthenticationTrigger trigger;
- };
-
- // The public interface Authenticate methods are proxies to these, which
- // can only be called from |auth_backend_thread_|.
- void DoAuthenticate(const AuthRequest& request);
- void DoAuthenticateWithLsid(const std::string& lsid);
- void DoAuthenticateWithToken(const std::string& email,
- const std::string& auth_token);
-
- // The public HandleServerConnectionEvent method proxies to this method, which
- // can only be called on |auth_backend_thread_|.
- void DoHandleServerConnectionEvent(
- const ServerConnectionEvent& event,
- const std::string& auth_token_snapshot);
-
- scoped_ptr<gaia::GaiaAuthenticator> const gaia_;
- syncable::DirectoryManager* const dirman_;
- ServerConnectionManager* const scm_;
- scoped_ptr<EventListenerHookup> connmgr_hookup_;
- Status status_;
- UserSettings* const user_settings_;
- scoped_ptr<Channel> channel_;
-
- base::Thread auth_backend_thread_;
- scoped_refptr<base::MessageLoopProxy> loop_proxy_;
-
- AuthWatcherEvent::AuthenticationTrigger current_attempt_trigger_;
- DISALLOW_COPY_AND_ASSIGN(AuthWatcher);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_ENGINE_AUTH_WATCHER_H_
diff --git a/chrome/browser/sync/engine/auth_watcher_unittest.cc b/chrome/browser/sync/engine/auth_watcher_unittest.cc
deleted file mode 100644
index cc840c7..0000000
--- a/chrome/browser/sync/engine/auth_watcher_unittest.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2010 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/scoped_ptr.h"
-#include "base/scoped_temp_dir.h"
-#include "base/test/test_file_util.h"
-#include "base/waitable_event.h"
-#include "chrome/browser/password_manager/encryptor.h"
-#include "chrome/browser/sync/engine/auth_watcher.h"
-#include "chrome/browser/sync/engine/syncer_thread.h"
-#include "chrome/browser/sync/util/user_settings.h"
-#include "chrome/common/deprecated/event_sys-inl.h"
-#include "chrome/common/net/http_return.h"
-#include "chrome/common/net/gaia/gaia_authenticator.h"
-#include "chrome/test/sync/engine/mock_connection_manager.h"
-#include "chrome/test/sync/engine/test_directory_setter_upper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-static FilePath::CharType kUserSettingsDB[] =
- FILE_PATH_LITERAL("Settings.sqlite3");
-static const char* kTestUserAgent = "useragent";
-static const char* kTestServiceId = "serviceid";
-static const char* kTestGaiaURL = "http://gaia_url";
-static const char* kUserDisplayName = "Mr. Auth Watcher";
-static const char* kUserDisplayEmail = "authwatcherdisplay@gmail.com";
-static const char* kTestEmail = "authwatchertest@gmail.com";
-static const char* kWrongPassword = "wrongpassword";
-static const char* kCorrectPassword = "correctpassword";
-static const char* kValidSID = "validSID";
-static const char* kValidLSID = "validLSID";
-static const char* kInvalidAuthToken = "invalidAuthToken";
-static const char* kValidAuthToken = "validAuthToken";
-
-namespace browser_sync {
-
-class GaiaAuthMockForAuthWatcher : public gaia::GaiaAuthenticator {
- public:
- GaiaAuthMockForAuthWatcher() : GaiaAuthenticator(
- kTestUserAgent, kTestServiceId, kTestGaiaURL),
- use_bad_auth_token_(false) {}
- virtual ~GaiaAuthMockForAuthWatcher() {}
-
- virtual int GetBackoffDelaySeconds(
- int current_backoff_delay) {
- return SyncerThread::GetRecommendedDelaySeconds(current_backoff_delay);
- }
-
- void SendBadAuthTokenForNextRequest() { use_bad_auth_token_ = true; }
-
- std::string renewed_token() {
- return renewed_token_;
- }
-
- protected:
- bool PerformGaiaRequest(const AuthParams& params, AuthResults* results) {
- if (params.password == kWrongPassword) {
- results->auth_error = gaia::BadAuthentication;
- return false;
- }
- if (params.password == kCorrectPassword) {
- results->sid = kValidSID;
- results->lsid = kValidLSID;
- results->auth_token = kValidAuthToken;
- }
- if (use_bad_auth_token_) {
- results->auth_token = kInvalidAuthToken;
- use_bad_auth_token_ = false;
- }
- return true;
- }
-
- void RenewAuthToken(const std::string& auth_token) {
- renewed_token_ = auth_token;
- }
-
- private:
- // Whether we should send an invalid auth token on the next request.
- bool use_bad_auth_token_;
- std::string renewed_token_;
-};
-
-class AuthWatcherTest : public testing::Test {
- public:
- AuthWatcherTest() : metadb_(kUserDisplayEmail),
- consumer_ready(false, false),
- event_produced(false, false),
- last_event_reason_(AuthWatcherEvent::ILLEGAL_VALUE) {}
- virtual void SetUp() {
-#if defined(OS_MACOSX)
- // Need to mock the Keychain for unit tests on Mac to avoid possible
- // blocking UI. |SetAuthTokenForService| uses Encryptor.
- Encryptor::UseMockKeychain(true);
-#endif
- metadb_.SetUp();
- connection_.reset(new MockConnectionManager(metadb_.manager(),
- metadb_.name()));
- // Mock out data that would normally be sent back from a server.
- connection()->SetAuthenticationResponseInfo(kValidAuthToken,
- kUserDisplayName, kUserDisplayEmail, "ID");
- user_settings_.reset(new UserSettings());
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- FilePath user_settings_path = temp_dir_.path().Append(kUserSettingsDB);
- user_settings_->Init(user_settings_path);
- gaia_auth_ = new GaiaAuthMockForAuthWatcher();
- auth_watcher_ = new AuthWatcher(metadb_.manager(), connection_.get(),
- kTestUserAgent, kTestServiceId, kTestGaiaURL,
- user_settings_.get(), gaia_auth_);
- authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(),
- this, &AuthWatcherTest::HandleAuthWatcherEvent));
- }
-
- virtual void TearDown() {
- metadb_.TearDown();
- auth_watcher_->Shutdown();
- EXPECT_FALSE(auth_watcher()->message_loop());
- }
-
- void HandleAuthWatcherEvent(const AuthWatcherEvent& event) {
- if (event.what_happened == AuthWatcherEvent::AUTHWATCHER_DESTROYED)
- return;
- consumer_ready.Wait(); // Block progress until the test is ready.
-
- last_event_reason_ = event.what_happened;
- if (event.what_happened == AuthWatcherEvent::AUTH_SUCCEEDED)
- user_email_ = event.user_email;
-
- event_produced.Signal();
- }
-
- AuthWatcherEvent::WhatHappened ConsumeNextEvent() {
- consumer_ready.Signal();
- event_produced.Wait();
- return last_event_reason_;
- }
-
- AuthWatcher* auth_watcher() { return auth_watcher_.get(); }
- MockConnectionManager* connection() { return connection_.get(); }
- GaiaAuthMockForAuthWatcher* gaia_auth() { return gaia_auth_; }
- const std::string& user_email() { return user_email_; }
-
- private:
- // Responsible for creating / deleting a temp dir containing user settings DB.
- ScopedTempDir temp_dir_;
-
- // The event listener hookup registered for HandleAuthWatcherEvent.
- scoped_ptr<EventListenerHookup> authwatcher_hookup_;
-
- // The sync engine pieces necessary to run an AuthWatcher.
- TriggeredOpenTestDirectorySetterUpper metadb_;
- scoped_ptr<MockConnectionManager> connection_;
- scoped_ptr<UserSettings> user_settings_;
- GaiaAuthMockForAuthWatcher* gaia_auth_; // Owned by auth_watcher_.
- scoped_refptr<AuthWatcher> auth_watcher_;
-
- // This is used to block the AuthWatcherThread when it raises events until we
- // are ready to read the event. It is not a manual-reset event, so it goes
- // straight back to non-signaled after one thread (the main thread) is
- // signaled (or "consumes" the signaled state).
- base::WaitableEvent consumer_ready;
-
- // This is signaled by the AuthWatcherThread after it sets last_event_reason_
- // and possibly user_email_ for us to read.
- base::WaitableEvent event_produced;
-
- // The 'WhatHappened' value from the last AuthWatcherEvent we handled.
- AuthWatcherEvent::WhatHappened last_event_reason_;
-
- // Set when we receive an AUTH_SUCCEEDED event.
- std::string user_email_;
-
- DISALLOW_COPY_AND_ASSIGN(AuthWatcherTest);
-};
-
-TEST_F(AuthWatcherTest, Construction) {
- EXPECT_TRUE(auth_watcher()->message_loop());
- EXPECT_EQ("SyncEngine_AuthWatcherThread",
- auth_watcher()->message_loop()->thread_name());
- EXPECT_TRUE(auth_watcher()->auth_backend_thread_.IsRunning());
- EXPECT_EQ(AuthWatcher::NOT_AUTHENTICATED, auth_watcher()->status());
-}
-
-TEST_F(AuthWatcherTest, AuthenticateGaiaAuthFailure) {
- auth_watcher()->Authenticate(kTestEmail, kWrongPassword,
- std::string(), // captcha_token
- std::string()); // captcha_value
-
- EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent());
- EXPECT_EQ(AuthWatcherEvent::GAIA_AUTH_FAILED, ConsumeNextEvent());
-}
-
-TEST_F(AuthWatcherTest, AuthenticateBadAuthToken) {
- gaia_auth()->SendBadAuthTokenForNextRequest();
- auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(),
- std::string());
- EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent());
- EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent());
-}
-
-TEST_F(AuthWatcherTest, AuthenticateSuccess) {
- auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(),
- std::string());
- EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent());
- EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent());
-
- // The server responds with a different email than what we used in the call
- // to Authenticate, and the AuthWatcher should have told us about.
- EXPECT_EQ(kUserDisplayEmail, user_email());
-}
-
-TEST_F(AuthWatcherTest, AuthenticateWithTokenBadAuthToken) {
- auth_watcher()->AuthenticateWithToken(kTestEmail, kInvalidAuthToken);
- EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent());
-}
-
-TEST_F(AuthWatcherTest, AuthenticateWithTokenSuccess) {
- auth_watcher()->AuthenticateWithToken(kTestEmail, kValidAuthToken);
- EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent());
- EXPECT_EQ(kUserDisplayEmail, user_email());
-}
-
-// Just check that the thread task was properly issued.
-TEST_F(AuthWatcherTest, RenewAuthToken) {
- auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(),
- std::string());
- EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent());
- EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent());
-
- auth_watcher()->RenewAuthToken("updated_token");
- EXPECT_EQ(AuthWatcherEvent::AUTH_RENEWED, ConsumeNextEvent());
- EXPECT_EQ(gaia_auth()->renewed_token(), "updated_token");
- EXPECT_EQ(connection()->auth_token(), "updated_token");
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/authenticator.cc b/chrome/browser/sync/engine/authenticator.cc
deleted file mode 100644
index eec7af3..0000000
--- a/chrome/browser/sync/engine/authenticator.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2006-2009 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 "chrome/browser/sync/engine/authenticator.h"
-
-#include "chrome/browser/sync/engine/net/server_connection_manager.h"
-#include "chrome/browser/sync/engine/syncproto.h"
-#include "chrome/browser/sync/protocol/sync.pb.h"
-#include "chrome/browser/sync/util/user_settings.h"
-#include "chrome/common/deprecated/event_sys-inl.h"
-#include "chrome/common/net/gaia/gaia_authenticator.h"
-
-namespace browser_sync {
-
-using std::string;
-
-Authenticator::Authenticator(ServerConnectionManager* manager,
- UserSettings* settings)
- : server_connection_manager_(manager), settings_(settings) {
-}
-
-Authenticator::Authenticator(ServerConnectionManager* manager)
- : server_connection_manager_(manager), settings_(NULL) {
-}
-
-Authenticator::AuthenticationResult Authenticator::Authenticate() {
- // TODO(sync): Pull and work with saved credentials.
- return NO_SAVED_CREDENTIALS;
-}
-
-Authenticator::AuthenticationResult Authenticator::Authenticate(
- string username, string password) {
- // TODO(sync): need to figure out if this routine is used anywhere other
- // than the test code.
- gaia::GaiaAuthenticator auth_service("ChromiumBrowser", "chromiumsync",
- "https://www.google.com:443/accounts/ClientLogin");
- auth_service.set_message_loop(MessageLoop::current());
- if (!auth_service.Authenticate(username, password)) {
- return UNSPECIFIC_ERROR_RETURN;
- }
- CHECK(!auth_service.auth_token().empty());
- return AuthenticateToken(auth_service.auth_token());
-}
-
-COMPILE_ASSERT(sync_pb::ClientToServerResponse::ErrorType_MAX == 7,
- client_to_server_response_errors_changed);
-
-Authenticator::AuthenticationResult Authenticator::HandleSuccessfulTokenRequest(
- const sync_pb::UserIdentification* user) {
- display_email_ = user->has_email() ? user->email() : "";
- display_name_ = user->has_display_name() ? user->display_name() : "";
- obfuscated_id_ = user->has_obfuscated_id() ? user->obfuscated_id() : "";
- return SUCCESS;
-}
-
-Authenticator::AuthenticationResult Authenticator::AuthenticateToken(
- string auth_token) {
- ClientToServerMessage client_to_server_message;
- // Used to be required for all requests.
- client_to_server_message.set_share("");
- client_to_server_message.set_message_contents(
- ClientToServerMessage::AUTHENTICATE);
-
- string tx, rx;
- client_to_server_message.SerializeToString(&tx);
- HttpResponse http_response;
-
- ServerConnectionManager::PostBufferParams params =
- { tx, &rx, &http_response };
- ScopedServerStatusWatcher watch(server_connection_manager_, &http_response);
- if (!server_connection_manager_->PostBufferWithAuth(&params, auth_token,
- &watch)) {
- LOG(WARNING) << "Error posting from authenticator:" << http_response;
- return SERVICE_DOWN;
- }
- sync_pb::ClientToServerResponse response;
- if (!response.ParseFromString(rx))
- return CORRUPT_SERVER_RESPONSE;
-
- switch (response.error_code()) {
- case sync_pb::ClientToServerResponse::SUCCESS:
- if (response.has_authenticate() && response.authenticate().has_user())
- return HandleSuccessfulTokenRequest(&response.authenticate().user());
- // TODO:(sync) make this CORRUPT_SERVER_RESPONSE when all servers are
- // returning user identification at login time.
- return SUCCESS;
- case sync_pb::ClientToServerResponse::USER_NOT_ACTIVATED:
- return USER_NOT_ACTIVATED;
- case sync_pb::ClientToServerResponse::AUTH_INVALID:
- case sync_pb::ClientToServerResponse::AUTH_EXPIRED:
- // TODO(tim): This is an egregious layering violation (bug 35060).
- http_response.server_status = HttpResponse::SYNC_AUTH_ERROR;
- return BAD_AUTH_TOKEN;
- // should never happen (no birthday in this request).
- case sync_pb::ClientToServerResponse::NOT_MY_BIRTHDAY:
- // should never happen (auth isn't throttled).
- case sync_pb::ClientToServerResponse::THROTTLED:
- // should never happen (only for stores).
- case sync_pb::ClientToServerResponse::ACCESS_DENIED:
- // should never happen (only sent on get updates / commit)
- case sync_pb::ClientToServerResponse::CLEAR_PENDING:
- default:
- LOG(ERROR) << "Corrupt Server packet received by auth, error code " <<
- response.error_code();
- return CORRUPT_SERVER_RESPONSE;
- }
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/engine/authenticator.h b/chrome/browser/sync/engine/authenticator.h
deleted file mode 100644
index 1abca3c..0000000
--- a/chrome/browser/sync/engine/authenticator.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2006-2009 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.
-//
-// The authenticator is a cross-platform class that handles authentication for
-// the sync client.
-//
-// Current State:
-// The authenticator is currently only used to authenticate tokens using the
-// newer protocol buffer request.
-
-#ifndef CHROME_BROWSER_SYNC_ENGINE_AUTHENTICATOR_H_
-#define CHROME_BROWSER_SYNC_ENGINE_AUTHENTICATOR_H_
-#pragma once
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/port.h"
-
-namespace sync_pb {
-class UserIdentification;
-}
-
-namespace browser_sync {
-
-class ServerConnectionManager;
-class UserSettings;
-
-class Authenticator {
- public:
- // Single return enum.
- enum AuthenticationResult {
- SUCCESS = 0,
- // We couldn't log on because we don't have saved credentials.
- NO_SAVED_CREDENTIALS,
- // We can't reach auth server (i.e. we're offline or server's down).
- NOT_CONNECTED,
- // Server's up, but we're down.
- SERVICE_DOWN,
- // We contacted the server, but the response didn't make sense.
- CORRUPT_SERVER_RESPONSE,
- // Bad username/password.
- BAD_CREDENTIALS,
- // Credentials are fine, but the user hasn't signed up.
- USER_NOT_ACTIVATED,
-
- // Return values for internal use.
-
- // We will never return this to the user unless they call AuthenticateToken
- // directly. Other auth functions retry and then return
- // CORRUPT_SERVER_RESPONSE.
- // TODO(sync): Implement retries.
- BAD_AUTH_TOKEN,
- // We should never return this, it's a placeholder during development.
- // TODO(sync): Remove this
- UNSPECIFIC_ERROR_RETURN,
- };
-
- // Constructor. This class will keep the connection authenticated.
- // TODO(sync): Make it work as described.
- // TODO(sync): Require a UI callback mechanism.
- Authenticator(ServerConnectionManager* manager, UserSettings* settings);
-
- // Constructor for a simple authenticator used for programmatic login from
- // test programs.
- explicit Authenticator(ServerConnectionManager* manager);
-
- // This version of Authenticate tries to use saved credentials, if we have
- // any.
- AuthenticationResult Authenticate();
-
- // We save the username and password in memory (if given) so we
- // can refresh the long-lived auth token if it expires.
- // Also we save a 10-bit hash of the password to allow offline login.
- AuthenticationResult Authenticate(std::string username, std::string password);
-
- // A version of the auth token to authenticate cookie portion of
- // authentication. It uses the new proto buffer based call instead of the HTTP
- // GET based one we currently use.
- // Can return one of SUCCESS, SERVICE_DOWN, CORRUPT_SERVER_RESPONSE,
- // USER_NOT_ACTIVATED or BAD_AUTH_TOKEN. See above for the meaning of these
- // values.
- // TODO(sync): Make this function private when we're done.
- AuthenticationResult AuthenticateToken(std::string auth_token);
-
- const char* display_email() const { return display_email_.c_str(); }
- const char* display_name() const { return display_name_.c_str(); }
- private:
- // Stores the information in the UserIdentification returned from the server.
- AuthenticationResult HandleSuccessfulTokenRequest(
- const sync_pb::UserIdentification* user);
- // The server connection manager that we're looking after.
- ServerConnectionManager* server_connection_manager_;
- // Returns SUCCESS or the value that should be returned to the user.
- std::string display_email_;
- std::string display_name_;
- std::string obfuscated_id_;
- UserSettings* const settings_;
- DISALLOW_COPY_AND_ASSIGN(Authenticator);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_ENGINE_AUTHENTICATOR_H_
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.cc b/chrome/browser/sync/engine/net/server_connection_manager.cc
index 4953836..6d35811 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/server_connection_manager.cc
@@ -135,11 +135,9 @@ ServerConnectionManager::ServerConnectionManager(
const string& server,
int port,
bool use_ssl,
- const string& user_agent,
- const string& client_id)
+ const string& user_agent)
: sync_server_(server),
sync_server_port_(port),
- client_id_(client_id),
user_agent_(user_agent),
use_ssl_(use_ssl),
proto_sync_path_(kSyncServerSyncPath),
@@ -163,7 +161,6 @@ void ServerConnectionManager::NotifyStatusChanged() {
channel_->NotifyListeners(event);
}
-// Uses currently set auth token. Set by AuthWatcher.
bool ServerConnectionManager::PostBufferWithCachedAuth(
const PostBufferParams* params, ScopedServerStatusWatcher* watcher) {
string path =
@@ -171,14 +168,6 @@ bool ServerConnectionManager::PostBufferWithCachedAuth(
return PostBufferToPath(params, path, auth_token(), watcher);
}
-bool ServerConnectionManager::PostBufferWithAuth(const PostBufferParams* params,
- const string& auth_token, ScopedServerStatusWatcher* watcher) {
- string path = MakeSyncServerPath(proto_sync_path(),
- MakeSyncQueryString(client_id_));
-
- return PostBufferToPath(params, path, auth_token, watcher);
-}
-
bool ServerConnectionManager::PostBufferToPath(const PostBufferParams* params,
const string& path, const string& auth_token,
ScopedServerStatusWatcher* watcher) {
diff --git a/chrome/browser/sync/engine/net/server_connection_manager.h b/chrome/browser/sync/engine/net/server_connection_manager.h
index 602116a..526dc8e 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/server_connection_manager.h
@@ -213,8 +213,7 @@ class ServerConnectionManager {
ServerConnectionManager(const std::string& server,
int port,
bool use_ssl,
- const std::string& user_agent,
- const std::string& client_id);
+ const std::string& user_agent);
virtual ~ServerConnectionManager();
@@ -225,14 +224,6 @@ class ServerConnectionManager {
virtual bool PostBufferWithCachedAuth(const PostBufferParams* params,
ScopedServerStatusWatcher* watcher);
- // POSTS buffer_in and reads a response into buffer_out. Add a specific auth
- // token to http headers.
- //
- // Returns true if executed successfully.
- virtual bool PostBufferWithAuth(const PostBufferParams* params,
- const std::string& auth_token,
- ScopedServerStatusWatcher* watcher);
-
// Checks the time on the server. Returns false if the request failed. |time|
// is an out parameter that stores the value returned from the server.
virtual bool CheckTime(int32* out_time);
@@ -289,6 +280,11 @@ class ServerConnectionManager {
return NULL; // For testing.
};
+ void set_client_id(const std::string& client_id) {
+ DCHECK(client_id_.empty());
+ client_id_.assign(client_id);
+ }
+
void set_auth_token(const std::string& auth_token) {
// TODO(chron): Consider adding a message loop check here.
AutoLock lock(auth_token_mutex_);
@@ -333,7 +329,7 @@ class ServerConnectionManager {
int sync_server_port_;
// The unique id of the user's client.
- const std::string client_id_;
+ std::string client_id_;
// The user-agent string for HTTP.
std::string user_agent_;
diff --git a/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h b/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h
index 67424b9..4108f9a 100644
--- a/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h
@@ -51,10 +51,8 @@ class SyncAPIServerConnectionManager
int port,
bool use_ssl,
const std::string& client_version,
- const std::string& client_id,
HttpPostProviderFactory* factory)
- : ServerConnectionManager(server, port, use_ssl, client_version,
- client_id),
+ : ServerConnectionManager(server, port, use_ssl, client_version),
post_provider_factory_(factory) {
DCHECK(post_provider_factory_.get());
}
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 00d1c4f..15e0e8d 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -25,7 +25,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/sync/sync_constants.h"
#include "chrome/browser/sync/engine/all_status.h"
-#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/engine/change_reorder_buffer.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
@@ -49,7 +48,6 @@
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/util/crypto_helpers.h"
-#include "chrome/browser/sync/util/user_settings.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/deprecated/event_sys.h"
#include "chrome/common/net/gaia/gaia_authenticator.h"
@@ -61,17 +59,15 @@
using browser_sync::AllStatus;
using browser_sync::AllStatusEvent;
-using browser_sync::AuthWatcher;
-using browser_sync::AuthWatcherEvent;
using browser_sync::Cryptographer;
using browser_sync::KeyParams;
using browser_sync::ModelSafeRoutingInfo;
using browser_sync::ModelSafeWorker;
using browser_sync::ModelSafeWorkerRegistrar;
+using browser_sync::ServerConnectionEvent;
using browser_sync::Syncer;
using browser_sync::SyncerEvent;
using browser_sync::SyncerThread;
-using browser_sync::UserSettings;
using browser_sync::kNigoriTag;
using browser_sync::sessions::SyncSessionContext;
using notifier::TalkMediator;
@@ -910,7 +906,6 @@ class SyncManager::SyncInternal
explicit SyncInternal(SyncManager* sync_manager)
: core_message_loop_(NULL),
observer_(NULL),
- auth_problem_(AuthError::NONE),
sync_manager_(sync_manager),
registrar_(NULL),
notification_pending_(false),
@@ -929,40 +924,25 @@ class SyncManager::SyncInternal
bool Init(const FilePath& database_location,
const std::string& sync_server_and_path,
int port,
- const char* gaia_service_id,
- const char* gaia_source,
bool use_ssl,
HttpPostProviderFactory* post_factory,
- HttpPostProviderFactory* auth_post_factory,
ModelSafeWorkerRegistrar* model_safe_worker_registrar,
- bool attempt_last_user_authentication,
- bool invalidate_last_user_auth_token,
- bool invalidate_xmpp_auth_token,
const char* user_agent,
- const std::string& lsid,
+ const SyncCredentials& credentials,
const bool use_chrome_async_socket,
const bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
const std::string& restored_key_for_bootstrapping);
- // Tell sync engine to submit credentials to GAIA for verification.
- // Successful GAIA authentication will kick off the following chain of events:
- // 1. Cause sync engine to open the syncer database.
- // 2. Trigger the AuthWatcher to create a Syncer for the directory and call
- // SyncerThread::SyncDirectory; the SyncerThread will block until (4).
- // 3. Tell the ServerConnectionManager to pass the newly received GAIA auth
- // token to a sync server to obtain a sync token.
- // 4. On receipt of this token, the ServerConnectionManager broadcasts
- // a server-reachable event, which will unblock the SyncerThread.
- // 5. When StartSyncing is called, the Syncer will begin the sync process, by
- // downloading from or uploading to the server.
- //
- // If authentication fails, an event will be broadcast all the way up to
- // the SyncManager::Observer. It may, in turn, decide to try again with new
- // credentials. Calling this method again is the appropriate course of action
- // to "retry".
- void Authenticate(const std::string& username, const std::string& password,
- const std::string& captcha);
+
+ // Sign into sync with given credentials.
+ // We do not verify the tokens given. After this call, the tokens are set
+ // and the sync DB is open. True if successful, false if something
+ // went wrong.
+ bool SignIn(const SyncCredentials& credentials);
+
+ // Update tokens that we're using in Sync. Email must stay the same.
+ void UpdateCredentials(const SyncCredentials& credentials);
// Tell the sync engine to start the syncing process.
void StartSyncing();
@@ -987,20 +967,17 @@ class SyncManager::SyncInternal
// This listener is called by the syncer channel for all syncer events.
virtual void HandleChannelEvent(const SyncerEvent& event);
- // We have a direct hookup to the authwatcher to be notified for auth failures
- // on startup, to serve our UI needs.
- void HandleAuthWatcherEvent(const AuthWatcherEvent& event);
+ // Listens for notifications from the ServerConnectionManager
+ void HandleServerConnectionEvent(const ServerConnectionEvent& event);
- // Listen here for directory opened events.
- void HandleDirectoryManagerEvent(
- const syncable::DirectoryManagerEvent& event);
+ // Open the directory named with username_for_share
+ bool OpenDirectory();
// Login to the talk mediator with the given credentials.
void TalkMediatorLogin(
const std::string& email, const std::string& token);
// TalkMediator::Delegate implementation.
-
virtual void OnNotificationStateChange(
bool notifications_enabled);
@@ -1016,14 +993,13 @@ class SyncManager::SyncInternal
}
SyncerThread* syncer_thread() { return syncer_thread_.get(); }
TalkMediator* talk_mediator() { return talk_mediator_.get(); }
- AuthWatcher* auth_watcher() { return auth_watcher_.get(); }
void set_observer(SyncManager::Observer* observer) { observer_ = observer; }
UserShare* GetUserShare() { return &share_; }
// Return the currently active (validated) username for use with syncable
// types.
const std::string& username_for_share() const {
- return share_.authenticated_name;
+ return share_.name;
}
// Note about SyncManager::Status implementation: Status is a trimmed
@@ -1078,21 +1054,6 @@ class SyncManager::SyncInternal
}
private:
- // Try to authenticate using a LSID cookie.
- void AuthenticateWithLsid(const std::string& lsid);
-
- // Try to authenticate using persisted credentials from a previous successful
- // authentication. If no such credentials exist, calls OnAuthError on the
- // client to collect credentials. Otherwise, there exist local credentials
- // that were once used for a successful auth, so we'll try to re-use these.
- // Failure of that attempt will be communicated as normal using OnAuthError.
- // Since this entry point will bypass normal GAIA authentication and try to
- // authenticate directly with the sync service using a cached token,
- // authentication failure will generally occur due to expired credentials, or
- // possibly because of a password change.
- bool AuthenticateForUser(const std::string& username,
- const std::string& auth_token);
-
// Helper to call OnAuthError when no authentication credentials are
// available.
void RaiseAuthNeededEvent();
@@ -1171,10 +1132,6 @@ class SyncManager::SyncInternal
// constructing any transaction type.
UserShare share_;
- // A wrapper around a sqlite store used for caching authentication data,
- // last user information, current sync-related URLs, and more.
- scoped_ptr<UserSettings> user_settings_;
-
MessageLoop* core_message_loop_;
// Observer registered via SetObserver/RemoveObserver.
@@ -1195,13 +1152,6 @@ class SyncManager::SyncInternal
// sync components.
AllStatus allstatus_;
- // AuthWatcher kicks off the authentication process and follows it through
- // phase 1 (GAIA) to phase 2 (sync engine). As part of this work it determines
- // the initial connectivity and causes the server connection event to be
- // broadcast, which signals the syncer thread to start syncing.
- // It has a heavy duty constructor requiring boilerplate so we heap allocate.
- scoped_refptr<AuthWatcher> auth_watcher_;
-
// Each element of this array is a store of change records produced by
// HandleChangeEvent during the CALCULATE_CHANGES step. The changes are
// segregated by model type, and are stored here to be processed and
@@ -1213,20 +1163,12 @@ class SyncManager::SyncInternal
scoped_ptr<browser_sync::ChannelHookup<syncable::DirectoryChangeEvent> >
dir_change_hookup_;
+ // Event listener hookup for the ServerConnectionManager.
+ scoped_ptr<EventListenerHookup> connection_manager_hookup_;
+
// The event listener hookup registered for HandleSyncerEvent.
scoped_ptr<browser_sync::ChannelHookup<SyncerEvent> > syncer_event_;
- // The event listener hookup registered for HandleAuthWatcherEvent.
- scoped_ptr<EventListenerHookup> authwatcher_hookup_;
-
- // The event listener hookup registered for the DirectoryManager (OPENED).
- scoped_ptr<EventListenerHookup> directory_manager_hookup_;
-
- // Our cache of a recent authentication problem. If no authentication problem
- // occurred, or if the last problem encountered has been cleared (by a
- // subsequent AuthWatcherEvent), this is set to NONE.
- AuthError::State auth_problem_;
-
// The sync dir_manager to which we belong.
SyncManager* const sync_manager_;
@@ -1261,17 +1203,11 @@ SyncManager::SyncManager() {
bool SyncManager::Init(const FilePath& database_location,
const char* sync_server_and_path,
int sync_server_port,
- const char* gaia_service_id,
- const char* gaia_source,
bool use_ssl,
HttpPostProviderFactory* post_factory,
- HttpPostProviderFactory* auth_post_factory,
ModelSafeWorkerRegistrar* registrar,
- bool attempt_last_user_authentication,
- bool invalidate_last_user_auth_token,
- bool invalidate_xmpp_auth_token,
const char* user_agent,
- const char* lsid,
+ const SyncCredentials& credentials,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -1282,29 +1218,22 @@ bool SyncManager::Init(const FilePath& database_location,
return data_->Init(database_location,
server_string,
sync_server_port,
- gaia_service_id,
- gaia_source,
use_ssl,
post_factory,
- auth_post_factory,
registrar,
- attempt_last_user_authentication,
- invalidate_last_user_auth_token,
- invalidate_xmpp_auth_token,
user_agent,
- lsid,
+ credentials,
use_chrome_async_socket,
try_ssltcp_first,
notification_method,
restored_key_for_bootstrapping);
}
-void SyncManager::Authenticate(const char* username, const char* password,
- const char* captcha) {
- data_->Authenticate(std::string(username), std::string(password),
- std::string(captcha));
+void SyncManager::UpdateCredentials(const SyncCredentials& credentials) {
+ data_->UpdateCredentials(credentials);
}
+
bool SyncManager::InitialSyncEndedForAllEnabledTypes() {
return data_->InitialSyncEndedForAllEnabledTypes();
}
@@ -1329,6 +1258,7 @@ void SyncManager::RequestNudge() {
data_->syncer_thread()->NudgeSyncer(0, SyncerThread::kLocal);
}
+// TODO(chron): Don't need to plumb this so deep.
const std::string& SyncManager::GetAuthenticatedUsername() {
DCHECK(data_);
return data_->username_for_share();
@@ -1338,17 +1268,11 @@ bool SyncManager::SyncInternal::Init(
const FilePath& database_location,
const std::string& sync_server_and_path,
int port,
- const char* gaia_service_id,
- const char* gaia_source,
bool use_ssl,
HttpPostProviderFactory* post_factory,
- HttpPostProviderFactory* auth_post_factory,
ModelSafeWorkerRegistrar* model_safe_worker_registrar,
- bool attempt_last_user_authentication,
- bool invalidate_last_user_auth_token,
- bool invalidate_xmpp_auth_token,
const char* user_agent,
- const std::string& lsid,
+ const SyncCredentials& credentials,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -1359,32 +1283,16 @@ bool SyncManager::SyncInternal::Init(
core_message_loop_ = MessageLoop::current();
DCHECK(core_message_loop_);
notification_method_ = notification_method;
- // Set up UserSettings, creating the db if necessary. We need this to
- // instantiate a URLFactory to give to the Syncer.
- FilePath settings_db_file =
- database_location.Append(FilePath(kBookmarkSyncUserSettingsDatabase));
- user_settings_.reset(new UserSettings());
- if (!user_settings_->Init(settings_db_file))
- return false;
-
registrar_ = model_safe_worker_registrar;
- LOG(INFO) << "Initialized sync user settings. Starting DirectoryManager.";
-
share_.dir_manager.reset(new DirectoryManager(database_location));
- directory_manager_hookup_.reset(NewEventListenerHookup(
- share_.dir_manager->channel(), this,
- &SyncInternal::HandleDirectoryManagerEvent));
- share_.dir_manager->cryptographer()->Bootstrap(
- restored_key_for_bootstrapping);
- string client_id = user_settings_->GetClientId();
connection_manager_.reset(new SyncAPIServerConnectionManager(
- sync_server_and_path, port, use_ssl, user_agent, client_id,
- post_factory));
+ sync_server_and_path, port, use_ssl, user_agent, post_factory));
- // Watch various objects for aggregated status.
- allstatus_.WatchConnectionManager(connection_manager());
+ connection_manager_hookup_.reset(
+ NewEventListenerHookup(connection_manager()->channel(), this,
+ &SyncManager::SyncInternal::HandleServerConnectionEvent));
net::NetworkChangeNotifier::AddObserver(this);
// TODO(akalin): CheckServerReachable() can block, which may cause jank if we
@@ -1404,7 +1312,7 @@ bool SyncManager::SyncInternal::Init(
const bool kInitializeSsl = true;
const bool kConnectImmediately = false;
talk_mediator_.reset(new TalkMediatorImpl(mediator_thread, kInitializeSsl,
- kConnectImmediately, invalidate_xmpp_auth_token));
+ kConnectImmediately, false));
if (notification_method != browser_sync::NOTIFICATION_LEGACY &&
notification_method != browser_sync::NOTIFICATION_SERVER) {
if (notification_method == browser_sync::NOTIFICATION_TRANSITIONAL) {
@@ -1417,30 +1325,11 @@ bool SyncManager::SyncInternal::Init(
// Listen to TalkMediator events ourselves
talk_mediator_->SetDelegate(this);
- std::string gaia_url = gaia::kGaiaUrl;
- const char* service_id = gaia_service_id ?
- gaia_service_id : SYNC_SERVICE_NAME;
-
- BridgedGaiaAuthenticator* gaia_auth = new BridgedGaiaAuthenticator(
- gaia_source, service_id, gaia_url, auth_post_factory);
-
- LOG(INFO) << "Sync is bringing up authwatcher and SyncSessionContext.";
-
- auth_watcher_ = new AuthWatcher(dir_manager(),
- connection_manager(),
- gaia_source,
- service_id,
- gaia_url,
- user_settings_.get(),
- gaia_auth);
-
- authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(),
- this, &SyncInternal::HandleAuthWatcherEvent));
+ LOG(INFO) << "Sync is bringing up SyncSessionContext.";
// Build a SyncSessionContext and store the worker in it.
SyncSessionContext* context = new SyncSessionContext(
- connection_manager_.get(), auth_watcher(),
- dir_manager(), model_safe_worker_registrar);
+ connection_manager_.get(), dir_manager(), model_safe_worker_registrar);
// The SyncerThread takes ownership of |context|.
syncer_thread_ = new SyncerThread(context);
@@ -1449,22 +1338,7 @@ bool SyncManager::SyncInternal::Init(
// Subscribe to the syncer thread's channel.
syncer_event_.reset(syncer_thread()->relay_channel()->AddObserver(this));
- bool attempting_auth = false;
- std::string username, auth_token;
- if (attempt_last_user_authentication &&
- auth_watcher()->settings()->GetLastUserAndServiceToken(
- SYNC_SERVICE_NAME, &username, &auth_token)) {
- if (invalidate_last_user_auth_token) {
- auth_token += "bogus";
- }
- attempting_auth = AuthenticateForUser(username, auth_token);
- } else if (!lsid.empty()) {
- attempting_auth = true;
- AuthenticateWithLsid(lsid);
- }
- if (attempt_last_user_authentication && !attempting_auth)
- RaiseAuthNeededEvent();
- return true;
+ return SignIn(credentials);
}
void SyncManager::SyncInternal::StartSyncing() {
@@ -1536,53 +1410,62 @@ void SyncManager::SyncInternal::SendPendingXMPPNotification(
}
}
-void SyncManager::SyncInternal::Authenticate(const std::string& username,
- const std::string& password,
- const std::string& captcha) {
- DCHECK(username_for_share().empty() || username == username_for_share())
- << "Username change from valid username detected";
- if (allstatus_.status().authenticated)
- return;
- if (password.empty()) {
- // TODO(timsteele): Seems like this shouldn't be needed, but auth_watcher
- // currently drops blank password attempts on the floor and doesn't update
- // state; it only LOGs an error in this case. We want to make sure we set
- // our GoogleServiceAuthError state to denote an error.
- RaiseAuthNeededEvent();
+bool SyncManager::SyncInternal::OpenDirectory() {
+ DCHECK(!initialized()) << "Should only happen once";
+
+ bool share_opened = dir_manager()->Open(username_for_share());
+ DCHECK(share_opened);
+ if (!share_opened) {
+ if (observer_) {
+ observer_->OnStopSyncingPermanently();
+ }
+
+ LOG(ERROR) << "Could not open share for:" << username_for_share();
+ return false;
+ }
+
+ // Database has to be initialized for the guid to be available.
+ syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
+ if (!lookup.good()) {
+ NOTREACHED();
+ return false;
}
- auth_watcher()->Authenticate(username, password, std::string(),
- captcha);
-}
-void SyncManager::SyncInternal::AuthenticateWithLsid(const string& lsid) {
- DCHECK(!lsid.empty());
- auth_watcher()->AuthenticateWithLsid(lsid);
+ connection_manager()->set_client_id(lookup->cache_guid());
+ syncer_thread()->CreateSyncer(username_for_share());
+ MarkAndNotifyInitializationComplete();
+ dir_change_hookup_.reset(lookup->AddChangeObserver(this));
+ return true;
}
-bool SyncManager::SyncInternal::AuthenticateForUser(
- const std::string& username, const std::string& auth_token) {
- share_.authenticated_name = username;
+bool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) {
+ DCHECK_EQ(MessageLoop::current(), core_message_loop_);
+ DCHECK(share_.name.empty());
+ share_.name = credentials.email;
- // We optimize by opening the directory before the "fresh" authentication
- // attempt completes so that we can immediately begin processing changes.
- if (!dir_manager()->Open(username_for_share())) {
- if (observer_)
- observer_->OnStopSyncingPermanently();
+ LOG(INFO) << "Signing in user: " << username_for_share();
+ if (!OpenDirectory()) {
return false;
}
- // Load the last-known good auth token into the connection manager and send
- // it off to the AuthWatcher for validation. The result of the validation
- // will update the connection manager if necessary.
- connection_manager()->set_auth_token(auth_token);
- auth_watcher()->AuthenticateWithToken(username, auth_token);
+ UpdateCredentials(credentials);
return true;
}
+void SyncManager::SyncInternal::UpdateCredentials(
+ const SyncCredentials& credentials) {
+ DCHECK_EQ(MessageLoop::current(), core_message_loop_);
+ DCHECK(share_.name == credentials.email);
+ connection_manager()->set_auth_token(credentials.sync_token);
+ TalkMediatorLogin(credentials.email, credentials.sync_token);
+ CheckServerReachable();
+ sync_manager_->RequestNudge();
+}
+
void SyncManager::SyncInternal::RaiseAuthNeededEvent() {
- auth_problem_ = AuthError::INVALID_GAIA_CREDENTIALS;
- if (observer_)
- observer_->OnAuthError(AuthError(auth_problem_));
+ if (observer_) {
+ observer_->OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS));
+ }
}
void SyncManager::SyncInternal::SetPassphrase(
@@ -1642,15 +1525,6 @@ void SyncManager::SyncInternal::Shutdown() {
// TODO(akalin): NULL the other member variables defensively, too.
scoped_ptr<TalkMediator> talk_mediator(talk_mediator_.release());
- // First reset the AuthWatcher in case an auth attempt is in progress so that
- // it terminates gracefully before we shutdown and close other components.
- // Otherwise the attempt can complete after we've closed the directory, for
- // example, and cause initialization to continue, which is bad.
- if (auth_watcher_) {
- auth_watcher_->Shutdown();
- authwatcher_hookup_.reset();
- }
-
if (syncer_thread()) {
if (!syncer_thread()->Stop(kThreadExitTimeoutMsec)) {
LOG(FATAL) << "Unable to stop the syncer, it won't be happy...";
@@ -1659,15 +1533,6 @@ void SyncManager::SyncInternal::Shutdown() {
syncer_thread_ = NULL;
}
- // TODO(chron): Since the auth_watcher_ is held by the sync session state,
- // we release the ref here after the syncer is deallocated.
- // In reality the SyncerSessionState's pointer to the
- // authwatcher should be ref counted, but for M6 we use this
- // lower risk fix so it's deallocated on the original thread.
- if (auth_watcher_) {
- auth_watcher_ = NULL;
- }
-
// Shutdown the xmpp buzz connection.
if (talk_mediator.get()) {
LOG(INFO) << "P2P: Mediator logout started.";
@@ -1679,7 +1544,7 @@ void SyncManager::SyncInternal::Shutdown() {
// Pump any messages the auth watcher, syncer thread, or talk
// mediator posted before they shut down. (See HandleSyncerEvent(),
- // HandleAuthWatcherEvent(), and HandleTalkMediatorEvent() for the
+ // and HandleTalkMediatorEvent() for the
// events that may be posted.)
{
CHECK(core_message_loop_);
@@ -1691,6 +1556,8 @@ void SyncManager::SyncInternal::Shutdown() {
net::NetworkChangeNotifier::RemoveObserver(this);
+ connection_manager_hookup_.reset();
+
if (dir_manager()) {
dir_manager()->FinalSaveChangesForAll();
dir_manager()->Close(username_for_share());
@@ -1699,7 +1566,6 @@ void SyncManager::SyncInternal::Shutdown() {
// Reset the DirectoryManager and UserSettings so they relinquish sqlite
// handles to backing files.
share_.dir_manager.reset();
- user_settings_.reset();
// We don't want to process any more events.
dir_change_hookup_.reset();
@@ -1712,22 +1578,7 @@ void SyncManager::SyncInternal::OnIPAddressChanged() {
// TODO(akalin): CheckServerReachable() can block, which may cause
// jank if we try to shut down sync. Fix this.
connection_manager()->CheckServerReachable();
-}
-
-void SyncManager::SyncInternal::HandleDirectoryManagerEvent(
- const syncable::DirectoryManagerEvent& event) {
- LOG(INFO) << "Sync internal handling a directory manager event";
- if (syncable::DirectoryManagerEvent::OPENED == event.what_happened) {
- DCHECK(!initialized()) << "Should only happen once";
- if (username_for_share().empty()) {
- share_.authenticated_name = event.dirname;
- }
- DCHECK(LowerCaseEqualsASCII(username_for_share(),
- StringToLowerASCII(event.dirname).c_str()))
- << "username_for_share= " << username_for_share()
- << ", event.dirname= " << event.dirname;
- MarkAndNotifyInitializationComplete();
- }
+ sync_manager_->RequestNudge();
}
// Listen to model changes, filter out ones initiated by the sync API, and
@@ -1750,6 +1601,25 @@ void SyncManager::SyncInternal::HandleChannelEvent(
}
}
+void SyncManager::SyncInternal::HandleServerConnectionEvent(
+ const ServerConnectionEvent& event) {
+ allstatus_.HandleServerConnectionEvent(event);
+ if (event.what_happened == ServerConnectionEvent::STATUS_CHANGED) {
+ if (event.connection_code ==
+ browser_sync::HttpResponse::SERVER_CONNECTION_OK) {
+ if (observer_) {
+ observer_->OnAuthError(AuthError(AuthError::None()));
+ }
+ }
+
+ if (event.connection_code == browser_sync::HttpResponse::SYNC_AUTH_ERROR) {
+ if (observer_) {
+ observer_->OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS));
+ }
+ }
+ }
+}
+
void SyncManager::SyncInternal::HandleTransactionEndingChangeEvent(
const syncable::DirectoryChangeEvent& event) {
// This notification happens immediately before a syncable WriteTransaction
@@ -1981,105 +1851,11 @@ void SyncManager::SyncInternal::HandleChannelEvent(const SyncerEvent& event) {
observer_->OnStopSyncingPermanently();
return;
}
-}
-void SyncManager::SyncInternal::HandleAuthWatcherEvent(
- const AuthWatcherEvent& event) {
- allstatus_.HandleAuthWatcherEvent(event);
- // We don't care about an authentication attempt starting event, and we
- // don't want to reset our state to GoogleServiceAuthError::NONE because the
- // fact that an _attempt_ is starting doesn't change the fact that we have an
- // auth problem.
- if (event.what_happened == AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START)
+ if (event.what_happened == SyncerEvent::UPDATED_TOKEN) {
+ observer_->OnUpdatedToken(event.updated_token);
return;
- // We clear our last auth problem cache on new auth watcher events, and only
- // set it to indicate a problem state for certain AuthWatcherEvent types.
- auth_problem_ = AuthError::NONE;
- switch (event.what_happened) {
- case AuthWatcherEvent::AUTH_SUCCEEDED:
- DCHECK(!event.user_email.empty());
- // We now know the supplied username and password were valid. If this
- // wasn't the first sync, authenticated_name should already be assigned.
- if (username_for_share().empty()) {
- share_.authenticated_name = event.user_email;
- }
-
- DCHECK(LowerCaseEqualsASCII(username_for_share(),
- StringToLowerASCII(event.user_email).c_str()))
- << "username_for_share= " << username_for_share()
- << ", event.user_email= " << event.user_email;
-
- if (observer_)
- observer_->OnAuthError(AuthError::None());
-
- // Hook up the DirectoryChangeEvent listener, HandleChangeEvent.
- {
- syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
- if (!lookup.good()) {
- DCHECK(false) << "ScopedDirLookup creation failed; unable to hook "
- << "up directory change event listener!";
- return;
- }
-
- // Note that we can end up here multiple times, for example if the
- // user had to re-login and we got a second AUTH_SUCCEEDED event. Take
- // care not to add ourselves as an observer a second time.
- if (!dir_change_hookup_.get())
- dir_change_hookup_.reset(lookup->AddChangeObserver(this));
- }
-
- if (!event.auth_token.empty()) {
- core_message_loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(
- this, &SyncManager::SyncInternal::TalkMediatorLogin,
- event.user_email, event.auth_token));
- }
- return;
- case AuthWatcherEvent::AUTH_RENEWED:
- DCHECK(!event.user_email.empty());
- DCHECK(!event.auth_token.empty());
- core_message_loop_->PostTask(
- FROM_HERE,
- NewRunnableMethod(
- this, &SyncManager::SyncInternal::TalkMediatorLogin,
- event.user_email, event.auth_token));
- return;
- // Authentication failures translate to GoogleServiceAuthError events.
- case AuthWatcherEvent::GAIA_AUTH_FAILED: // Invalid GAIA credentials.
- if (event.auth_results->auth_error == gaia::CaptchaRequired) {
- auth_problem_ = AuthError::CAPTCHA_REQUIRED;
- std::string url_string("https://www.google.com/accounts/");
- url_string += event.auth_results->captcha_url;
- GURL captcha(url_string);
- observer_->OnAuthError(AuthError::FromCaptchaChallenge(
- event.auth_results->captcha_token, captcha,
- GURL(event.auth_results->auth_error_url)));
- return;
- } else if (event.auth_results->auth_error ==
- gaia::ConnectionUnavailable) {
- auth_problem_ = AuthError::CONNECTION_FAILED;
- } else {
- auth_problem_ = AuthError::INVALID_GAIA_CREDENTIALS;
- }
- break;
- case AuthWatcherEvent::SERVICE_AUTH_FAILED: // Expired GAIA credentials.
- auth_problem_ = AuthError::INVALID_GAIA_CREDENTIALS;
- break;
- case AuthWatcherEvent::SERVICE_USER_NOT_SIGNED_UP:
- auth_problem_ = AuthError::USER_NOT_SIGNED_UP;
- break;
- case AuthWatcherEvent::SERVICE_CONNECTION_FAILED:
- auth_problem_ = AuthError::CONNECTION_FAILED;
- break;
- default: // We don't care about the many other AuthWatcherEvent types.
- return;
}
-
-
- // Fire notification that the status changed due to an authentication error.
- if (observer_)
- observer_->OnAuthError(AuthError(auth_problem_));
}
void SyncManager::SyncInternal::OnNotificationStateChange(
@@ -2121,8 +1897,8 @@ void SyncManager::SyncInternal::TalkMediatorLogin(
<< "(talk_mediator_ is NULL)";
return;
}
- // TODO(akalin): Make talk_mediator automatically login on
- // auth token change.
+ LOG(INFO) << "P2P: Trying talk mediator login.";
+
talk_mediator_->SetAuthToken(email, token, SYNC_SERVICE_NAME);
talk_mediator_->Login();
}
@@ -2184,7 +1960,7 @@ void SyncManager::SetupForTestMode(const std::wstring& test_username) {
void SyncManager::SyncInternal::SetupForTestMode(
const std::wstring& test_username) {
- share_.authenticated_name = WideToUTF8(test_username);
+ share_.name = WideToUTF8(test_username);
// Some tests are targeting only local db operations & integrity, and don't
// want syncer thread interference.
@@ -2192,18 +1968,8 @@ void SyncManager::SyncInternal::SetupForTestMode(
allstatus_.WatchSyncerThread(NULL);
syncer_thread_ = NULL;
- if (!dir_manager()->Open(username_for_share()))
+ if (!dir_manager()->Open(username_for_share())) {
DCHECK(false) << "Could not open directory when running in test mode";
-
- // Hook up the DirectoryChangeEvent listener, HandleChangeEvent.
- {
- syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
- if (!lookup.good()) {
- DCHECK(false) << "ScopedDirLookup creation failed; unable to hook "
- << "up directory change event listener!";
- return;
- }
- dir_change_hookup_.reset(lookup->AddChangeObserver(this));
}
}
@@ -2213,7 +1979,7 @@ BaseTransaction::BaseTransaction(UserShare* share)
: lookup_(NULL) {
DCHECK(share && share->dir_manager.get());
lookup_ = new syncable::ScopedDirLookup(share->dir_manager.get(),
- share->authenticated_name);
+ share->name);
cryptographer_ = share->dir_manager->cryptographer();
if (!(lookup_->good()))
DCHECK(false) << "ScopedDirLookup failed on valid DirManager.";
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
index e4e8510..16f8bd9 100644
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -107,12 +107,14 @@ struct UserShare {
// be shared across multiple threads (unlike Directory).
scoped_ptr<syncable::DirectoryManager> dir_manager;
- // The username of the sync user. This is empty until we have performed at
- // least one successful GAIA authentication with this username, which means
- // on first-run it is empty until an AUTH_SUCCEEDED event and on future runs
- // it is set as soon as the client instructs us to authenticate for the last
- // known valid user (AuthenticateForLastKnownUser()).
- std::string authenticated_name;
+ // The username of the sync user.
+ std::string name;
+};
+
+// Contains everything needed to talk to and identify a user account.
+struct SyncCredentials {
+ std::string email;
+ std::string sync_token;
};
// A valid BaseNode will never have an ID of zero.
@@ -669,6 +671,9 @@ class SyncManager {
// Called when user interaction may be required due to an auth problem.
virtual void OnAuthError(const GoogleServiceAuthError& auth_error) = 0;
+ // Called when a new auth token is provided by the sync server.
+ virtual void OnUpdatedToken(const std::string& token) = 0;
+
// Called when user interaction is required to obtain a valid passphrase.
virtual void OnPassphraseRequired() = 0;
@@ -715,52 +720,22 @@ class SyncManager {
// |sync_server_and_path| and |sync_server_port| represent the Chrome sync
// server to use, and |use_ssl| specifies whether to communicate securely;
// the default is false.
- // |gaia_service_id| is the service id used for GAIA authentication. If it's
- // null then default will be used.
// |post_factory| will be owned internally and used to create
// instances of an HttpPostProvider.
- // |auth_post_factory| will be owned internally and used to create
- // instances of an HttpPostProvider for communicating with GAIA.
- // TODO(timsteele): It seems like one factory should suffice, but for now to
- // avoid having to deal with threading issues since the auth code and syncer
- // code live on separate threads that run simultaneously, we just dedicate
- // one to each component. Long term we may want to reconsider the HttpBridge
- // API to take all the params in one chunk in a threadsafe manner.. which is
- // still suboptimal as there will be high contention between the two threads
- // on startup; so maybe what we have now is the best solution- it does mirror
- // the CURL implementation as each thread creates their own internet handle.
- // Investigate.
// |model_safe_worker| ownership is given to the SyncManager.
// |user_agent| is a 7-bit ASCII string suitable for use as the User-Agent
// HTTP header. Used internally when collecting stats to classify clients.
- // As a fallback when no cached auth information is available, try to
- // bootstrap authentication using |lsid|, if it isn't empty.
- //
- // |invalidate_last_user_auth_token| makes it so that any auth token
- // read from user settings is invalidated. This is used for testing
- // code paths related to authentication failures.
- //
- // |invalidate_xmpp_auth_token| makes it so that any auth token
- // used to log into XMPP is invalidated. This is used for testing
- // code paths related to authentication failures for XMPP only.
- //
// |try_ssltcp_first| indicates that the SSLTCP port (443) is tried before the
// the XMPP port (5222) during login. It is used by the sync tests that are
// run on the chromium builders because port 5222 is blocked.
bool Init(const FilePath& database_location,
const char* sync_server_and_path,
int sync_server_port,
- const char* gaia_service_id,
- const char* gaia_source,
bool use_ssl,
HttpPostProviderFactory* post_factory,
- HttpPostProviderFactory* auth_post_factory,
browser_sync::ModelSafeWorkerRegistrar* registrar,
- bool attempt_last_user_authentication,
- bool invalidate_last_user_auth_token,
- bool invalidate_xmpp_auth_token,
const char* user_agent,
- const char* lsid,
+ const SyncCredentials& credentials,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -776,15 +751,11 @@ class SyncManager {
// called.
bool InitialSyncEndedForAllEnabledTypes();
- // Submit credentials to GAIA for verification. On success, both |username|
- // and the obtained auth token are persisted on disk for future re-use.
- // If authentication fails, OnAuthProblem is called on our Observer.
- // The Observer may, in turn, decide to try again with new
- // credentials. Calling this method again is the appropriate course of action
- // to "retry".
- // |username|, |password|, and |captcha| are owned by the caller.
- void Authenticate(const char* username, const char* password,
- const char* captcha);
+ // Migrate tokens from user settings DB to the token service.
+ void MigrateTokens();
+
+ // Update tokens that we're using in Sync. Email must stay the same.
+ void UpdateCredentials(const SyncCredentials& credentials);
// Start the SyncerThread.
void StartSyncing();
diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc
index a77134b..b83c501 100644
--- a/chrome/browser/sync/engine/syncapi_unittest.cc
+++ b/chrome/browser/sync/engine/syncapi_unittest.cc
@@ -25,7 +25,7 @@ class SyncApiTest : public testing::Test {
virtual void SetUp() {
setter_upper_.SetUp();
share_.dir_manager.reset(setter_upper_.manager());
- share_.authenticated_name = setter_upper_.name();
+ share_.name = setter_upper_.name();
}
virtual void TearDown() {
diff --git a/chrome/browser/sync/engine/syncer_proto_util.cc b/chrome/browser/sync/engine/syncer_proto_util.cc
index 17de218..2cc2300 100644
--- a/chrome/browser/sync/engine/syncer_proto_util.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util.cc
@@ -6,9 +6,9 @@
#include "base/format_macros.h"
#include "base/string_util.h"
-#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
+#include "chrome/browser/sync/engine/syncer_types.h"
#include "chrome/browser/sync/engine/syncer_util.h"
#include "chrome/browser/sync/protocol/service_constants.h"
#include "chrome/browser/sync/sessions/sync_session.h"
@@ -124,7 +124,7 @@ void SyncerProtoUtil::AddRequestBirthday(syncable::Directory* dir,
// static
bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
- AuthWatcher* auth_watcher,
+ sessions::SyncSession* session,
const ClientToServerMessage& msg,
ClientToServerResponse* response) {
@@ -144,12 +144,9 @@ bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
std::string new_token =
http_response.update_client_auth_header;
if (!new_token.empty()) {
- // We could also do this in the SCM's PostBufferWithAuth.
- // But then we could be in the middle of authentication, which seems
- // like a bad time to update the token. A consequence of this is that
- // we can't reset the cookie in response to auth attempts, but this
- // should be OK.
- auth_watcher->RenewAuthToken(new_token);
+ SyncerEvent event(SyncerEvent::UPDATED_TOKEN);
+ event.updated_token = new_token;
+ session->context()->syncer_event_channel()->Notify(event);
}
if (response->ParseFromString(rx)) {
@@ -189,7 +186,7 @@ bool SyncerProtoUtil::PostClientToServerMessage(
}
if (!PostAndProcessHeaders(session->context()->connection_manager(),
- session->context()->auth_watcher(),
+ session,
msg,
response)) {
return false;
diff --git a/chrome/browser/sync/engine/syncer_proto_util.h b/chrome/browser/sync/engine/syncer_proto_util.h
index 39fcc5c..ca68ec3 100644
--- a/chrome/browser/sync/engine/syncer_proto_util.h
+++ b/chrome/browser/sync/engine/syncer_proto_util.h
@@ -105,7 +105,7 @@ class SyncerProtoUtil {
// Post the message using the scm, and do some processing on the returned
// headers. Decode the server response.
static bool PostAndProcessHeaders(browser_sync::ServerConnectionManager* scm,
- browser_sync::AuthWatcher* authwatcher,
+ sessions::SyncSession* session,
const ClientToServerMessage& msg,
sync_pb::ClientToServerResponse* response);
diff --git a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
index e6eb68b..57cae0a 100644
--- a/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_proto_util_unittest.cc
@@ -182,7 +182,7 @@ TEST_F(SyncerProtoUtilTest, AddRequestBirthday) {
class DummyConnectionManager : public browser_sync::ServerConnectionManager {
public:
DummyConnectionManager()
- : ServerConnectionManager("unused", 0, false, "version", "id"),
+ : ServerConnectionManager("unused", 0, false, "version"),
send_error_(false),
access_denied_(false) {}
diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc
index 800ddddb..9f369ed8 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -17,12 +17,10 @@
#include "base/rand_util.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
#include "chrome/browser/sync/engine/net/server_connection_manager.h"
#include "chrome/browser/sync/engine/syncer.h"
#include "chrome/browser/sync/sessions/session_state.h"
-#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/common/chrome_switches.h"
#include "jingle/notifier/listener/notification_constants.h"
@@ -75,19 +73,12 @@ SyncerThread::SyncerThread(sessions::SyncSessionContext* context)
syncer_long_poll_interval_seconds_(kDefaultLongPollIntervalSeconds),
syncer_polling_interval_(kDefaultShortPollIntervalSeconds),
syncer_max_interval_(kDefaultMaxPollIntervalMs),
- directory_manager_hookup_(NULL),
syncer_events_(NULL),
session_context_(context),
disable_idle_detection_(false) {
DCHECK(context);
syncer_event_relay_channel_.reset(new SyncerEventChannel());
- if (context->directory_manager()) {
- directory_manager_hookup_.reset(NewEventListenerHookup(
- context->directory_manager()->channel(), this,
- &SyncerThread::HandleDirectoryManagerEvent));
- }
-
if (context->connection_manager())
WatchConnectionManager(context->connection_manager());
@@ -98,7 +89,6 @@ SyncerThread::~SyncerThread() {
syncer_event_relay_channel_->Notify(SyncerEvent(
SyncerEvent::SHUTDOWN_USE_WITH_CARE));
syncer_event_relay_channel_.reset();
- directory_manager_hookup_.reset();
syncer_events_.reset();
delete vault_.syncer_;
CHECK(!thread_.IsRunning());
@@ -587,22 +577,18 @@ void SyncerThread::HandleChannelEvent(const SyncerEvent& event) {
NudgeSyncImpl(event.nudge_delay_milliseconds, kUnknown);
}
-void SyncerThread::HandleDirectoryManagerEvent(
- const syncable::DirectoryManagerEvent& event) {
- LOG(INFO) << "Handling a directory manager event";
- if (syncable::DirectoryManagerEvent::OPENED == event.what_happened) {
- AutoLock lock(lock_);
- LOG(INFO) << "Syncer starting up for: " << event.dirname;
- // The underlying database structure is ready, and we should create
- // the syncer.
- CHECK(vault_.syncer_ == NULL);
- session_context_->set_account_name(event.dirname);
- vault_.syncer_ = new Syncer(session_context_.get());
-
- syncer_events_.reset(
- session_context_->syncer_event_channel()->AddObserver(this));
- vault_field_changed_.Broadcast();
- }
+void SyncerThread::CreateSyncer(const std::string& dirname) {
+ AutoLock lock(lock_);
+ LOG(INFO) << "Creating syncer up for: " << dirname;
+ // The underlying database structure is ready, and we should create
+ // the syncer.
+ CHECK(vault_.syncer_ == NULL);
+ session_context_->set_account_name(dirname);
+ vault_.syncer_ = new Syncer(session_context_.get());
+
+ syncer_events_.reset(
+ session_context_->syncer_event_channel()->AddObserver(this));
+ vault_field_changed_.Broadcast();
}
// Sets |*connected| to false if it is currently true but |code| suggests that
diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h
index 8c71db4..158d759 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -29,11 +29,6 @@
class EventListenerHookup;
-namespace syncable {
-class DirectoryManager;
-struct DirectoryManagerEvent;
-}
-
namespace browser_sync {
class ModelSafeWorker;
@@ -138,6 +133,9 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
virtual SyncerEventChannel* relay_channel();
+ // Call this when a directory is opened
+ void CreateSyncer(const std::string& dirname);
+
// DDOS avoidance function. The argument and return value is in seconds
static int GetRecommendedDelaySeconds(int base_delay_seconds);
@@ -230,8 +228,6 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
friend void* RunSyncerThread(void* syncer_thread);
void* Run();
- void HandleDirectoryManagerEvent(
- const syncable::DirectoryManagerEvent& event);
void HandleChannelEvent(const SyncerEvent& event);
// SyncSession::Delegate implementation.
@@ -323,7 +319,6 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>,
// this is called.
void NudgeSyncImpl(int milliseconds_from_now, NudgeSource source);
- scoped_ptr<EventListenerHookup> directory_manager_hookup_;
scoped_ptr<ChannelHookup<SyncerEvent> > syncer_events_;
#if defined(OS_LINUX)
diff --git a/chrome/browser/sync/engine/syncer_thread_unittest.cc b/chrome/browser/sync/engine/syncer_thread_unittest.cc
index 16328bd..ded07f0 100644
--- a/chrome/browser/sync/engine/syncer_thread_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_thread_unittest.cc
@@ -66,7 +66,7 @@ class SyncerThreadWithSyncerTest : public testing::Test,
metadb_.name()));
worker_ = new ModelSafeWorker();
SyncSessionContext* context = new SyncSessionContext(connection_.get(),
- NULL, metadb_.manager(), this);
+ metadb_.manager(), this);
syncer_thread_ = new SyncerThread(context);
syncer_event_hookup_.reset(
syncer_thread_->relay_channel()->AddObserver(this));
@@ -217,12 +217,12 @@ class SyncShareIntercept
};
TEST_F(SyncerThreadTest, Construction) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
}
TEST_F(SyncerThreadTest, StartStop) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
EXPECT_TRUE(syncer_thread->Start());
EXPECT_TRUE(syncer_thread->Stop(2000));
@@ -247,7 +247,7 @@ TEST(SyncerThread, GetRecommendedDelay) {
}
TEST_F(SyncerThreadTest, CalculateSyncWaitTime) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
syncer_thread->DisableIdleDetection();
@@ -307,7 +307,7 @@ TEST_F(SyncerThreadTest, CalculateSyncWaitTime) {
TEST_F(SyncerThreadTest, CalculatePollingWaitTime) {
// Set up the environment.
int user_idle_milliseconds_param = 0;
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
syncer_thread->DisableIdleDetection();
// Hold the lock to appease asserts in code.
@@ -639,8 +639,8 @@ TEST_F(SyncerThreadWithSyncerTest, Polling) {
syncer_thread()->SetSyncerShortPollInterval(poll_interval);
EXPECT_TRUE(syncer_thread()->Start());
- // Calling Open() should cause the SyncerThread to create a Syncer.
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
TimeDelta two_polls = poll_interval + poll_interval;
// We could theoretically return immediately from the wait if the interceptor
@@ -673,6 +673,7 @@ TEST_F(SyncerThreadWithSyncerTest, Nudge) {
PreventThreadFromPolling();
EXPECT_TRUE(syncer_thread()->Start());
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
const TimeDelta poll_interval = TimeDelta::FromMinutes(5);
interceptor.WaitForSyncShare(1, poll_interval + poll_interval);
@@ -697,6 +698,7 @@ TEST_F(SyncerThreadWithSyncerTest, Throttling) {
EXPECT_TRUE(syncer_thread()->Start());
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
// Wait for some healthy syncing.
interceptor.WaitForSyncShare(4, poll_interval + poll_interval);
@@ -750,6 +752,7 @@ TEST_F(SyncerThreadWithSyncerTest, StopSyncPermanently) {
EXPECT_TRUE(syncer_thread()->Start());
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
connection()->set_store_birthday("NotYourLuckyDay");
@@ -765,6 +768,7 @@ TEST_F(SyncerThreadWithSyncerTest, AuthInvalid) {
syncer_thread()->SetSyncerShortPollInterval(poll_interval);
EXPECT_TRUE(syncer_thread()->Start());
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
// Wait for some healthy syncing.
interceptor.WaitForSyncShare(2, TimeDelta::FromSeconds(10));
@@ -826,6 +830,7 @@ TEST_F(SyncerThreadWithSyncerTest, FLAKY_Pause) {
Field(&SyncerEvent::what_happened, SyncerEvent::SYNCER_THREAD_EXITING)));
ASSERT_TRUE(syncer_thread()->Start());
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
// Request a pause.
@@ -869,6 +874,7 @@ TEST_F(SyncerThreadWithSyncerTest, StartWhenNotConnected) {
connection()->SetServerNotReachable();
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
// Syncer thread will always go through once cycle at the start,
// then it will wait for a connection.
@@ -923,6 +929,8 @@ TEST_F(SyncerThreadWithSyncerTest, DISABLED_PauseWhenNotConnected) {
Field(&SyncerEvent::what_happened, SyncerEvent::WAITING_FOR_CONNECTION))).
WillOnce(SignalEvent(&event));
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
+
ASSERT_TRUE(syncer_thread()->Start());
ASSERT_TRUE(sync_cycle_ended_event.TimedWait(max_wait_time_));
ASSERT_TRUE(event.TimedWait(max_wait_time_));
@@ -994,6 +1002,7 @@ TEST_F(SyncerThreadWithSyncerTest, PauseResumeWhenNotRunning) {
// Pause the thread then start the syncer.
ASSERT_TRUE(Pause(&listener));
metadb()->Open();
+ syncer_thread()->CreateSyncer(metadb()->name());
ASSERT_TRUE(syncer_thread()->Start());
// Resume and let the syncer cycle.
diff --git a/chrome/browser/sync/engine/syncer_types.h b/chrome/browser/sync/engine/syncer_types.h
index 19be54e..0805c89 100644
--- a/chrome/browser/sync/engine/syncer_types.h
+++ b/chrome/browser/sync/engine/syncer_types.h
@@ -78,6 +78,8 @@ struct SyncerEvent {
STATUS_CHANGED,
+ UPDATED_TOKEN, // new token in updated_token
+
// Take care not to wait in shutdown handlers for the syncer to stop as it
// causes a race in the event system. Use SyncerShutdownEvent instead.
SHUTDOWN_USE_WITH_CARE,
@@ -143,6 +145,9 @@ struct SyncerEvent {
// How many milliseconds later should the syncer kick in? For
// REQUEST_SYNC_NUDGE only.
int nudge_delay_milliseconds;
+
+ // Update-Client-Auth returns a new token for sync use.
+ std::string updated_token;
};
struct SyncerShutdownEvent {
diff --git a/chrome/browser/sync/engine/syncer_unittest.cc b/chrome/browser/sync/engine/syncer_unittest.cc
index 0d9ab8e..74e5122 100644
--- a/chrome/browser/sync/engine/syncer_unittest.cc
+++ b/chrome/browser/sync/engine/syncer_unittest.cc
@@ -168,7 +168,7 @@ class SyncerTest : public testing::Test,
new MockConnectionManager(syncdb_.manager(), syncdb_.name()));
EnableDatatype(syncable::BOOKMARKS);
worker_ = new ModelSafeWorker();
- context_.reset(new SyncSessionContext(mock_server_.get(), NULL,
+ context_.reset(new SyncSessionContext(mock_server_.get(),
syncdb_.manager(), this));
context_->set_account_name(syncdb_.name());
ASSERT_FALSE(context_->syncer_event_channel());
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index b570c4f..c4e0963 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -10,6 +10,7 @@
#include "base/task.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/sync/engine/syncapi.h"
@@ -21,24 +22,25 @@
#include "chrome/browser/sync/glue/password_model_worker.h"
#include "chrome/browser/sync/sessions/session_state.h"
#include "chrome/common/chrome_version_info.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/webkit_glue.h"
static const int kSaveChangesIntervalSeconds = 10;
-static const char kGaiaServiceId[] = "chromiumsync";
-static const char kGaiaSourceForChrome[] = "ChromiumBrowser";
static const FilePath::CharType kSyncDataFolderName[] =
FILE_PATH_LITERAL("Sync Data");
using browser_sync::DataTypeController;
+typedef TokenService::TokenAvailableDetails TokenAvailableDetails;
typedef GoogleServiceAuthError AuthError;
namespace browser_sync {
using sessions::SyncSessionSnapshot;
+using sync_api::SyncCredentials;
SyncBackendHost::SyncBackendHost(
SyncFrontend* frontend,
@@ -75,10 +77,8 @@ void SyncBackendHost::Initialize(
const GURL& sync_service_url,
const syncable::ModelTypeSet& types,
URLRequestContextGetter* baseline_context_getter,
- const std::string& lsid,
+ const SyncCredentials& credentials,
bool delete_sync_data_folder,
- bool invalidate_sync_login,
- bool invalidate_sync_xmpp_login,
bool use_chrome_async_socket,
bool try_ssltcp_first,
NotificationMethod notification_method) {
@@ -110,13 +110,10 @@ void SyncBackendHost::Initialize(
}
InitCore(Core::DoInitializeOptions(
- sync_service_url, lsid.empty(),
+ sync_service_url,
MakeHttpBridgeFactory(baseline_context_getter),
- MakeHttpBridgeFactory(baseline_context_getter),
- lsid,
+ credentials,
delete_sync_data_folder,
- invalidate_sync_login,
- invalidate_sync_xmpp_login,
use_chrome_async_socket,
try_ssltcp_first,
notification_method,
@@ -148,12 +145,11 @@ void SyncBackendHost::InitCore(const Core::DoInitializeOptions& options) {
options));
}
-void SyncBackendHost::Authenticate(const std::string& username,
- const std::string& password,
- const std::string& captcha) {
+void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) {
core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoAuthenticate,
- username, password, captcha));
+ NewRunnableMethod(core_.get(),
+ &SyncBackendHost::Core::DoUpdateCredentials,
+ credentials));
}
void SyncBackendHost::StartSyncingWithServer() {
@@ -344,6 +340,15 @@ void SyncBackendHost::Core::NotifyPassphraseAccepted(
NotificationService::NoDetails());
}
+void SyncBackendHost::Core::NotifyUpdatedToken(const std::string& token) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ TokenAvailableDetails details(GaiaConstants::kSyncService, token);
+ NotificationService::current()->Notify(
+ NotificationType::TOKEN_UPDATED,
+ NotificationService::AllSources(),
+ Details<const TokenAvailableDetails>(&details));
+}
+
SyncBackendHost::UserShareHandle SyncBackendHost::GetUserShareHandle() const {
DCHECK(syncapi_initialized_);
return core_->syncapi()->GetUserShare();
@@ -432,8 +437,9 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
// Blow away the partial or corrupt sync data folder before doing any more
// initialization, if necessary.
- if (options.delete_sync_data_folder)
+ if (options.delete_sync_data_folder) {
DeleteSyncDataFolder();
+ }
// Make sure that the directory exists before initializing the backend.
// If it already exists, this will do no harm.
@@ -445,17 +451,11 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
success = syncapi_->Init(path_str,
(options.service_url.host() + options.service_url.path()).c_str(),
options.service_url.EffectiveIntPort(),
- kGaiaServiceId,
- kGaiaSourceForChrome,
options.service_url.SchemeIsSecure(),
options.http_bridge_factory,
- options.auth_http_bridge_factory,
host_, // ModelSafeWorkerRegistrar.
- options.attempt_last_user_authentication,
- options.invalidate_sync_login,
- options.invalidate_sync_xmpp_login,
MakeUserAgentForSyncapi().c_str(),
- options.lsid.c_str(),
+ options.credentials,
options.use_chrome_async_socket,
options.try_ssltcp_first,
options.notification_method,
@@ -463,11 +463,10 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
DCHECK(success) << "Syncapi initialization failed!";
}
-void SyncBackendHost::Core::DoAuthenticate(const std::string& username,
- const std::string& password,
- const std::string& captcha) {
+void SyncBackendHost::Core::DoUpdateCredentials(
+ const SyncCredentials& credentials) {
DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
- syncapi_->Authenticate(username.c_str(), password.c_str(), captcha.c_str());
+ syncapi_->UpdateCredentials(credentials);
}
void SyncBackendHost::Core::DoStartSyncing() {
@@ -624,8 +623,7 @@ bool SyncBackendHost::Core::IsCurrentThreadSafeForModel(
void SyncBackendHost::Core::OnAuthError(const AuthError& auth_error) {
- // We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
- // we can modify state.
+ // Post to our core loop so we can modify state. Could be on another thread.
host_->frontend_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &Core::HandleAuthErrorEventOnFrontendLoop,
auth_error));
@@ -660,6 +658,11 @@ void SyncBackendHost::Core::OnStopSyncingPermanently() {
&Core::HandleStopSyncingPermanentlyOnFrontendLoop));
}
+void SyncBackendHost::Core::OnUpdatedToken(const std::string& token) {
+ host_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &Core::NotifyUpdatedToken, token));
+}
+
void SyncBackendHost::Core::HandleStopSyncingPermanentlyOnFrontendLoop() {
if (!host_ || !host_->frontend_)
return;
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 2b8680d..9e0a9f1 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -16,6 +16,7 @@
#include "base/ref_counted.h"
#include "base/thread.h"
#include "base/timer.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/sync/notification_method.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
@@ -101,17 +102,14 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
void Initialize(const GURL& service_url,
const syncable::ModelTypeSet& types,
URLRequestContextGetter* baseline_context_getter,
- const std::string& lsid,
+ const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder,
- bool invalidate_sync_login,
- bool invalidate_sync_xmpp_login,
bool use_chrome_async_socket,
bool try_ssltcp_first,
NotificationMethod notification_method);
- // Called on |frontend_loop_| to kick off asynchronous authentication.
- void Authenticate(const std::string& username, const std::string& password,
- const std::string& captcha);
+ // Called from |frontend_loop| to update SyncCredentials.
+ void UpdateCredentials(const sync_api::SyncCredentials& credentials);
// This starts the SyncerThread running a Syncer object to communicate with
// sync servers. Until this is called, no changes will leave or enter this
@@ -208,29 +206,22 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
virtual void OnPaused();
virtual void OnResumed();
virtual void OnStopSyncingPermanently();
+ virtual void OnUpdatedToken(const std::string& token);
struct DoInitializeOptions {
DoInitializeOptions(
const GURL& service_url,
- bool attempt_last_user_authentication,
sync_api::HttpPostProviderFactory* http_bridge_factory,
- sync_api::HttpPostProviderFactory* auth_http_bridge_factory,
- const std::string& lsid,
+ const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder,
- bool invalidate_sync_login,
- bool invalidate_sync_xmpp_login,
bool use_chrome_async_socket,
bool try_ssltcp_first,
NotificationMethod notification_method,
std::string restored_key_for_bootstrapping)
: service_url(service_url),
- attempt_last_user_authentication(attempt_last_user_authentication),
http_bridge_factory(http_bridge_factory),
- auth_http_bridge_factory(auth_http_bridge_factory),
- lsid(lsid),
+ credentials(credentials),
delete_sync_data_folder(delete_sync_data_folder),
- invalidate_sync_login(invalidate_sync_login),
- invalidate_sync_xmpp_login(invalidate_sync_xmpp_login),
use_chrome_async_socket(use_chrome_async_socket),
try_ssltcp_first(try_ssltcp_first),
notification_method(notification_method),
@@ -239,7 +230,7 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
GURL service_url;
bool attempt_last_user_authentication;
sync_api::HttpPostProviderFactory* http_bridge_factory;
- sync_api::HttpPostProviderFactory* auth_http_bridge_factory;
+ sync_api::SyncCredentials credentials;
std::string lsid;
bool delete_sync_data_folder;
bool invalidate_sync_login;
@@ -260,11 +251,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// of the syncapi on behalf of SyncBackendHost::Initialize.
void DoInitialize(const DoInitializeOptions& options);
- // Called on our SyncBackendHost's core_thread_ to perform authentication
- // on behalf of SyncBackendHost::Authenticate.
- void DoAuthenticate(const std::string& username,
- const std::string& password,
- const std::string& captcha);
+ // Called on our SyncBackendHost's core_thread_ to perform credential
+ // update on behalf of SyncBackendHost::UpdateCredentials
+ void DoUpdateCredentials(const sync_api::SyncCredentials& credentials);
// Called on the SyncBackendHost core_thread_ to tell the syncapi to start
// syncing (generally after initialization and authentication).
@@ -308,14 +297,17 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// setup to nudge the syncapi into a useable state.
void DoInitializeForTest(const std::wstring& test_user,
sync_api::HttpPostProviderFactory* factory,
- sync_api::HttpPostProviderFactory* auth_factory,
bool delete_sync_data_folder,
NotificationMethod notification_method) {
- DoInitialize(DoInitializeOptions(GURL(), false, factory, auth_factory,
- std::string(), delete_sync_data_folder,
- false, false, false, false,
- notification_method, ""));
- syncapi_->SetupForTestMode(test_user);
+ // Construct dummy credentials for test.
+ sync_api::SyncCredentials credentials;
+ credentials.email = WideToUTF8(test_user);
+ credentials.sync_token = "token";
+ DoInitialize(DoInitializeOptions(GURL(), factory,
+ credentials,
+ delete_sync_data_folder, false, false,
+ notification_method, std::string()));
+ syncapi_->SetupForTestMode(test_user);
}
#endif
@@ -358,6 +350,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// Invoked when the passphrase provided by the user has been accepted.
void NotifyPassphraseAccepted(const std::string& bootstrap_token);
+ // Invoked when an updated token is available from the sync server.
+ void NotifyUpdatedToken(const std::string& token);
+
// Called from Core::OnSyncCycleCompleted to handle updating frontend
// thread components.
void HandleSyncCycleCompletedOnFrontendLoop(
@@ -372,6 +367,9 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
// Return true if a model lives on the current thread.
bool IsCurrentThreadSafeForModel(syncable::ModelType model_type);
+ // True if credentials are ready for sync use.
+ bool CredentialsAvailable();
+
// Our parent SyncBackendHost
SyncBackendHost* host_;
diff --git a/chrome/browser/sync/profile_sync_factory.h b/chrome/browser/sync/profile_sync_factory.h
index 1ca0473..a4a2550 100644
--- a/chrome/browser/sync/profile_sync_factory.h
+++ b/chrome/browser/sync/profile_sync_factory.h
@@ -6,7 +6,9 @@
#define CHROME_BROWSER_SYNC_PROFILE_SYNC_FACTORY_H__
#pragma once
+#include <string>
#include <utility>
+
#include "base/task.h"
#include "chrome/browser/sync/glue/change_processor.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
@@ -48,7 +50,8 @@ class ProfileSyncFactory {
// Instantiates and initializes a new ProfileSyncService. Enabled
// data types are registered with the service. The return pointer
// is owned by the caller.
- virtual ProfileSyncService* CreateProfileSyncService() = 0;
+ virtual ProfileSyncService* CreateProfileSyncService(
+ const std::string& cros_user) = 0;
// Instantiates a new DataTypeManager with a SyncBackendHost and a
// list of data type controllers. The return pointer is owned by
diff --git a/chrome/browser/sync/profile_sync_factory_impl.cc b/chrome/browser/sync/profile_sync_factory_impl.cc
index a5df306..d6708cd 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -76,9 +76,11 @@ ProfileSyncFactoryImpl::ProfileSyncFactoryImpl(Profile* profile,
command_line_(command_line) {
}
-ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService() {
+ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService(
+ const std::string& cros_user) {
+
ProfileSyncService* pss = new ProfileSyncService(
- this, profile_, browser_defaults::kBootstrapSyncAuthentication);
+ this, profile_, cros_user);
// App sync is enabled by default. Register unless explicitly
// disabled.
diff --git a/chrome/browser/sync/profile_sync_factory_impl.h b/chrome/browser/sync/profile_sync_factory_impl.h
index ce535e5..233f3f1 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_factory_impl.h
@@ -6,6 +6,8 @@
#define CHROME_BROWSER_SYNC_PROFILE_SYNC_FACTORY_IMPL_H__
#pragma once
+#include <string>
+
#include "base/basictypes.h"
#include "chrome/browser/sync/profile_sync_factory.h"
@@ -18,7 +20,8 @@ class ProfileSyncFactoryImpl : public ProfileSyncFactory {
virtual ~ProfileSyncFactoryImpl() {}
// ProfileSyncFactory interface.
- virtual ProfileSyncService* CreateProfileSyncService();
+ virtual ProfileSyncService* CreateProfileSyncService(
+ const std::string& cros_user);
virtual browser_sync::DataTypeManager* CreateDataTypeManager(
browser_sync::SyncBackendHost* backend,
diff --git a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
index 908ccae..26f47d1 100644
--- a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
@@ -39,7 +39,7 @@ class ProfileSyncFactoryImplTest : public testing::Test {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDefault) {
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -55,7 +55,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDefault) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableAutofill) {
command_line_->AppendSwitch(switches::kDisableSyncAutofill);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -71,7 +71,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableAutofill) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableBookmarks) {
command_line_->AppendSwitch(switches::kDisableSyncBookmarks);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -87,7 +87,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableBookmarks) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisablePreferences) {
command_line_->AppendSwitch(switches::kDisableSyncPreferences);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -103,7 +103,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisablePreferences) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableThemes) {
command_line_->AppendSwitch(switches::kDisableSyncThemes);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -119,7 +119,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableThemes) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableExtensions) {
command_line_->AppendSwitch(switches::kDisableSyncExtensions);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
@@ -135,7 +135,7 @@ TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableExtensions) {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDisableApps) {
command_line_->AppendSwitch(switches::kDisableSyncApps);
scoped_ptr<ProfileSyncService> pss;
- pss.reset(profile_sync_service_factory_->CreateProfileSyncService());
+ pss.reset(profile_sync_service_factory_->CreateProfileSyncService(""));
DataTypeController::StateMap controller_states;
DataTypeController::StateMap* controller_states_ptr = &controller_states;
pss->GetDataTypeControllerStates(controller_states_ptr);
diff --git a/chrome/browser/sync/profile_sync_factory_mock.h b/chrome/browser/sync/profile_sync_factory_mock.h
index 6c14d1e..18cc30c 100644
--- a/chrome/browser/sync/profile_sync_factory_mock.h
+++ b/chrome/browser/sync/profile_sync_factory_mock.h
@@ -23,8 +23,8 @@ class ProfileSyncFactoryMock : public ProfileSyncFactory {
browser_sync::AssociatorInterface* bookmark_model_associator,
browser_sync::ChangeProcessor* bookmark_change_processor);
- MOCK_METHOD0(CreateProfileSyncService,
- ProfileSyncService*(void));
+ MOCK_METHOD1(CreateProfileSyncService,
+ ProfileSyncService*(const std::string&));
MOCK_METHOD2(CreateDataTypeManager,
browser_sync::DataTypeManager*(
browser_sync::SyncBackendHost*,
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 5732ebf..567631d 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -30,7 +30,10 @@
#include "chrome/browser/sync/glue/session_data_type_controller.h"
#include "chrome/browser/sync/profile_sync_factory.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/token_migrator.h"
+#include "chrome/browser/sync/util/user_settings.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_source.h"
@@ -44,6 +47,7 @@ using browser_sync::ChangeProcessor;
using browser_sync::DataTypeController;
using browser_sync::DataTypeManager;
using browser_sync::SyncBackendHost;
+using sync_api::SyncCredentials;
typedef GoogleServiceAuthError AuthError;
@@ -55,20 +59,20 @@ const char* ProfileSyncService::kDevServerUrl =
ProfileSyncService::ProfileSyncService(ProfileSyncFactory* factory,
Profile* profile,
- bool bootstrap_sync_authentication)
+ const std::string& cros_user)
: last_auth_error_(AuthError::None()),
factory_(factory),
profile_(profile),
- bootstrap_sync_authentication_(bootstrap_sync_authentication),
+ cros_user_(cros_user),
sync_service_url_(kDevServerUrl),
backend_initialized_(false),
- expecting_first_run_auth_needed_event_(false),
is_auth_in_progress_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)),
unrecoverable_error_detected_(false),
use_chrome_async_socket_(false),
notification_method_(browser_sync::kDefaultNotificationMethod),
- ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)),
+ token_migrator_(NULL) {
DCHECK(factory);
DCHECK(profile);
registrar_.Add(this,
@@ -109,10 +113,8 @@ ProfileSyncService::ProfileSyncService()
: last_auth_error_(AuthError::None()),
factory_(NULL),
profile_(NULL),
- bootstrap_sync_authentication_(false),
sync_service_url_(kSyncServerUrl),
backend_initialized_(false),
- expecting_first_run_auth_needed_event_(false),
is_auth_in_progress_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)),
unrecoverable_error_detected_(false),
@@ -126,6 +128,37 @@ ProfileSyncService::~ProfileSyncService() {
Shutdown(false);
}
+bool ProfileSyncService::AreCredentialsAvailable() {
+ if (IsManaged()) {
+ return false;
+ }
+
+ if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) {
+ return false;
+ }
+
+ // CrOS user is always logged in. Chrome uses signin_ to check logged in.
+ if (!cros_user_.empty() || !signin_.GetUsername().empty()) {
+ // TODO(chron): Verify CrOS unit test behavior.
+ if (profile()->GetTokenService() &&
+ profile()->GetTokenService()->HasTokenForService(
+ GaiaConstants::kSyncService)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void ProfileSyncService::LoadMigratedCredentials(const std::string& username,
+ const std::string& token) {
+ signin_.SetUsername(username);
+ profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username);
+ profile()->GetTokenService()->OnIssueAuthTokenSuccess(
+ GaiaConstants::kSyncService, token);
+ profile()->GetPrefs()->SetBoolean(prefs::kSyncCredentialsMigrated, true);
+ token_migrator_.reset();
+}
+
void ProfileSyncService::Initialize() {
LOG(INFO) << "Starting ProfileSyncService.";
InitSettings();
@@ -141,24 +174,49 @@ void ProfileSyncService::Initialize() {
return;
}
- if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
- DisableForUser(); // Clean up in case of previous crash / setup abort.
+ RegisterAuthNotifications();
- // Automatically start sync in Chromium OS.
- if (bootstrap_sync_authentication_ &&
- !profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) {
- // If the LSID is empty, we're in a CrOS UI test that is not testing sync
- // behavior, so we don't want the sync service to start.
- if (profile()->GetTokenService() &&
- !profile()->GetTokenService()->HasLsid()) {
- LOG(WARNING) << "Skipping CrOS sync startup, no LSID present.";
- return;
- }
- StartUp();
+ // In Chrome, we integrate a SigninManager which works with the sync
+ // setup wizard to kick off the TokenService. CrOS does its own plumbing
+ // for the TokenService.
+ if (cros_user_.empty()) {
+ // Will load tokens from DB and broadcast Token events after.
+ signin_.Initialize(profile_);
+ }
+
+ if (!HasSyncSetupCompleted()) {
+ DisableForUser(); // Clean up in case of previous crash / setup abort.
+ if (!cros_user_.empty() && AreCredentialsAvailable()) {
+ StartUp(); // Under ChromeOS, just autostart it anyway if creds are here.
}
- } else {
+ } else if (AreCredentialsAvailable()) {
+ // If we have credentials and sync setup finished, autostart the backend.
+ // Note that if we haven't finished setting up sync, backend bring up will
+ // be done by the wizard.
StartUp();
+ } else {
+ // Try to migrate the tokens (if that hasn't already succeeded).
+ if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncCredentialsMigrated)) {
+ token_migrator_.reset(new TokenMigrator(this, profile_->GetPath()));
+ token_migrator_->TryMigration();
+ }
}
+
+}
+
+void ProfileSyncService::RegisterAuthNotifications() {
+ registrar_.Add(this,
+ NotificationType::TOKEN_AVAILABLE,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::TOKEN_LOADING_FINISHED,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::GOOGLE_SIGNIN_FAILED,
+ NotificationService::AllSources());
}
void ProfileSyncService::RegisterDataTypeController(
@@ -232,6 +290,7 @@ void ProfileSyncService::RegisterPreferences() {
pref_service->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0);
pref_service->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, false);
pref_service->RegisterBooleanPref(prefs::kSyncSuppressStart, false);
+ pref_service->RegisterBooleanPref(prefs::kSyncCredentialsMigrated, false);
// If you've never synced before, or if you're using Chrome OS, all datatypes
// are on by default.
@@ -269,23 +328,29 @@ void ProfileSyncService::ClearPreferences() {
pref_service->ScheduleSavePersistentPrefs();
}
+SyncCredentials ProfileSyncService::GetCredentials() {
+ SyncCredentials credentials;
+ credentials.email = !cros_user_.empty() ? cros_user_ : signin_.GetUsername();
+ DCHECK(!credentials.email.empty());
+ TokenService* service = profile_->GetTokenService();
+ credentials.sync_token = service->GetTokenForService(
+ GaiaConstants::kSyncService);
+ return credentials;
+}
+
void ProfileSyncService::InitializeBackend(bool delete_sync_data_folder) {
if (!backend_.get()) {
NOTREACHED();
return;
}
- // TODO(akalin): Gather all the command-line-controlled switches
- // into an Options struct to make passing them down less annoying.
+ // TODO(chron): Reimplement invalidate XMPP login / Sync login
+ // command line switches. Perhaps make it a command
+ // line in the TokenService itself to pass an arbitrary
+ // token.
- bool invalidate_sync_login = false;
- bool invalidate_sync_xmpp_login = false;
bool try_ssltcp_first = false;
#if !defined(NDEBUG)
- invalidate_sync_login = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kInvalidateSyncLogin);
- invalidate_sync_xmpp_login = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kInvalidateSyncXmppLogin);
try_ssltcp_first = CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSyncUseSslTcp);
#endif
@@ -294,15 +359,17 @@ void ProfileSyncService::InitializeBackend(bool delete_sync_data_folder) {
// If sync setup hasn't finished, we don't want to initialize routing info
// for any data types so that we don't download updates for types that the
// user chooses not to sync on the first DownloadUpdatesCommand.
- if (HasSyncSetupCompleted())
+ if (HasSyncSetupCompleted()) {
GetPreferredDataTypes(&types);
+ }
+
+ SyncCredentials credentials = GetCredentials();
+
backend_->Initialize(sync_service_url_,
types,
profile_->GetRequestContext(),
- profile_->GetTokenService()->GetLsid(),
+ credentials,
delete_sync_data_folder,
- invalidate_sync_login,
- invalidate_sync_xmpp_login,
use_chrome_async_socket_,
try_ssltcp_first,
notification_method_);
@@ -321,7 +388,9 @@ void ProfileSyncService::StartUp() {
return;
}
- LOG(INFO) << "ProfileSyncSerivce bringing up backend host.";
+ DCHECK(AreCredentialsAvailable());
+
+ LOG(INFO) << "ProfileSyncService bringing up backend host.";
last_synced_time_ = base::Time::FromInternalValue(
profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
@@ -355,31 +424,21 @@ void ProfileSyncService::Shutdown(bool sync_disabled) {
// Clear various flags.
is_auth_in_progress_ = false;
backend_initialized_ = false;
- expecting_first_run_auth_needed_event_ = false;
last_attempted_user_email_.clear();
}
-void ProfileSyncService::EnableForUser(gfx::NativeWindow parent_window) {
- if (WizardIsVisible()) {
- wizard_.Focus();
- return;
- }
- expecting_first_run_auth_needed_event_ = true;
- DCHECK(!data_type_manager_.get());
-
- wizard_.SetParent(parent_window);
- StartUp();
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
-}
-
void ProfileSyncService::DisableForUser() {
- LOG(INFO) << "Clearing Sync DB.";
+ LOG(INFO) << "Disabling sync for user.";
- // Clear prefs (including SyncSetupHasCompleted) before shutting down so
+ // Clear prefs (including SyncSetupHasCompleted) before shutting down so
// PSS clients don't think we're set up while we're shutting down.
ClearPreferences();
Shutdown(true);
+ if (cros_user_.empty()) {
+ signin_.SignOut();
+ }
+
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
}
@@ -441,29 +500,20 @@ void ProfileSyncService::OnUnrecoverableError(
from_here.file_name(),
from_here.line_number()));
- // Shut all data types down.
- if (data_type_manager_.get())
- data_type_manager_->Stop();
-
// Tell the wizard so it can inform the user only if it is already open.
wizard_.Step(SyncSetupWizard::FATAL_ERROR);
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
- LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable.";
+ LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable."
+ << message;
std::string location;
from_here.Write(true, true, &location);
LOG(ERROR) << location;
- if (SetupInProgress()) {
- // We've hit an error in the middle of a startup process- shutdown all the
- // backend stuff, and then restart it, so we're in the same state as before.
- MessageLoop::current()->PostTask(FROM_HERE,
+ // Shut all data types down.
+ MessageLoop::current()->PostTask(FROM_HERE,
scoped_runnable_method_factory_.NewRunnableMethod(
&ProfileSyncService::Shutdown, true));
- MessageLoop::current()->PostTask(FROM_HERE,
- scoped_runnable_method_factory_.NewRunnableMethod(
- &ProfileSyncService::StartUp));
- }
}
void ProfileSyncService::OnBackendInitialized() {
@@ -472,11 +522,12 @@ void ProfileSyncService::OnBackendInitialized() {
// The very first time the backend initializes is effectively the first time
// we can say we successfully "synced". last_synced_time_ will only be null
// in this case, because the pref wasn't restored on StartUp.
- if (last_synced_time_.is_null())
+ if (last_synced_time_.is_null()) {
UpdateLastSyncedTime();
+ }
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
- if (bootstrap_sync_authentication_) {
+ if (!cros_user_.empty()) {
if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) {
ShowChooseDataTypes(NULL);
} else {
@@ -484,8 +535,9 @@ void ProfileSyncService::OnBackendInitialized() {
}
}
- if (HasSyncSetupCompleted())
+ if (HasSyncSetupCompleted()) {
ConfigureDataTypeManager();
+ }
}
void ProfileSyncService::OnSyncCycleCompleted() {
@@ -493,22 +545,16 @@ void ProfileSyncService::OnSyncCycleCompleted() {
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
}
-void ProfileSyncService::OnAuthError() {
- last_auth_error_ = backend_->GetAuthError();
+void ProfileSyncService::UpdateAuthErrorState(
+ const GoogleServiceAuthError& error) {
+ last_auth_error_ = error;
// Protect against the in-your-face dialogs that pop out of nowhere.
// Require the user to click somewhere to run the setup wizard in the case
// of a steady-state auth failure.
- if (WizardIsVisible() || expecting_first_run_auth_needed_event_) {
+ if (WizardIsVisible()) {
wizard_.Step(AuthError::NONE == last_auth_error_.state() ?
SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GAIA_LOGIN);
- }
-
- if (expecting_first_run_auth_needed_event_) {
- last_auth_error_ = AuthError::None();
- expecting_first_run_auth_needed_event_ = false;
- }
-
- if (!WizardIsVisible()) {
+ } else {
auth_error_time_ == base::TimeTicks::Now();
}
@@ -523,6 +569,10 @@ void ProfileSyncService::OnAuthError() {
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
}
+void ProfileSyncService::OnAuthError() {
+ UpdateAuthErrorState(backend_->GetAuthError());
+ }
+
void ProfileSyncService::OnStopSyncingPermanently() {
if (SetupInProgress()) {
wizard_.Step(SyncSetupWizard::SETUP_ABORTED_BY_PENDING_CLEAR);
@@ -533,6 +583,12 @@ void ProfileSyncService::OnStopSyncingPermanently() {
}
void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) {
+ // TODO(johnnyg): File a bug to make sure this doesn't happen.
+ if (!cros_user_.empty()) {
+ LOG(WARNING) << "ShowLoginDialog called on Chrome OS.";
+ return;
+ }
+
if (WizardIsVisible()) {
wizard_.Focus();
return;
@@ -544,10 +600,10 @@ void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) {
auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null.
}
- if (last_auth_error_.state() != AuthError::NONE) {
- wizard_.SetParent(parent_window);
- wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
- }
+ wizard_.SetParent(parent_window);
+ wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
+
+ FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
}
void ProfileSyncService::ShowChooseDataTypes(gfx::NativeWindow parent_window) {
@@ -623,16 +679,26 @@ string16 ProfileSyncService::GetAuthenticatedUsername() const {
void ProfileSyncService::OnUserSubmittedAuth(
const std::string& username, const std::string& password,
const std::string& captcha) {
- if (!backend_.get()) {
- NOTREACHED();
- return;
- }
last_attempted_user_email_ = username;
is_auth_in_progress_ = true;
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
auth_start_time_ = base::TimeTicks::Now();
- backend_->Authenticate(username, password, captcha);
+
+ // TODO(chron): Mechanism for ChromeOS auth renewal?
+ // (maybe just run the dialog anyway?)
+ // or send it to the CrOS login somehow?
+ if (!cros_user_.empty()) {
+ LOG(WARNING) << "No mechanism on ChromeOS yet. See http://crbug.com/50292";
+ }
+
+ if (!signin_.GetUsername().empty()) {
+ signin_.SignOut();
+ }
+ signin_.StartSignIn(username,
+ password,
+ last_auth_error_.captcha().token,
+ captcha);
}
void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything,
@@ -649,7 +715,7 @@ void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything,
}
void ProfileSyncService::OnUserCancelledDialog() {
- if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
+ if (!HasSyncSetupCompleted()) {
// A sync dialog was aborted before authentication.
// Rollback.
expect_sync_configuration_aborted_ = true;
@@ -815,10 +881,43 @@ void ProfileSyncService::Observe(NotificationType type,
std::string* pref_name = Details<std::string>(details).ptr();
if (*pref_name == prefs::kSyncManaged) {
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
- if (*pref_sync_managed_)
+ if (*pref_sync_managed_) {
DisableForUser();
- else if (HasSyncSetupCompleted())
+ } else if (HasSyncSetupCompleted() && AreCredentialsAvailable()) {
StartUp();
+ }
+ }
+ break;
+ }
+ case NotificationType::GOOGLE_SIGNIN_SUCCESSFUL: {
+ LOG(INFO) << "Signin OK. Waiting on tokens.";
+ // TODO(chron): UI update?
+ // TODO(chron): Timeout?
+ break;
+ }
+ case NotificationType::GOOGLE_SIGNIN_FAILED: {
+ GoogleServiceAuthError error =
+ *(Details<GoogleServiceAuthError>(details).ptr());
+ UpdateAuthErrorState(error);
+ break;
+ }
+ case NotificationType::TOKEN_AVAILABLE: {
+ if (AreCredentialsAvailable()) {
+ if (backend_initialized_) {
+ backend_->UpdateCredentials(GetCredentials());
+ }
+
+ StartUp();
+ }
+ break;
+ }
+ case NotificationType::TOKEN_LOADING_FINISHED: {
+ // If not in Chrome OS, and we have a username without tokens,
+ // the user will need to signin again, so sign out.
+ if (cros_user_.empty() &&
+ !signin_.GetUsername().empty() &&
+ !AreCredentialsAvailable()) {
+ DisableForUser();
}
break;
}
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index c0f023f..efa2cb2 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -15,12 +15,14 @@
#include "base/string16.h"
#include "base/time.h"
#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/data_type_manager.h"
#include "chrome/browser/sync/glue/session_model_associator.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "chrome/browser/sync/notification_method.h"
#include "chrome/browser/sync/profile_sync_service_observer.h"
+#include "chrome/browser/sync/signin_manager.h"
#include "chrome/browser/sync/sync_setup_wizard.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/unrecoverable_error_handler.h"
@@ -34,6 +36,7 @@ class NotificationSource;
class NotificationType;
class Profile;
class ProfileSyncFactory;
+class TokenMigrator;
// ProfileSyncService is the layer between browser subsystems like bookmarks,
// and the sync backend. Each subsystem is logically thought of as being
@@ -114,13 +117,23 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
ProfileSyncService(ProfileSyncFactory* factory_,
Profile* profile,
- bool bootstrap_sync_authentication);
+ const std::string& cros_user);
virtual ~ProfileSyncService();
// Initializes the object. This should be called every time an object of this
// class is constructed.
void Initialize();
+ void RegisterAuthNotifications();
+
+ // Return whether all sync tokens are loaded and
+ // available for the backend to start up.
+ bool AreCredentialsAvailable();
+
+ // Loads credentials migrated from the old user settings db.
+ void LoadMigratedCredentials(const std::string& username,
+ const std::string& token);
+
// Registers a data type controller with the sync service. This
// makes the data type controller available for use, it does not
// enable or activate the synchronization of the data type (see
@@ -138,8 +151,7 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
void GetDataTypeControllerStates(
browser_sync::DataTypeController::StateMap* state_map) const;
- // Enables/disables sync for user.
- virtual void EnableForUser(gfx::NativeWindow parent_window);
+ // Disables sync for user. Use ShowLoginDialog to enable.
virtual void DisableForUser();
// Whether sync is enabled by user or not.
@@ -157,6 +169,9 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
const std::string& password,
const std::string& captcha);
+ // Update the last auth error and notify observers of error state.
+ void UpdateAuthErrorState(const GoogleServiceAuthError& error);
+
// Called when a user chooses which data types to sync as part of the sync
// setup wizard. |sync_everything| represents whether they chose the
// "keep everything synced" option; if true, |chosen_types| will be ignored
@@ -326,6 +341,9 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
void RegisterPreferences();
void ClearPreferences();
+ // Return SyncCredentials from the TokenService.
+ sync_api::SyncCredentials GetCredentials();
+
// Test need to override this to create backends that allow setting up
// initial conditions, such as populating sync nodes.
virtual void CreateBackend();
@@ -334,10 +352,8 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
return data_type_controllers_;
}
- // We keep track of the last auth error observed so we can cover up the first
- // "expected" auth failure from observers.
- // TODO(timsteele): Same as expecting_first_run_auth_needed_event_. Remove
- // this!
+ // The wizard will try to read the auth state out of the profile sync
+ // service using this member. Captcha and error state are reflected.
GoogleServiceAuthError last_auth_error_;
// Our asynchronous backend to communicate with sync components living on
@@ -380,11 +396,8 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// The profile whose data we are synchronizing.
Profile* profile_;
- // True if the profile sync service should attempt to use an LSID
- // cookie for authentication. This is typically set to true in
- // ChromiumOS since we want to use the system level authentication
- // for sync.
- bool bootstrap_sync_authentication_;
+ // Email for the ChromiumOS user, if we're running under ChromiumOS.
+ std::string cros_user_;
// TODO(ncarter): Put this in a profile, once there is UI for it.
// This specifies where to find the sync server.
@@ -400,17 +413,6 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// Whether the SyncBackendHost has been initialized.
bool backend_initialized_;
- // Set to true when the user first enables sync, and we are waiting for
- // syncapi to give us the green light on providing credentials for the first
- // time. It is set back to false as soon as we get this message, and is
- // false all other times so we don't have to persist this value as it will
- // get initialized to false.
- // TODO(timsteele): Remove this by way of starting the wizard when enabling
- // sync *before* initializing the backend. syncapi will need to change, but
- // it means we don't have to wait for the first AuthError; if we ever get
- // one, it is actually an error and this bool isn't needed.
- bool expecting_first_run_auth_needed_event_;
-
// Various pieces of UI query this value to determine if they should show
// an "Authenticating.." type of message. We are the only central place
// all auth attempts funnel through, so it makes sense to provide this.
@@ -419,6 +421,9 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
SyncSetupWizard wizard_;
+ // Encapsulates user signin with TokenService.
+ SigninManager signin_;
+
// True if an unrecoverable error (e.g. violation of an assumed invariant)
// occurred during syncer operation. This value should be checked before
// doing any work that might corrupt things further.
@@ -454,6 +459,8 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// desist syncing immediately.
bool expect_sync_configuration_aborted_;
+ scoped_ptr<TokenMigrator> token_migrator_;
+
DISALLOW_COPY_AND_ASSIGN(ProfileSyncService);
};
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index e970457..d0884cc 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/webdata/autofill_change.h"
#include "chrome/browser/webdata/autofill_entry.h"
#include "chrome/browser/webdata/web_database.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/profile_mock.h"
@@ -137,7 +138,7 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
void StartSyncService(Task* task, bool will_fail_association) {
if (!service_.get()) {
service_.reset(
- new TestProfileSyncService(&factory_, &profile_, false, false,
+ new TestProfileSyncService(&factory_, &profile_, "test_user", false,
task));
AutofillDataTypeController* data_type_controller =
new AutofillDataTypeController(&factory_,
@@ -164,6 +165,13 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
EXPECT_CALL(*personal_data_manager_, IsDataLoaded()).
WillRepeatedly(Return(true));
+ // We need tokens to get the tests going
+ token_service_.IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
+
+ EXPECT_CALL(profile_, GetTokenService()).
+ WillRepeatedly(Return(&token_service_));
+
service_->set_num_expected_resumes(will_fail_association ? 0 : 1);
service_->RegisterDataTypeController(data_type_controller);
service_->Initialize();
diff --git a/chrome/browser/sync/profile_sync_service_mock.h b/chrome/browser/sync/profile_sync_service_mock.h
index 1b36c63..3142baf 100644
--- a/chrome/browser/sync/profile_sync_service_mock.h
+++ b/chrome/browser/sync/profile_sync_service_mock.h
@@ -20,7 +20,6 @@ class ProfileSyncServiceMock : public ProfileSyncService {
ProfileSyncServiceMock() {}
virtual ~ProfileSyncServiceMock() {}
- MOCK_METHOD0(EnableForUser, void());
MOCK_METHOD0(DisableForUser, void());
MOCK_METHOD0(OnBackendInitialized, void());
MOCK_METHOD0(OnSyncCycleCompleted, void());
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index c989822..ea53bf7 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_observer_mock.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
@@ -140,7 +141,7 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
int num_pause_expectations) {
if (!service_.get()) {
service_.reset(new TestProfileSyncService(&factory_, &profile_,
- false, false, root_task));
+ "test_user", false, root_task));
service_->set_num_expected_resumes(num_resume_expectations);
service_->set_num_expected_pauses(num_pause_expectations);
PasswordDataTypeController* data_type_controller =
@@ -155,6 +156,13 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
WillOnce(ReturnNewDataTypeManager());
+ // We need tokens to get the tests going
+ token_service_.IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
+
+ EXPECT_CALL(profile_, GetTokenService()).
+ WillRepeatedly(Return(&token_service_));
+
// Creating model safe workers will request the history service and
// password store. I couldn't manage to convince gmock that splitting up
// the expectations to match the class responsibilities was a good thing,
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index b706f7d..e1f3299 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -19,6 +19,7 @@
#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_pref_service.h"
@@ -68,7 +69,7 @@ class ProfileSyncServicePreferenceTest
return false;
service_.reset(new TestProfileSyncService(
- &factory_, profile_.get(), false, false, task));
+ &factory_, profile_.get(), "test", false, task));
// Register the preference data type.
model_associator_ =
@@ -87,6 +88,8 @@ class ProfileSyncServicePreferenceTest
service_->RegisterDataTypeController(
new PreferenceDataTypeController(&factory_,
service_.get()));
+ profile_->GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
service_->Initialize();
MessageLoop::current()->Run();
return true;
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index e12192b..23e4885 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
@@ -110,7 +111,7 @@ class ProfileSyncServiceSessionTest
return false;
sync_service_.reset(new TestProfileSyncService(
- &factory_, profile(), false, false, task));
+ &factory_, profile(), "test user", false, task));
profile()->set_session_service(helper_.service());
// Register the session data type.
@@ -126,6 +127,8 @@ class ProfileSyncServiceSessionTest
sync_service_->set_num_expected_resumes(will_fail_association ? 0 : 1);
sync_service_->RegisterDataTypeController(
new SessionDataTypeController(&factory_, sync_service_.get()));
+ profile()->GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
sync_service_->Initialize();
MessageLoop::current()->Run();
return true;
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index d38e6c9..e831e36 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_profile.h"
@@ -40,6 +41,7 @@ ACTION_P(InvokeCallback, callback_result) {
#define SKIP_MACOSX(test) test
#endif
+// TODO(chron): Test not using cros_user flag and use signin_
class ProfileSyncServiceStartupTest : public testing::Test {
public:
ProfileSyncServiceStartupTest()
@@ -54,7 +56,7 @@ class ProfileSyncServiceStartupTest : public testing::Test {
virtual void SetUp() {
service_.reset(new TestProfileSyncService(&factory_, &profile_,
- false, true, NULL));
+ "test", true, NULL));
service_->AddObserver(&observer_);
service_->set_num_expected_resumes(0);
service_->set_num_expected_pauses(0);
@@ -99,12 +101,17 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFirstTime)) {
Mock::VerifyAndClearExpectations(data_type_manager);
// Then start things up.
- EXPECT_CALL(*data_type_manager, Configure(_)).Times(1);
+ EXPECT_CALL(*data_type_manager, Configure(_)).Times(2);
EXPECT_CALL(*data_type_manager, state()).
WillOnce(Return(DataTypeManager::CONFIGURED));
EXPECT_CALL(*data_type_manager, Stop()).Times(1);
- EXPECT_CALL(observer_, OnStateChanged()).Times(4);
- service_->EnableForUser(NULL);
+ EXPECT_CALL(observer_, OnStateChanged()).Times(5);
+
+ // Create some tokens in the token service; the service will startup when
+ // it is notified that tokens are available.
+ profile_.GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
+
syncable::ModelTypeSet set;
set.insert(syncable::BOOKMARKS);
service_->OnUserChoseDatatypes(false, set);
@@ -119,6 +126,9 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartNormal)) {
EXPECT_CALL(observer_, OnStateChanged()).Times(3);
+ // Pre load the tokens
+ profile_.GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
service_->Initialize();
}
@@ -130,6 +140,8 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(ManagedStartup)) {
EXPECT_CALL(observer_, OnStateChanged()).Times(1);
// Service should not be started by Initialize() since it's managed.
+ profile_.GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
service_->Initialize();
}
@@ -138,6 +150,8 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(SwitchManaged)) {
EXPECT_CALL(*data_type_manager, Configure(_)).Times(1);
EXPECT_CALL(observer_, OnStateChanged()).Times(3);
+ profile_.GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
service_->Initialize();
// The service should stop when switching to managed mode.
@@ -164,51 +178,13 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFailure)) {
WillOnce(DoAll(Notify(NotificationType::SYNC_CONFIGURE_START),
NotifyWithResult(NotificationType::SYNC_CONFIGURE_DONE,
&result)));
- EXPECT_CALL(*data_type_manager, Stop()).Times(1);
EXPECT_CALL(*data_type_manager, state()).
WillOnce(Return(DataTypeManager::STOPPED));
EXPECT_CALL(observer_, OnStateChanged()).Times(3);
+ profile_.GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
service_->Initialize();
EXPECT_TRUE(service_->unrecoverable_error_detected());
}
-
-class ProfileSyncServiceStartupBootstrapTest
- : public ProfileSyncServiceStartupTest {
- public:
- ProfileSyncServiceStartupBootstrapTest() {}
- virtual ~ProfileSyncServiceStartupBootstrapTest() {}
-
- virtual void SetUp() {
- service_.reset(new TestProfileSyncService(&factory_, &profile_,
- true, true, NULL));
- service_->AddObserver(&observer_);
- service_->set_num_expected_resumes(0);
- service_->set_num_expected_pauses(0);
- service_->set_synchronous_sync_configuration();
- }
-};
-
-TEST_F(ProfileSyncServiceStartupBootstrapTest, SKIP_MACOSX(StartFirstTime)) {
- DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
- EXPECT_CALL(*data_type_manager, Configure(_)).Times(1);
- EXPECT_CALL(*data_type_manager, state()).
- WillOnce(Return(DataTypeManager::CONFIGURED));
- EXPECT_CALL(*data_type_manager, Stop()).Times(1);
- EXPECT_CALL(observer_, OnStateChanged()).Times(4);
-
- profile_.GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
-
- // Pretend the login screen worked.
- GaiaAuthConsumer::ClientLoginResult result;
- result.sid = "sid";
- result.lsid = "lsid";
- profile_.GetTokenService()->Initialize("test",
- &profile_);
- profile_.GetTokenService()->UpdateCredentials(result);
-
- // Will start sync even though setup hasn't been completed (since
- // setup is bypassed when bootstrapping is enabled).
- service_->Initialize();
-}
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index 17137ea4..f913433 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/profile_mock.h"
#include "chrome/test/sync/engine/test_id_factory.h"
@@ -153,7 +154,7 @@ class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
void StartSyncService(Task* task) {
if (!service_.get()) {
service_.reset(
- new TestProfileSyncService(&factory_, &profile_, false, false,
+ new TestProfileSyncService(&factory_, &profile_, "test", false,
task));
TypedUrlDataTypeController* data_type_controller =
new TypedUrlDataTypeController(&factory_,
@@ -176,7 +177,14 @@ class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
EXPECT_CALL(profile_, GetHistoryService(_)).
WillRepeatedly(Return(history_service_.get()));
+ token_service_.IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
+
+ EXPECT_CALL(profile_, GetTokenService()).
+ WillRepeatedly(Return(&token_service_));
+
service_->RegisterDataTypeController(data_type_controller);
+
service_->Initialize();
MessageLoop::current()->Run();
}
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index bb366c7..8ea701a 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -15,6 +15,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/sync/engine/syncapi.h"
@@ -32,6 +33,7 @@
#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_profile.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -246,9 +248,10 @@ class ProfileSyncServiceTest : public testing::Test {
}
void StartSyncServiceAndSetInitialSyncEnded(bool set_initial_sync_ended) {
if (!service_.get()) {
+ // Set bootstrap to true and it will provide a logged in user for test
service_.reset(new TestProfileSyncService(&factory_,
profile_.get(),
- false, false, NULL));
+ "test", false, NULL));
if (!set_initial_sync_ended)
service_->dont_set_initial_sync_ended_on_init();
@@ -267,6 +270,9 @@ class ProfileSyncServiceTest : public testing::Test {
new browser_sync::BookmarkDataTypeController(&factory_,
profile_.get(),
service_.get()));
+
+ profile_->GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "token");
service_->Initialize();
MessageLoop::current()->Run();
}
@@ -467,15 +473,15 @@ TEST_F(ProfileSyncServiceTest, InitialState) {
TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
service_.reset(new TestProfileSyncService(&factory_, profile_.get(),
- false, true, NULL));
+ "test", true, NULL));
service_->set_num_expected_resumes(0);
- EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
- WillOnce(ReturnNewDataTypeManager());
+ EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
EXPECT_CALL(factory_, CreateBookmarkSyncComponents(_, _)).Times(0);
service_->RegisterDataTypeController(
new browser_sync::BookmarkDataTypeController(&factory_,
profile_.get(),
service_.get()));
+
service_->Initialize();
service_.reset();
}
@@ -1349,9 +1355,9 @@ TEST_F(ProfileSyncServiceTestWithData, TestStartupWithOldSyncData) {
if (!service_.get()) {
service_.reset(
new TestProfileSyncService(&factory_, profile_.get(),
- false, true, NULL));
-
+ "test", true, NULL));
service_->dont_set_initial_sync_ended_on_init();
+ service_->set_synchronous_sync_configuration();
profile_->GetPrefs()->SetBoolean(prefs::kSyncHasSetupCompleted, false);
model_associator_ = new TestBookmarkModelAssociator(service_.get(),
@@ -1376,26 +1382,25 @@ TEST_F(ProfileSyncServiceTestWithData, TestStartupWithOldSyncData) {
ASSERT_FALSE(service_->backend());
ASSERT_FALSE(service_->HasSyncSetupCompleted());
- // This will actually start up the sync service.
- service_->EnableForUser(NULL);
+ // Create some tokens in the token service; the service will startup when
+ // it is notified that tokens are available.
+ profile_->GetTokenService()->IssueAuthTokenForTest(
+ GaiaConstants::kSyncService, "sync_token");
+
syncable::ModelTypeSet set;
set.insert(syncable::BOOKMARKS);
service_->OnUserChoseDatatypes(false, set);
- MessageLoop::current()->Run();
+ MessageLoop::current()->RunAllPending();
// Stop the service so we can read the new Sync Data files that were created.
service_.reset();
// This file should have been deleted when the whole directory was nuked.
ASSERT_FALSE(file_util::PathExists(sync_file3));
+ ASSERT_FALSE(file_util::PathExists(sync_file1));
- // These two will still exist, but their texts should have changed.
- ASSERT_TRUE(file_util::PathExists(sync_file1));
- std::string file1text;
- file_util::ReadFileToString(sync_file1, &file1text);
- ASSERT_FALSE(file1text.compare(nonsense1) == 0);
-
+ // This will still exist, but the text should have changed.
ASSERT_TRUE(file_util::PathExists(sync_file2));
std::string file2text;
file_util::ReadFileToString(sync_file2, &file2text);
diff --git a/chrome/browser/sync/sessions/sync_session_context.h b/chrome/browser/sync/sessions/sync_session_context.h
index 1e37a7c..4c6b63f 100644
--- a/chrome/browser/sync/sessions/sync_session_context.h
+++ b/chrome/browser/sync/sessions/sync_session_context.h
@@ -31,7 +31,6 @@ class DirectoryManager;
namespace browser_sync {
-class AuthWatcher;
class ConflictResolver;
class ModelSafeWorkerRegistrar;
class ServerConnectionManager;
@@ -43,13 +42,11 @@ class ScopedSessionContextSyncerEventChannel;
class SyncSessionContext {
public:
SyncSessionContext(ServerConnectionManager* connection_manager,
- AuthWatcher* auth_watcher,
syncable::DirectoryManager* directory_manager,
ModelSafeWorkerRegistrar* model_safe_worker_registrar)
: resolver_(NULL),
syncer_event_channel_(NULL),
connection_manager_(connection_manager),
- auth_watcher_(auth_watcher),
directory_manager_(directory_manager),
registrar_(model_safe_worker_registrar),
extensions_activity_monitor_(new ExtensionsActivityMonitor()),
@@ -68,9 +65,6 @@ class SyncSessionContext {
ServerConnectionManager* connection_manager() {
return connection_manager_;
}
- AuthWatcher* auth_watcher() {
- return auth_watcher_;
- }
syncable::DirectoryManager* directory_manager() {
return directory_manager_;
}
@@ -125,7 +119,6 @@ class SyncSessionContext {
SyncerEventChannel* syncer_event_channel_;
ServerConnectionManager* const connection_manager_;
- AuthWatcher* const auth_watcher_;
syncable::DirectoryManager* const directory_manager_;
// A registrar of workers capable of processing work closures on a thread
diff --git a/chrome/browser/sync/sessions/sync_session_unittest.cc b/chrome/browser/sync/sessions/sync_session_unittest.cc
index 2bc4594..011f667 100644
--- a/chrome/browser/sync/sessions/sync_session_unittest.cc
+++ b/chrome/browser/sync/sessions/sync_session_unittest.cc
@@ -27,7 +27,7 @@ class SyncSessionTest : public testing::Test,
GetModelSafeRoutingInfo(&routes_);
}
virtual void SetUp() {
- context_.reset(new SyncSessionContext(NULL, NULL, NULL, this));
+ context_.reset(new SyncSessionContext(NULL, NULL, this));
session_.reset(new SyncSession(context_.get(), this));
}
virtual void TearDown() {
@@ -40,7 +40,7 @@ class SyncSessionTest : public testing::Test,
}
virtual bool IsSyncingCurrentlySilenced() {
FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced");
- return false;
+ return false;
}
virtual void OnReceivedLongPollIntervalUpdate(
const base::TimeDelta& new_interval) {
@@ -51,7 +51,7 @@ class SyncSessionTest : public testing::Test,
FailControllerInvocationIfDisabled("OnReceivedShortPollIntervalUpdate");
}
virtual void OnShouldStopSyncingPermanently() {
- FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently");
+ FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently");
}
// ModelSafeWorkerRegistrar implementation.
@@ -110,7 +110,7 @@ TEST_F(SyncSessionTest, SetWriteTransaction) {
TestDirectorySetterUpper db;
db.SetUp();
session_.reset(NULL);
- context_.reset(new SyncSessionContext(NULL, NULL, db.manager(), this));
+ context_.reset(new SyncSessionContext(NULL, db.manager(), this));
session_.reset(new SyncSession(context_.get(), this));
context_->set_account_name(db.name());
syncable::ScopedDirLookup dir(context_->directory_manager(),
diff --git a/chrome/browser/sync/signin_manager.cc b/chrome/browser/sync/signin_manager.cc
new file mode 100644
index 0000000..6f2a30c
--- /dev/null
+++ b/chrome/browser/sync/signin_manager.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2010 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 "chrome/browser/sync/signin_manager.h"
+
+#include "base/string_util.h"
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+
+// static
+void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
+ user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, "");
+}
+
+void SigninManager::Initialize(Profile* profile) {
+ profile_ = profile;
+ username_ = profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
+ profile_->GetTokenService()->Initialize(
+ GaiaConstants::kChromeSource, profile_);
+ if (!username_.empty()) {
+ profile_->GetTokenService()->LoadTokensFromDB();
+ }
+}
+
+// If a username already exists, the user is logged in.
+const std::string& SigninManager::GetUsername() {
+ return username_;
+}
+
+void SigninManager::SetUsername(const std::string& username) {
+ username_ = username;
+}
+
+// Users must always sign out before they sign in again.
+void SigninManager::StartSignIn(const std::string& username,
+ const std::string& password,
+ const std::string& login_token,
+ const std::string& login_captcha) {
+ DCHECK(username_.empty());
+ // The Sign out should clear the token service credentials.
+ DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
+
+ username_.assign(username);
+ password_.assign(password);
+
+ client_login_.reset(new GaiaAuthenticator2(this,
+ GaiaConstants::kChromeSource,
+ profile_->GetRequestContext()));
+ client_login_->StartClientLogin(username,
+ password,
+ "",
+ login_token,
+ login_captcha);
+}
+
+void SigninManager::SignOut() {
+ client_login_.reset();
+ username_.clear();
+ password_.clear();
+ profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
+ profile_->GetPrefs()->ScheduleSavePersistentPrefs();
+ profile_->GetTokenService()->ResetCredentialsInMemory();
+ profile_->GetTokenService()->EraseTokensFromDB();
+}
+
+void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
+ profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
+ profile_->GetPrefs()->ScheduleSavePersistentPrefs();
+
+ GoogleServiceSigninSuccessDetails details(username_, password_);
+ NotificationService::current()->Notify(
+ NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
+ Source<SigninManager>(this),
+ Details<const GoogleServiceSigninSuccessDetails>(&details));
+
+ password_.clear(); // Don't need it anymore.
+
+ profile_->GetTokenService()->UpdateCredentials(result);
+ DCHECK(profile_->GetTokenService()->AreCredentialsValid());
+ profile_->GetTokenService()->StartFetchingTokens();
+}
+
+void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
+ GoogleServiceAuthError details(error);
+ NotificationService::current()->Notify(
+ NotificationType::GOOGLE_SIGNIN_FAILED,
+ Source<SigninManager>(this),
+ Details<const GoogleServiceAuthError>(&details));
+ SignOut();
+}
diff --git a/chrome/browser/sync/signin_manager.h b/chrome/browser/sync/signin_manager.h
new file mode 100644
index 0000000..a62514f
--- /dev/null
+++ b/chrome/browser/sync/signin_manager.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2010 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.
+//
+// The signin manager encapsulates some functionality tracking
+// which user is signed in. When a user is signed in, a ClientLogin
+// request is run on their behalf. Auth tokens are fetched from Google
+// and the results are stored in the TokenService.
+
+#ifndef CHROME_BROWSER_SYNC_SIGNIN_MANAGER_H_
+#define CHROME_BROWSER_SYNC_SIGNIN_MANAGER_H_
+#pragma once
+
+#include <string>
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "chrome/common/net/gaia/gaia_auth_consumer.h"
+#include "chrome/common/net/gaia/google_service_auth_error.h"
+
+class GaiaAuthenticator2;
+class Profile;
+class PrefService;
+
+// Details for the Notification type GOOGLE_SIGNIN_SUCCESSFUL.
+// A listener might use this to make note of a username / password
+// pair for encryption keys.
+struct GoogleServiceSigninSuccessDetails {
+ GoogleServiceSigninSuccessDetails(const std::string& in_username,
+ const std::string& in_password)
+ : username(in_username),
+ password(in_password) {}
+ std::string username;
+ std::string password;
+};
+
+class SigninManager : public GaiaAuthConsumer {
+ public:
+ // Call to register our prefs.
+ static void RegisterUserPrefs(PrefService* user_prefs);
+
+ // If user was signed in, load tokens from DB if available.
+ void Initialize(Profile* profile);
+
+ // If a user is signed in, this will return their name.
+ // Otherwise, it will return an empty string.
+ const std::string& GetUsername();
+
+ // Sets the user name. Used for migrating credentials from previous system.
+ void SetUsername(const std::string& username);
+
+ // Attempt to sign in this user. If successful, set a preference indicating
+ // the signed in user and send out a notification, then start fetching tokens
+ // for the user.
+ void StartSignIn(const std::string& username,
+ const std::string& password,
+ const std::string& login_token,
+ const std::string& login_captcha);
+ // Sign a user out, removing the preference, erasing all keys
+ // associated with the user, and cancelling all auth in progress.
+ void SignOut();
+
+ // GaiaAuthConsumer
+ virtual void OnClientLoginSuccess(const ClientLoginResult& result);
+ virtual void OnClientLoginFailure(const GoogleServiceAuthError& error);
+ virtual void OnIssueAuthTokenSuccess(const std::string& service,
+ const std::string& auth_token) {
+ NOTREACHED();
+ }
+ virtual void OnIssueAuthTokenFailure(const std::string& service,
+ const GoogleServiceAuthError& error) {
+ NOTREACHED();
+ }
+
+ private:
+ Profile* profile_;
+ std::string username_;
+ std::string password_; // This is kept empty whenever possible.
+ scoped_ptr<GaiaAuthenticator2> client_login_;
+};
+
+#endif // CHROME_BROWSER_SYNC_SIGNIN_MANAGER_H_
diff --git a/chrome/browser/sync/signin_manager_unittest.cc b/chrome/browser/sync/signin_manager_unittest.cc
new file mode 100644
index 0000000..208667c
--- /dev/null
+++ b/chrome/browser/sync/signin_manager_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 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 "chrome/browser/sync/signin_manager.h"
+
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/net/gaia/token_service_unittest.h"
+#include "chrome/browser/password_manager/encryptor.h"
+#include "chrome/browser/webdata/web_data_service.h"
+#include "chrome/common/net/test_url_fetcher_factory.h"
+#include "chrome/test/testing_profile.h"
+#include "chrome/test/signaling_task.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+class SigninManagerTest : public TokenServiceTestHarness {
+ public:
+ virtual void SetUp() {
+ TokenServiceTestHarness::SetUp();
+ manager_.reset(new SigninManager());
+ google_login_success_.ListenFor(NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
+ Source<SigninManager>(manager_.get()));
+ google_login_failure_.ListenFor(NotificationType::GOOGLE_SIGNIN_FAILED,
+ Source<SigninManager>(manager_.get()));
+
+ URLFetcher::set_factory(&factory_);
+ }
+
+ TestURLFetcherFactory factory_;
+ scoped_ptr<SigninManager> manager_;
+ TestNotificationTracker google_login_success_;
+ TestNotificationTracker google_login_failure_;
+};
+
+TEST_F(SigninManagerTest, SignIn) {
+ manager_->Initialize(profile_.get());
+ EXPECT_TRUE(manager_->GetUsername().empty());
+
+ manager_->StartSignIn("username", "password", "", "");
+ EXPECT_FALSE(manager_->GetUsername().empty());
+
+ // Should go into token service and stop.
+ manager_->OnClientLoginSuccess(credentials_);
+ EXPECT_EQ(1U, google_login_success_.size());
+ EXPECT_EQ(0U, google_login_failure_.size());
+
+ // Should persist across resets.
+ manager_.reset(new SigninManager());
+ manager_->Initialize(profile_.get());
+ EXPECT_FALSE(manager_->GetUsername().empty());
+}
+
+TEST_F(SigninManagerTest, SignOut) {
+ manager_->Initialize(profile_.get());
+ manager_->StartSignIn("username", "password", "", "");
+ manager_->OnClientLoginSuccess(credentials_);
+
+ EXPECT_FALSE(manager_->GetUsername().empty());
+ manager_->SignOut();
+ EXPECT_TRUE(manager_->GetUsername().empty());
+ // Should not be persisted anymore
+ manager_.reset(new SigninManager());
+ manager_->Initialize(profile_.get());
+ EXPECT_TRUE(manager_->GetUsername().empty());
+}
+
+TEST_F(SigninManagerTest, SignInFailure) {
+ manager_->Initialize(profile_.get());
+ manager_->StartSignIn("username", "password", "", "");
+ GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
+ manager_->OnClientLoginFailure(error);
+
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(1U, google_login_failure_.size());
+
+ EXPECT_TRUE(manager_->GetUsername().empty());
+
+ // Should not be persisted
+ manager_.reset(new SigninManager());
+ manager_->Initialize(profile_.get());
+ EXPECT_TRUE(manager_->GetUsername().empty());
+}
+
+TEST_F(SigninManagerTest, SignOutMidConnect) {
+ manager_->Initialize(profile_.get());
+ manager_->StartSignIn("username", "password", "", "");
+ manager_->SignOut();
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(0U, google_login_failure_.size());
+
+ EXPECT_TRUE(manager_->GetUsername().empty());
+}
diff --git a/chrome/browser/sync/sync_setup_wizard_unittest.cc b/chrome/browser/sync/sync_setup_wizard_unittest.cc
index 5ecd9b6..484d376 100644
--- a/chrome/browser/sync/sync_setup_wizard_unittest.cc
+++ b/chrome/browser/sync/sync_setup_wizard_unittest.cc
@@ -32,7 +32,7 @@ typedef GoogleServiceAuthError AuthError;
class ProfileSyncServiceForWizardTest : public ProfileSyncService {
public:
ProfileSyncServiceForWizardTest(ProfileSyncFactory* factory, Profile* profile)
- : ProfileSyncService(factory, profile, false),
+ : ProfileSyncService(factory, profile, ""),
user_cancelled_dialog_(false) {
RegisterPreferences();
ResetTestStats();
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index c7c1575..32391ae 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -188,8 +188,8 @@ void OpenSyncMyBookmarksDialog(
if (service->HasSyncSetupCompleted()) {
ShowOptionsWindow(OPTIONS_PAGE_CONTENT, OPTIONS_GROUP_NONE, profile);
} else {
- service->EnableForUser(NULL);
- ProfileSyncService::SyncEvent(code);
+ service->ShowLoginDialog(NULL);
+ ProfileSyncService::SyncEvent(code); // UMA stats
}
}
diff --git a/chrome/browser/sync/syncable/directory_manager.cc b/chrome/browser/sync/syncable/directory_manager.cc
index 0719c67..fbdeb46 100644
--- a/chrome/browser/sync/syncable/directory_manager.cc
+++ b/chrome/browser/sync/syncable/directory_manager.cc
@@ -54,17 +54,6 @@ bool DirectoryManager::Open(const std::string& name) {
bool was_open = false;
const DirOpenResult result = OpenImpl(name,
GetSyncDataDatabasePath(), &was_open);
- if (!was_open) {
- DirectoryManagerEvent event;
- event.dirname = name;
- if (syncable::OPENED == result) {
- event.what_happened = DirectoryManagerEvent::OPENED;
- } else {
- event.what_happened = DirectoryManagerEvent::OPEN_FAILED;
- event.error = result;
- }
- channel_->NotifyListeners(event);
- }
return syncable::OPENED == result;
}
diff --git a/chrome/browser/sync/syncable/directory_manager.h b/chrome/browser/sync/syncable/directory_manager.h
index a6f0847..0c0b55d 100644
--- a/chrome/browser/sync/syncable/directory_manager.h
+++ b/chrome/browser/sync/syncable/directory_manager.h
@@ -31,14 +31,11 @@ namespace syncable {
struct DirectoryManagerEvent {
enum {
- OPEN_FAILED,
- OPENED,
CLOSED,
CLOSED_ALL,
SHUTDOWN,
} what_happened;
std::string dirname;
- DirOpenResult error; // Only for OPEN_FAILED.
typedef DirectoryManagerEvent EventType;
static inline bool IsChannelShutdownEvent(const EventType& event) {
return SHUTDOWN == event.what_happened;
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index aba7c42..0854a6b 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -100,7 +100,7 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
UserShare* user_share = core_->syncapi()->GetUserShare();
DirectoryManager* dir_manager = user_share->dir_manager.get();
- ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
+ ScopedDirLookup dir(dir_manager, user_share->name);
if (!dir.good())
FAIL();
@@ -154,7 +154,6 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
&SyncBackendHost::Core::DoInitializeForTest,
user,
options.http_bridge_factory,
- options.auth_http_bridge_factory,
options.delete_sync_data_folder,
browser_sync::kDefaultNotificationMethod));
@@ -186,10 +185,12 @@ class TestProfileSyncService : public ProfileSyncService {
public:
TestProfileSyncService(ProfileSyncFactory* factory,
Profile* profile,
- bool bootstrap_sync_authentication,
+ const std::string& test_user,
bool synchronous_backend_initialization,
Task* initial_condition_setup_task)
- : ProfileSyncService(factory, profile, bootstrap_sync_authentication),
+ : ProfileSyncService(factory, profile,
+ !test_user.empty() ?
+ test_user : ""),
synchronous_backend_initialization_(
synchronous_backend_initialization),
synchronous_sync_configuration_(false),
diff --git a/chrome/browser/sync/token_migrator.cc b/chrome/browser/sync/token_migrator.cc
new file mode 100644
index 0000000..084bc40
--- /dev/null
+++ b/chrome/browser/sync/token_migrator.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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 "chrome/browser/sync/token_migrator.h"
+
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/util/user_settings.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
+
+const FilePath::CharType kSyncDataFolderName[] =
+ FILE_PATH_LITERAL("Sync Data");
+
+const FilePath::CharType kBookmarkSyncUserSettingsDatabase[] =
+ FILE_PATH_LITERAL("BookmarkSyncSettings.sqlite3");
+
+using browser_sync::UserSettings;
+
+TokenMigrator::TokenMigrator(ProfileSyncService* service,
+ const FilePath& profile_path)
+ : service_(service),
+ database_location_(profile_path.Append(kSyncDataFolderName)) {
+}
+
+TokenMigrator::~TokenMigrator() {
+}
+
+void TokenMigrator::TryMigration() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(ChromeThread::DB, FROM_HERE,
+ NewRunnableMethod(this, &TokenMigrator::LoadTokens));
+}
+
+void TokenMigrator::LoadTokens() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ scoped_ptr<UserSettings> user_settings(new UserSettings());
+ FilePath settings_db_file =
+ database_location_.Append(FilePath(kBookmarkSyncUserSettingsDatabase));
+ if (!user_settings->Init(settings_db_file))
+ return;
+
+ if (!user_settings->GetLastUserAndServiceToken(GaiaConstants::kSyncService,
+ &username_, &token_))
+ return;
+
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &TokenMigrator::PostTokensBack));
+}
+
+void TokenMigrator::PostTokensBack() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ service_->LoadMigratedCredentials(username_, token_);
+}
diff --git a/chrome/browser/sync/token_migrator.h b/chrome/browser/sync/token_migrator.h
new file mode 100644
index 0000000..6ee3394
--- /dev/null
+++ b/chrome/browser/sync/token_migrator.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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 <string>
+
+#include "base/file_path.h"
+#include "base/task.h"
+
+class ProfileSyncService;
+
+// The TokenMigrator provides a bridge between the IO thread and
+// the UI thread to load the old-style credentials from the user
+// settings DB, and post them back to the UI thread to store the
+// token in the token service.
+class TokenMigrator {
+ public:
+ TokenMigrator(ProfileSyncService* service,
+ const FilePath& profile_path);
+ ~TokenMigrator();
+
+ // This is called on the UI thread, it only posts a task.
+ // If migration succeeds, the tokens will become available in
+ // the token service.
+ void TryMigration();
+
+ private:
+ // This runs as a deferred task on the DB thread.
+ void LoadTokens();
+
+ // This runs as a deferred task on the UI thread (only after the DB thread is
+ // finished with the data.
+ void PostTokensBack();
+
+ // The username and token retrieved from the user settings DB.
+ std::string username_;
+ std::string token_;
+
+ // The ProfileSyncService owns this object, so this pointer is valid when
+ // PostTokensBack is called.
+ ProfileSyncService* service_;
+
+ // Pending tasks, stored so they can be canceled if this object is destroyed.
+ CancelableTask* loading_task_;
+
+ // The directory to search for the user settings database.
+ FilePath database_location_;
+
+ DISALLOW_COPY_AND_ASSIGN(TokenMigrator);
+};
+
+// We ensure this object will outlive its tasks, so don't need refcounting.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(TokenMigrator);
diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc
index 41b9ffa..9af444f 100644
--- a/chrome/browser/views/options/content_page_view.cc
+++ b/chrome/browser/views/options/content_page_view.cc
@@ -139,7 +139,7 @@ void ContentPageView::ButtonPressed(
IDS_CONFIRM_STOP_SYNCING_DIALOG_HEIGHT_LINES)));
return;
} else {
- sync_service_->EnableForUser(GetWindow()->GetNativeWindow());
+ sync_service_->ShowLoginDialog(GetWindow()->GetNativeWindow());
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
}
} else if (sender == sync_customize_button_) {
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 8851192..47e84f4 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -903,10 +903,6 @@
'browser/sync/engine/all_status.h',
'browser/sync/engine/apply_updates_command.cc',
'browser/sync/engine/apply_updates_command.h',
- 'browser/sync/engine/auth_watcher.cc',
- 'browser/sync/engine/auth_watcher.h',
- 'browser/sync/engine/authenticator.cc',
- 'browser/sync/engine/authenticator.h',
'browser/sync/engine/build_and_process_conflict_sets_command.cc',
'browser/sync/engine/build_and_process_conflict_sets_command.h',
'browser/sync/engine/build_commit_command.cc',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 257b1e0..e6343f3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2538,18 +2538,18 @@
'browser/sync/engine/syncapi.h',
'browser/sync/glue/app_data_type_controller.cc',
'browser/sync/glue/app_data_type_controller.h',
- 'browser/sync/glue/autofill_change_processor.h',
'browser/sync/glue/autofill_change_processor.cc',
+ 'browser/sync/glue/autofill_change_processor.h',
'browser/sync/glue/autofill_data_type_controller.cc',
'browser/sync/glue/autofill_data_type_controller.h',
- 'browser/sync/glue/autofill_model_associator.h',
'browser/sync/glue/autofill_model_associator.cc',
+ 'browser/sync/glue/autofill_model_associator.h',
'browser/sync/glue/bookmark_change_processor.cc',
'browser/sync/glue/bookmark_change_processor.h',
'browser/sync/glue/bookmark_data_type_controller.cc',
'browser/sync/glue/bookmark_data_type_controller.h',
- 'browser/sync/glue/bookmark_model_associator.h',
'browser/sync/glue/bookmark_model_associator.cc',
+ 'browser/sync/glue/bookmark_model_associator.h',
'browser/sync/glue/change_processor.cc',
'browser/sync/glue/change_processor.h',
'browser/sync/glue/data_type_controller.h',
@@ -2566,16 +2566,14 @@
'browser/sync/glue/extension_data_type_controller.h',
'browser/sync/glue/extension_model_associator.cc',
'browser/sync/glue/extension_model_associator.h',
- 'browser/sync/glue/extension_sync_traits.cc',
- 'browser/sync/glue/extension_sync_traits.h',
'browser/sync/glue/extension_sync.cc',
'browser/sync/glue/extension_sync.h',
+ 'browser/sync/glue/extension_sync_traits.cc',
+ 'browser/sync/glue/extension_sync_traits.h',
'browser/sync/glue/extension_util.cc',
'browser/sync/glue/extension_util.h',
'browser/sync/glue/history_model_worker.cc',
'browser/sync/glue/history_model_worker.h',
- 'browser/sync/glue/password_model_worker.cc',
- 'browser/sync/glue/password_model_worker.h',
'browser/sync/glue/http_bridge.cc',
'browser/sync/glue/http_bridge.h',
'browser/sync/glue/model_associator.h',
@@ -2585,6 +2583,8 @@
'browser/sync/glue/password_data_type_controller.h',
'browser/sync/glue/password_model_associator.cc',
'browser/sync/glue/password_model_associator.h',
+ 'browser/sync/glue/password_model_worker.cc',
+ 'browser/sync/glue/password_model_worker.h',
'browser/sync/glue/preference_change_processor.cc',
'browser/sync/glue/preference_change_processor.h',
'browser/sync/glue/preference_data_type_controller.cc',
@@ -2616,13 +2616,15 @@
'browser/sync/glue/typed_url_model_associator.h',
'browser/sync/glue/ui_model_worker.cc',
'browser/sync/glue/ui_model_worker.h',
- 'browser/sync/notification_method.h',
'browser/sync/notification_method.cc',
- 'browser/sync/profile_sync_service.cc',
- 'browser/sync/profile_sync_service.h',
+ 'browser/sync/notification_method.h',
'browser/sync/profile_sync_factory.h',
'browser/sync/profile_sync_factory_impl.cc',
'browser/sync/profile_sync_factory_impl.h',
+ 'browser/sync/profile_sync_service.cc',
+ 'browser/sync/profile_sync_service.h',
+ 'browser/sync/signin_manager.cc',
+ 'browser/sync/signin_manager.h',
'browser/sync/sync_constants.cc',
'browser/sync/sync_constants.h',
'browser/sync/sync_setup_flow.cc',
@@ -2631,8 +2633,10 @@
'browser/sync/sync_setup_wizard.h',
'browser/sync/sync_ui_util.cc',
'browser/sync/sync_ui_util.h',
- 'browser/sync/sync_ui_util_mac.mm',
'browser/sync/sync_ui_util_mac.h',
+ 'browser/sync/sync_ui_util_mac.mm',
+ 'browser/sync/token_migrator.cc',
+ 'browser/sync/token_migrator.h',
'browser/tab_closeable_state_watcher.cc',
'browser/tab_closeable_state_watcher.h',
'browser/tab_contents/background_contents.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index d9c244c..f0470e9 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1147,6 +1147,7 @@
'browser/net/chrome_url_request_context_unittest.cc',
'browser/net/connection_tester_unittest.cc',
'browser/net/gaia/token_service_unittest.cc',
+ 'browser/net/gaia/token_service_unittest.h',
'browser/net/load_timing_observer_unittest.cc',
'browser/net/passive_log_collector_unittest.cc',
'browser/net/predictor_unittest.cc',
@@ -1263,6 +1264,7 @@
'browser/sync/profile_sync_service_typed_url_unittest.cc',
'browser/sync/profile_sync_service_unittest.cc',
'browser/sync/profile_sync_test_util.h',
+ 'browser/sync/signin_manager_unittest.cc',
'browser/sync/sync_setup_wizard_unittest.cc',
'browser/sync/sync_ui_util_mac_unittest.mm',
'browser/sync/test_profile_sync_service.h',
@@ -2178,7 +2180,6 @@
'sources': [
'app/breakpad_mac_stubs.mm',
'browser/sync/engine/apply_updates_command_unittest.cc',
- 'browser/sync/engine/auth_watcher_unittest.cc',
'browser/sync/engine/cleanup_disabled_types_command_unittest.cc',
'browser/sync/engine/download_updates_command_unittest.cc',
'browser/sync/engine/mock_model_safe_workers.h',
@@ -2353,7 +2354,6 @@
'test/live_sync/many_client_live_preferences_sync_test.cc',
'test/live_sync/multiple_client_live_bookmarks_sync_test.cc',
'test/live_sync/multiple_client_live_preferences_sync_test.cc',
- 'test/live_sync/offline_sync_test.cc',
'test/live_sync/profile_sync_service_test_harness.cc',
'test/live_sync/profile_sync_service_test_harness.h',
'test/live_sync/single_client_live_bookmarks_sync_test.cc',
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index df520c6..834b9e5 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -1045,6 +1045,13 @@ class NotificationType {
// are a ChromeCookieDetails object.
COOKIE_CHANGED,
+ // Sidebar -----------------------------------------------------------------
+
+ // Sent when the sidebar state is changed.
+ // The source is a SidebarManager instance, the details are the changed
+ // SidebarContainer object.
+ SIDEBAR_CHANGED,
+
// Token Service -----------------------------------------------------------
// When the token service has a new token available for a service, one of
@@ -1053,16 +1060,32 @@ class NotificationType {
// TokenAvailableDetails object.
TOKEN_AVAILABLE,
- // Sent when the sidebar state is changed.
- // The source is a SidebarManager instance, the details are the changed
- // SidebarContainer object.
- SIDEBAR_CHANGED,
+ // When there aren't any additional tokens left to load, this notification
+ // is sent.
+ // The source is a TokenService on the profile. There are no details.
+ TOKEN_LOADING_FINISHED,
// If a token request failed, one of these is issued per failed request.
// The source is a TokenService on the Profile. The details are a
// TokenRequestFailedDetails object.
TOKEN_REQUEST_FAILED,
+ // When a service has a new token they got from a frontend that the
+ // TokenService should know about, fire this notification. The details
+ // are a TokenAvailableDetails object.
+ TOKEN_UPDATED,
+
+ // Sent when a user signs into Google services such as sync.
+ // The source is the SigninManager instance. The details are a
+ // GoogleServiceSignin object.
+ GOOGLE_SIGNIN_SUCCESSFUL,
+
+ // Sent when a user fails to sign into Google services such as sync.
+ // The source is the SigninManager instance. The details are a
+ // GoogleServiceAuthError object.
+ GOOGLE_SIGNIN_FAILED,
+
+
// Misc --------------------------------------------------------------------
#if defined(OS_CHROMEOS)
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 2cd8b84..168f4e8 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -923,10 +923,17 @@ const char kSyncManaged[] = "sync.managed";
// used when sync is disabled by the user via the privacy dashboard.
const char kSyncSuppressStart[] = "sync.suppress_start";
+// Boolean to reperesent if sync credentials have been migrated from the
+// user settings DB to the token service.
+const char kSyncCredentialsMigrated[] = "sync.credentials_migrated";
+
// A string that can be used to restore sync encryption infrastructure on
// startup so that the user doesn't need to provide credentials on each start.
const char kEncryptionBootstrapToken[] = "sync.encryption_bootstrap_token";
+// String that identifies the user logged into sync and other google services.
+const char kGoogleServicesUsername[] = "google.services.username";
+
// Create web application shortcut dialog preferences.
const char kWebAppCreateOnDesktop[] = "browser.web_app.create_on_desktop";
const char kWebAppCreateInAppsMenu[] = "browser.web_app.create_in_apps_menu";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 6321c6a..1caaa31b 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -342,6 +342,8 @@ extern const char kSyncTypedUrls[];
extern const char kSyncExtensions[];
extern const char kSyncManaged[];
extern const char kSyncSuppressStart[];
+extern const char kGoogleServicesUsername[];
+extern const char kSyncCredentialsMigrated[];
extern const char kEncryptionBootstrapToken[];
extern const char kWebAppCreateOnDesktop[];
diff --git a/chrome/test/live_sync/live_sync_test.cc b/chrome/test/live_sync/live_sync_test.cc
index 5ff3e74..9fc8598 100644
--- a/chrome/test/live_sync/live_sync_test.cc
+++ b/chrome/test/live_sync/live_sync_test.cc
@@ -22,6 +22,7 @@
#include "chrome/test/testing_browser_process.h"
#include "googleurl/src/gurl.h"
#include "net/base/escape.h"
+#include "net/base/network_change_notifier.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/proxy/proxy_service.h"
@@ -231,6 +232,10 @@ void LiveSyncTest::SetUpInProcessBrowserTestFixture() {
// Without this, running the test case on Linux causes an error as we make an
// external DNS lookup of "ocsp.thawte.com".
resolver->AllowDirectLookup("*.thawte.com");
+ // The new XMPP cert seems to use crl.geotrust.com on Linux.
+ resolver->AllowDirectLookup("*.geotrust.com");
+ // SSL chain.
+ resolver->AllowDirectLookup("*.gstatic.com");
mock_host_resolver_override_.reset(
new net::ScopedDefaultHostResolverProc(resolver));
}
@@ -255,10 +260,12 @@ void LiveSyncTest::TearDownLocalTestServer() {
ASSERT_TRUE(test_server_.Stop());
}
-
void LiveSyncTest::EnableNetwork(Profile* profile) {
SetProxyConfig(profile->GetRequestContext(),
net::ProxyConfig::CreateDirect());
+ // Bugs: http://crbug.com/53857
+ // http://crbug.com/53858
+ net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
}
void LiveSyncTest::DisableNetwork(Profile* profile) {
@@ -267,6 +274,7 @@ void LiveSyncTest::DisableNetwork(Profile* profile) {
net::ProxyConfig config;
config.proxy_rules().ParseFromString("http=127.0.0.1:0");
SetProxyConfig(profile->GetRequestContext(), config);
+ net::NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
}
bool LiveSyncTest::EnsureSyncServerConfiguration() {
diff --git a/chrome/test/live_sync/offline_sync_test.cc b/chrome/test/live_sync/offline_sync_test.cc
deleted file mode 100644
index c64df34..0000000
--- a/chrome/test/live_sync/offline_sync_test.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2010 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 "chrome/browser/profile.h"
-#include "chrome/common/net/gaia/google_service_auth_error.h"
-#include "chrome/test/live_sync/live_sync_test.h"
-#include "chrome/test/live_sync/profile_sync_service_test_harness.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-class OfflineSyncTest : public LiveSyncTest {
- public:
- OfflineSyncTest() : LiveSyncTest(LiveSyncTest::SINGLE_CLIENT) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(OfflineSyncTest);
-};
-
-IN_PROC_BROWSER_TEST_F(OfflineSyncTest, OfflineStart) {
- ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
- DisableNetwork(GetProfile(0));
-
- EXPECT_FALSE(GetClient(0)->SetupSync());
- EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED,
- GetClient(0)->service()->GetAuthError().state());
-
- EnableNetwork(GetProfile(0));
- EXPECT_TRUE(GetClient(0)->RetryAuthentication());
-}
diff --git a/chrome/test/live_sync/profile_sync_service_test_harness.cc b/chrome/test/live_sync/profile_sync_service_test_harness.cc
index 12448da..b49bf56 100644
--- a/chrome/test/live_sync/profile_sync_service_test_harness.cc
+++ b/chrome/test/live_sync/profile_sync_service_test_harness.cc
@@ -7,9 +7,11 @@
#include "chrome/browser/defaults.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "chrome/browser/sync/sessions/session_state.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/live_sync/profile_sync_service_test_harness.h"
@@ -84,7 +86,8 @@ bool StateChangeTimeoutEvent::Abort() {
ProfileSyncServiceTestHarness::ProfileSyncServiceTestHarness(Profile* p,
const std::string& username, const std::string& password, int id)
- : wait_state_(WAITING_FOR_ON_AUTH_ERROR), profile_(p), service_(NULL),
+ : wait_state_(WAITING_FOR_ON_BACKEND_INITIALIZED),
+ profile_(p), service_(NULL),
last_status_(kInvalidStatus),
last_timestamp_(0),
min_timestamp_needed_(kMinTimestampNeededNone),
@@ -95,15 +98,11 @@ ProfileSyncServiceTestHarness::ProfileSyncServiceTestHarness(Profile* p,
}
bool ProfileSyncServiceTestHarness::SetupSync() {
- service_ = profile_->GetProfileSyncService();
- service_->StartUp();
+ service_ = profile_->GetProfileSyncService("");
service_->AddObserver(this);
- return WaitForServiceInit(false);
-}
+ service_->signin_.StartSignIn(username_, password_, "", "");
-bool ProfileSyncServiceTestHarness::RetryAuthentication() {
- wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED;
- return WaitForServiceInit(true);
+ return WaitForServiceInit();
}
void ProfileSyncServiceTestHarness::SignalStateCompleteWithNextState(
@@ -121,11 +120,6 @@ bool ProfileSyncServiceTestHarness::RunStateChangeMachine() {
WaitState state = wait_state_;
ProfileSyncService::Status status(service_->QueryDetailedSyncStatus());
switch (wait_state_) {
- case WAITING_FOR_ON_AUTH_ERROR: {
- LogClientInfo("WAITING_FOR_ON_AUTH_ERROR");
- SignalStateCompleteWithNextState(WAITING_FOR_ON_BACKEND_INITIALIZED);
- break;
- }
case WAITING_FOR_ON_BACKEND_INITIALIZED: {
LogClientInfo("WAITING_FOR_ON_BACKEND_INITIALIZED");
if (service_->GetAuthError().state() != GoogleServiceAuthError::NONE) {
@@ -143,6 +137,21 @@ bool ProfileSyncServiceTestHarness::RunStateChangeMachine() {
}
break;
}
+ case WAITING_FOR_SERVER_REACHABLE: {
+ LogClientInfo("WAITING_FOR_SERVER_REACHABLE");
+ const SyncSessionSnapshot* snap = GetLastSessionSnapshot();
+ if (!status.server_reachable) {
+ break;
+ }
+ if (service()->backend()->HasUnsyncedItems() ||
+ snap->has_more_to_sync || snap->unsynced_count != 0) {
+ SignalStateCompleteWithNextState(WAITING_FOR_SYNC_TO_FINISH);
+ break;
+ }
+ last_timestamp_ = snap->max_local_timestamp;
+ SignalStateCompleteWithNextState(FULLY_SYNCED);
+ break;
+ }
case WAITING_FOR_SYNC_TO_FINISH: {
LogClientInfo("WAITING_FOR_SYNC_TO_FINISH");
const SyncSessionSnapshot* snap = GetLastSessionSnapshot();
@@ -151,7 +160,10 @@ bool ProfileSyncServiceTestHarness::RunStateChangeMachine() {
// be a sufficient condition for sync to have completed. However, the
// additional check of snap->unsynced_count is required due to
// http://crbug.com/48989.
- if (snap->has_more_to_sync || snap->unsynced_count != 0) {
+ if (service()->backend()->HasUnsyncedItems() ||
+ snap->has_more_to_sync || snap->unsynced_count != 0) {
+ if (!status.server_reachable)
+ SignalStateCompleteWithNextState(WAITING_FOR_SERVER_REACHABLE);
break;
}
EXPECT_LE(last_timestamp_, snap->max_local_timestamp);
@@ -286,18 +298,10 @@ bool ProfileSyncServiceTestHarness::AwaitStatusChangeWithTimeout(
return timeout_signal->Abort();
}
-bool ProfileSyncServiceTestHarness::WaitForServiceInit(bool is_auth_retry) {
+bool ProfileSyncServiceTestHarness::WaitForServiceInit() {
LogClientInfo("WaitForServiceInit");
- if (!is_auth_retry) {
- // Wait for the OnAuthError() callback.
- EXPECT_EQ(wait_state_, WAITING_FOR_ON_AUTH_ERROR);
- EXPECT_TRUE(AwaitStatusChangeWithTimeout(30,
- "Waiting for the OnAuthError() callback.")) <<
- "OnAuthError() not seen after 30 seconds.";
- }
- // Enter GAIA credentials and wait for the OnBackendInitialized() callback.
- service_->backend()->Authenticate(username_, password_, std::string());
+ // Wait for the OnBackendInitialized() callback.
EXPECT_EQ(wait_state_, WAITING_FOR_ON_BACKEND_INITIALIZED);
EXPECT_TRUE(AwaitStatusChangeWithTimeout(30,
"Waiting for OnBackendInitialized().")) <<
@@ -307,15 +311,13 @@ bool ProfileSyncServiceTestHarness::WaitForServiceInit(bool is_auth_retry) {
return false;
}
- // Choose datatypes to be synced. Note: This is unnecessary on Chrome OS.
- if (!browser_defaults::kBootstrapSyncAuthentication) {
- syncable::ModelTypeSet set;
- for (int i = syncable::FIRST_REAL_MODEL_TYPE;
- i < syncable::MODEL_TYPE_COUNT; ++i) {
- set.insert(syncable::ModelTypeFromInt(i));
- }
- service_->OnUserChoseDatatypes(true, set);
+ // Choose datatypes to be synced.
+ syncable::ModelTypeSet set;
+ for (int i = syncable::FIRST_REAL_MODEL_TYPE;
+ i < syncable::MODEL_TYPE_COUNT; ++i) {
+ set.insert(syncable::ModelTypeFromInt(i));
}
+ service_->OnUserChoseDatatypes(true, set);
// Wait for notifications_enabled to be set to true.
EXPECT_EQ(wait_state_, WAITING_FOR_NOTIFICATIONS_ENABLED);
@@ -329,7 +331,10 @@ bool ProfileSyncServiceTestHarness::WaitForServiceInit(bool is_auth_retry) {
const SyncSessionSnapshot*
ProfileSyncServiceTestHarness::GetLastSessionSnapshot() const {
EXPECT_FALSE(service_ == NULL) << "Sync service has not yet been set up.";
- return service_->backend()->GetLastSessionSnapshot();
+ if (service_->backend()) {
+ return service_->backend()->GetLastSessionSnapshot();
+ }
+ return NULL;
}
void ProfileSyncServiceTestHarness::LogClientInfo(std::string message) {
diff --git a/chrome/test/live_sync/profile_sync_service_test_harness.h b/chrome/test/live_sync/profile_sync_service_test_harness.h
index 3b32930..34cfde3 100644
--- a/chrome/test/live_sync/profile_sync_service_test_harness.h
+++ b/chrome/test/live_sync/profile_sync_service_test_harness.h
@@ -31,10 +31,6 @@ class ProfileSyncServiceTestHarness : public ProfileSyncServiceObserver {
// authenticated, and we are ready to process changes.
bool SetupSync();
- // Retries a sync setup when the previous attempt was aborted by an
- // authentication failure.
- bool RetryAuthentication();
-
// ProfileSyncServiceObserver implementation.
virtual void OnStateChanged();
@@ -79,16 +75,16 @@ class ProfileSyncServiceTestHarness : public ProfileSyncServiceObserver {
friend class StateChangeTimeoutEvent;
enum WaitState {
- // The sync client awaits the OnAuthError() callback.
- WAITING_FOR_ON_AUTH_ERROR = 0,
// The sync client awaits the OnBackendInitialized() callback.
- WAITING_FOR_ON_BACKEND_INITIALIZED,
+ WAITING_FOR_ON_BACKEND_INITIALIZED = 0,
// The sync client is waiting for notifications_enabled to become true.
WAITING_FOR_NOTIFICATIONS_ENABLED,
// The sync client is waiting for an ongoing sync cycle to complete.
WAITING_FOR_SYNC_TO_FINISH,
// The sync client anticipates incoming updates leading to a new sync cycle.
WAITING_FOR_UPDATES,
+ // The sync client is waiting for server_reachable to become true.
+ WAITING_FOR_SERVER_REACHABLE,
// The sync client is fully synced and there are no pending updates.
FULLY_SYNCED,
// An authentication error has occurred.
@@ -110,7 +106,7 @@ class ProfileSyncServiceTestHarness : public ProfileSyncServiceObserver {
// Returns true if the service initialized correctly. Set is_auth_retry to
// true when calling this method second time after an authentication failure.
- bool WaitForServiceInit(bool is_auth_retry);
+ bool WaitForServiceInit();
// Logs message with relevant info about client's sync state (if available).
void LogClientInfo(std::string message);
diff --git a/chrome/test/live_sync/single_client_live_bookmarks_sync_test.cc b/chrome/test/live_sync/single_client_live_bookmarks_sync_test.cc
index c4cc585..bc66917 100644
--- a/chrome/test/live_sync/single_client_live_bookmarks_sync_test.cc
+++ b/chrome/test/live_sync/single_client_live_bookmarks_sync_test.cc
@@ -4,6 +4,37 @@
#include "chrome/test/live_sync/live_bookmarks_sync_test.h"
+// TODO(rsimha): Debug the flakiness of this with fred. http://crbug.com/53858
+IN_PROC_BROWSER_TEST_F(SingleClientLiveBookmarksSyncTest,
+ FAILS_OfflineToOnline) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ DisableNetwork(GetProfile(0));
+
+ BookmarkModel* bm = GetBookmarkModel(0);
+ BookmarkModelVerifier* v = verifier_helper();
+
+ const BookmarkNode* top = v->AddGroup(bm, bm->other_node(), 0, L"top");
+ v->SetTitle(bm, top, L"title");
+
+
+ EXPECT_TRUE(GetClient(0)->AwaitSyncCycleCompletion("Offline state change."));
+ {
+ ProfileSyncService::Status status(
+ GetClient(0)->service()->QueryDetailedSyncStatus());
+ EXPECT_EQ(status.summary, ProfileSyncService::Status::OFFLINE_UNSYNCED);
+ }
+
+ EnableNetwork(GetProfile(0));
+ {
+ EXPECT_TRUE(GetClient(0)->AwaitSyncCycleCompletion("Commit changes."));
+ ProfileSyncService::Status status(
+ GetClient(0)->service()->QueryDetailedSyncStatus());
+ EXPECT_EQ(status.summary, ProfileSyncService::Status::READY);
+ v->ExpectMatch(bm);
+ }
+}
+
IN_PROC_BROWSER_TEST_F(SingleClientLiveBookmarksSyncTest, Sanity) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
BookmarkModel* bm = GetBookmarkModel(0);
diff --git a/chrome/test/profile_mock.h b/chrome/test/profile_mock.h
index 67f7ee2..b3b0dcf 100644
--- a/chrome/test/profile_mock.h
+++ b/chrome/test/profile_mock.h
@@ -18,6 +18,7 @@ class ProfileMock : public TestingProfile {
MOCK_METHOD1(GetWebDataService, WebDataService*(ServiceAccessType access));
MOCK_METHOD0(GetPersonalDataManager, PersonalDataManager*());
MOCK_METHOD1(GetPasswordStore, PasswordStore* (ServiceAccessType access));
+ MOCK_METHOD0(GetTokenService, TokenService*());
};
#endif // CHROME_TEST_PROFILE_MOCK_H__
diff --git a/chrome/test/sync/engine/mock_connection_manager.cc b/chrome/test/sync/engine/mock_connection_manager.cc
index bfba668..24ad1f2 100644
--- a/chrome/test/sync/engine/mock_connection_manager.cc
+++ b/chrome/test/sync/engine/mock_connection_manager.cc
@@ -33,7 +33,7 @@ using syncable::WriteTransaction;
MockConnectionManager::MockConnectionManager(DirectoryManager* dirmgr,
const string& name)
- : ServerConnectionManager("unused", 0, false, "version", "id"),
+ : ServerConnectionManager("unused", 0, false, "version"),
conflict_all_commits_(false),
conflict_n_commits_(0),
next_new_id_(10000),
diff --git a/chrome/test/sync/engine/syncer_command_test.h b/chrome/test/sync/engine/syncer_command_test.h
index eed8def..02ea57d 100644
--- a/chrome/test/sync/engine/syncer_command_test.h
+++ b/chrome/test/sync/engine/syncer_command_test.h
@@ -48,6 +48,9 @@ class SyncerCommandTestWithParam : public testing::TestWithParam<T>,
virtual void OnShouldStopSyncingPermanently() {
FAIL() << "Shouldn't be forced to stop syncing.";
}
+ virtual void SignalUpdatedToken(const std::string& token) {
+ FAIL() << "Should never update token.";
+ }
// ModelSafeWorkerRegistrar implementation.
virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {
@@ -91,7 +94,7 @@ class SyncerCommandTestWithParam : public testing::TestWithParam<T>,
void ResetContext() {
context_.reset(new sessions::SyncSessionContext(
- mock_server_.get(), NULL, syncdb_->manager(), registrar()));
+ mock_server_.get(), syncdb_->manager(), registrar()));
context_->set_account_name(syncdb_->name());
ClearSession();
}
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index c6ad9b3..6fd04fc 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -453,6 +453,11 @@ TokenService* TestingProfile::GetTokenService() {
}
ProfileSyncService* TestingProfile::GetProfileSyncService() {
+ return GetProfileSyncService("");
+}
+
+ProfileSyncService* TestingProfile::GetProfileSyncService(
+ const std::string& cros_user) {
if (!profile_sync_service_.get()) {
// Use a NiceMock here since we are really using the mock as a
// fake. Test cases that want to set expectations on a
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index 6399692..d75b7c1 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -224,6 +224,7 @@ class TestingProfile : public Profile {
virtual void InitExtensions() {}
virtual void InitWebResources() {}
virtual NTPResourceCache* GetNTPResourceCache();
+
virtual DesktopNotificationService* GetDesktopNotificationService();
virtual BackgroundContentsService* GetBackgroundContentsService() {
return NULL;
@@ -252,6 +253,8 @@ class TestingProfile : public Profile {
// Creates and initializes a profile sync service if the tests require one.
virtual TokenService* GetTokenService();
virtual ProfileSyncService* GetProfileSyncService();
+ virtual ProfileSyncService* GetProfileSyncService(
+ const std::string& cros_notes);
virtual CloudPrintProxyService* GetCloudPrintProxyService() { return NULL; }
virtual ChromeBlobStorageContext* GetBlobStorageContext() {