summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-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
65 files changed, 1941 insertions, 1165 deletions
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index c371880..9ec92d02 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -181,10 +181,6 @@ 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 58df847..a2ab751 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_->ShowLoginDialog(NULL);
+ syncService_->EnableForUser(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 3ecd267..6970816 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_->ShowLoginDialog(NULL);
+ sync_service_->EnableForUser(NULL);
}
}
diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc
index 9d6d72b..13b2cea 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_->ShowLoginDialog(NULL);
+ sync_service_->EnableForUser(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 b61ab62..b46868f 100644
--- a/chrome/browser/net/gaia/token_service.cc
+++ b/chrome/browser/net/gaia/token_service.cc
@@ -13,8 +13,6 @@
#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()
@@ -31,18 +29,12 @@ 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() {
@@ -155,12 +147,6 @@ 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));
@@ -192,11 +178,6 @@ 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.
@@ -226,12 +207,3 @@ 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 006423f..20ca12d 100644
--- a/chrome/browser/net/gaia/token_service.h
+++ b/chrome/browser/net/gaia/token_service.h
@@ -37,15 +37,12 @@
#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 "chrome/common/notification_observer.h"
-#include "chrome/common/notification_registrar.h"
+#include "base/gtest_prod_util.h"
class URLRequestContextGetter;
class Profile;
@@ -53,8 +50,7 @@ class Profile;
// The TokenService is a Profile member, so all calls are expected
// from the UI thread.
class TokenService : public GaiaAuthConsumer,
- public WebDataServiceConsumer,
- public NotificationObserver {
+ public WebDataServiceConsumer {
public:
TokenService();
virtual ~TokenService();
@@ -127,10 +123,6 @@ 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);
@@ -141,11 +133,6 @@ 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,
@@ -182,8 +169,6 @@ 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 ce0096b..512efff 100644
--- a/chrome/browser/net/gaia/token_service_unittest.cc
+++ b/chrome/browser/net/gaia/token_service_unittest.cc
@@ -4,18 +4,127 @@
//
// This file defines a unit test for the profile's token service.
-#include "chrome/browser/net/gaia/token_service_unittest.h"
-
+#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/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();
+ }
+ }
-class TokenServiceTest : public TokenServiceTestHarness {
+ TokenService::TokenRequestFailedDetails details_;
+};
+
+class TokenServiceTest : public testing::Test {
public:
+ TokenServiceTest()
+ : ui_thread_(ChromeThread::UI, &message_loop_),
+ db_thread_(ChromeThread::DB) {
+ }
+
virtual void SetUp() {
- TokenServiceTestHarness::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());
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) {
@@ -36,7 +145,8 @@ TEST_F(TokenServiceTest, NotificationSuccess) {
EXPECT_EQ(1U, success_tracker_.size());
EXPECT_EQ(0U, failure_tracker_.size());
- TokenService::TokenAvailableDetails details = success_tracker_.details();
+ TokenService::TokenAvailableDetails details =
+ success_tracker_.get_last_token_details();
// MSVC doesn't like this comparison as EQ.
EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
EXPECT_EQ(details.token(), "token");
@@ -50,7 +160,8 @@ TEST_F(TokenServiceTest, NotificationFailed) {
EXPECT_EQ(0U, success_tracker_.size());
EXPECT_EQ(1U, failure_tracker_.size());
- TokenService::TokenRequestFailedDetails details = failure_tracker_.details();
+ TokenService::TokenRequestFailedDetails details =
+ failure_tracker_.get_last_token_details();
// MSVC doesn't like this comparison as EQ.
EXPECT_TRUE(details.service() == GaiaConstants::kSyncService);
@@ -164,7 +275,8 @@ TEST_F(TokenServiceTest, LoadTokensIntoMemoryBasic) {
service_.LoadTokensIntoMemory(db_tokens, &memory_tokens);
EXPECT_EQ(1U, success_tracker_.size());
- TokenService::TokenAvailableDetails details = success_tracker_.details();
+ TokenService::TokenAvailableDetails details =
+ success_tracker_.get_last_token_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
deleted file mode 100644
index ad46138..0000000
--- a/chrome/browser/net/gaia/token_service_unittest.h
+++ /dev/null
@@ -1,130 +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.
-//
-// 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 075cbf1..2b37c26 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -42,7 +42,6 @@
#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"
@@ -140,7 +139,6 @@ 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 b2d7eba..5c3669c 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -444,11 +444,6 @@ 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 68eec93..d876d8c 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -377,11 +377,6 @@ 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 ff6a8da..6a7cb51 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -479,7 +479,6 @@ 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
@@ -1236,16 +1235,10 @@ 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(cros_user);
+ InitSyncService();
return sync_service_.get();
}
@@ -1255,11 +1248,11 @@ CloudPrintProxyService* ProfileImpl::GetCloudPrintProxyService() {
return cloud_print_proxy_service_.get();
}
-void ProfileImpl::InitSyncService(const std::string& cros_user) {
+void ProfileImpl::InitSyncService() {
profile_sync_factory_.reset(
new ProfileSyncFactoryImpl(this, CommandLine::ForCurrentProcess()));
sync_service_.reset(
- profile_sync_factory_->CreateProfileSyncService(cros_user));
+ profile_sync_factory_->CreateProfileSyncService());
sync_service_->Initialize();
}
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index 79e4438..d3831cb 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -100,10 +100,8 @@ 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(const std::string& cros_user);
+ void InitSyncService();
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 73d59ef..7f81ca2 100644
--- a/chrome/browser/sync/abstract_profile_sync_service_test.h
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.h
@@ -12,7 +12,6 @@
#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"
@@ -56,7 +55,7 @@ class ProfileSyncServiceTestHelper {
UserShare* user_share = service->backend()->GetUserShareHandle();
DirectoryManager* dir_manager = user_share->dir_manager.get();
- ScopedDirLookup dir(dir_manager, user_share->name);
+ ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
if (!dir.good())
return false;
@@ -121,7 +120,6 @@ 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 72e1f6d..178fe7f 100644
--- a/chrome/browser/sync/engine/all_status.cc
+++ b/chrome/browser/sync/engine/all_status.cc
@@ -8,6 +8,7 @@
#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"
@@ -47,6 +48,11 @@ 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));
@@ -93,6 +99,10 @@ 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;
@@ -143,6 +153,34 @@ 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) {
@@ -184,15 +222,6 @@ 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 b843a1a..772f40d 100644
--- a/chrome/browser/sync/engine/all_status.h
+++ b/chrome/browser/sync/engine/all_status.h
@@ -89,6 +89,7 @@ class AllStatus : public ChannelEventHandler<SyncerEvent> {
AllStatus();
~AllStatus();
+ void WatchConnectionManager(ServerConnectionManager* conn_mgr);
void HandleServerConnectionEvent(const ServerConnectionEvent& event);
void HandleAuthWatcherEvent(const AuthWatcherEvent& event);
@@ -115,6 +116,7 @@ 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;
@@ -123,6 +125,7 @@ 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
new file mode 100644
index 0000000..b414e18
--- /dev/null
+++ b/chrome/browser/sync/engine/auth_watcher.cc
@@ -0,0 +1,352 @@
+// 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
new file mode 100644
index 0000000..da90f95
--- /dev/null
+++ b/chrome/browser/sync/engine/auth_watcher.h
@@ -0,0 +1,222 @@
+// 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
new file mode 100644
index 0000000..cc840c7
--- /dev/null
+++ b/chrome/browser/sync/engine/auth_watcher_unittest.cc
@@ -0,0 +1,235 @@
+// 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
new file mode 100644
index 0000000..eec7af3
--- /dev/null
+++ b/chrome/browser/sync/engine/authenticator.cc
@@ -0,0 +1,110 @@
+// 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
new file mode 100644
index 0000000..1abca3c
--- /dev/null
+++ b/chrome/browser/sync/engine/authenticator.h
@@ -0,0 +1,105 @@
+// 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 6d35811..4953836 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.cc
+++ b/chrome/browser/sync/engine/net/server_connection_manager.cc
@@ -135,9 +135,11 @@ ServerConnectionManager::ServerConnectionManager(
const string& server,
int port,
bool use_ssl,
- const string& user_agent)
+ const string& user_agent,
+ const string& client_id)
: sync_server_(server),
sync_server_port_(port),
+ client_id_(client_id),
user_agent_(user_agent),
use_ssl_(use_ssl),
proto_sync_path_(kSyncServerSyncPath),
@@ -161,6 +163,7 @@ void ServerConnectionManager::NotifyStatusChanged() {
channel_->NotifyListeners(event);
}
+// Uses currently set auth token. Set by AuthWatcher.
bool ServerConnectionManager::PostBufferWithCachedAuth(
const PostBufferParams* params, ScopedServerStatusWatcher* watcher) {
string path =
@@ -168,6 +171,14 @@ 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 526dc8e..602116a 100644
--- a/chrome/browser/sync/engine/net/server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/server_connection_manager.h
@@ -213,7 +213,8 @@ class ServerConnectionManager {
ServerConnectionManager(const std::string& server,
int port,
bool use_ssl,
- const std::string& user_agent);
+ const std::string& user_agent,
+ const std::string& client_id);
virtual ~ServerConnectionManager();
@@ -224,6 +225,14 @@ 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);
@@ -280,11 +289,6 @@ 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_);
@@ -329,7 +333,7 @@ class ServerConnectionManager {
int sync_server_port_;
// The unique id of the user's client.
- std::string client_id_;
+ const 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 4108f9a..67424b9 100644
--- a/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h
+++ b/chrome/browser/sync/engine/net/syncapi_server_connection_manager.h
@@ -51,8 +51,10 @@ 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),
+ : ServerConnectionManager(server, port, use_ssl, client_version,
+ client_id),
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 15e0e8d..00d1c4f 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -25,6 +25,7 @@
#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"
@@ -48,6 +49,7 @@
#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"
@@ -59,15 +61,17 @@
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;
@@ -906,6 +910,7 @@ 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),
@@ -924,25 +929,40 @@ 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 SyncCredentials& credentials,
+ const std::string& lsid,
const bool use_chrome_async_socket,
const bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
const std::string& restored_key_for_bootstrapping);
-
- // 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 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);
// Tell the sync engine to start the syncing process.
void StartSyncing();
@@ -967,17 +987,20 @@ class SyncManager::SyncInternal
// This listener is called by the syncer channel for all syncer events.
virtual void HandleChannelEvent(const SyncerEvent& event);
- // Listens for notifications from the ServerConnectionManager
- void HandleServerConnectionEvent(const ServerConnectionEvent& 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);
- // Open the directory named with username_for_share
- bool OpenDirectory();
+ // Listen here for directory opened events.
+ void HandleDirectoryManagerEvent(
+ const syncable::DirectoryManagerEvent& event);
// 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);
@@ -993,13 +1016,14 @@ 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_.name;
+ return share_.authenticated_name;
}
// Note about SyncManager::Status implementation: Status is a trimmed
@@ -1054,6 +1078,21 @@ 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();
@@ -1132,6 +1171,10 @@ 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.
@@ -1152,6 +1195,13 @@ 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
@@ -1163,12 +1213,20 @@ 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_;
@@ -1203,11 +1261,17 @@ 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 SyncCredentials& credentials,
+ const char* lsid,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -1218,22 +1282,29 @@ 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,
- credentials,
+ lsid,
use_chrome_async_socket,
try_ssltcp_first,
notification_method,
restored_key_for_bootstrapping);
}
-void SyncManager::UpdateCredentials(const SyncCredentials& credentials) {
- data_->UpdateCredentials(credentials);
+void SyncManager::Authenticate(const char* username, const char* password,
+ const char* captcha) {
+ data_->Authenticate(std::string(username), std::string(password),
+ std::string(captcha));
}
-
bool SyncManager::InitialSyncEndedForAllEnabledTypes() {
return data_->InitialSyncEndedForAllEnabledTypes();
}
@@ -1258,7 +1329,6 @@ 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();
@@ -1268,11 +1338,17 @@ 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 SyncCredentials& credentials,
+ const std::string& lsid,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -1283,16 +1359,32 @@ 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, post_factory));
+ sync_server_and_path, port, use_ssl, user_agent, client_id,
+ post_factory));
- connection_manager_hookup_.reset(
- NewEventListenerHookup(connection_manager()->channel(), this,
- &SyncManager::SyncInternal::HandleServerConnectionEvent));
+ // Watch various objects for aggregated status.
+ allstatus_.WatchConnectionManager(connection_manager());
net::NetworkChangeNotifier::AddObserver(this);
// TODO(akalin): CheckServerReachable() can block, which may cause jank if we
@@ -1312,7 +1404,7 @@ bool SyncManager::SyncInternal::Init(
const bool kInitializeSsl = true;
const bool kConnectImmediately = false;
talk_mediator_.reset(new TalkMediatorImpl(mediator_thread, kInitializeSsl,
- kConnectImmediately, false));
+ kConnectImmediately, invalidate_xmpp_auth_token));
if (notification_method != browser_sync::NOTIFICATION_LEGACY &&
notification_method != browser_sync::NOTIFICATION_SERVER) {
if (notification_method == browser_sync::NOTIFICATION_TRANSITIONAL) {
@@ -1325,11 +1417,30 @@ bool SyncManager::SyncInternal::Init(
// Listen to TalkMediator events ourselves
talk_mediator_->SetDelegate(this);
- LOG(INFO) << "Sync is bringing up SyncSessionContext.";
+ 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));
// Build a SyncSessionContext and store the worker in it.
SyncSessionContext* context = new SyncSessionContext(
- connection_manager_.get(), dir_manager(), model_safe_worker_registrar);
+ connection_manager_.get(), auth_watcher(),
+ dir_manager(), model_safe_worker_registrar);
// The SyncerThread takes ownership of |context|.
syncer_thread_ = new SyncerThread(context);
@@ -1338,7 +1449,22 @@ bool SyncManager::SyncInternal::Init(
// Subscribe to the syncer thread's channel.
syncer_event_.reset(syncer_thread()->relay_channel()->AddObserver(this));
- return SignIn(credentials);
+ 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;
}
void SyncManager::SyncInternal::StartSyncing() {
@@ -1410,62 +1536,53 @@ void SyncManager::SyncInternal::SendPendingXMPPNotification(
}
}
-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;
+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();
}
+ auth_watcher()->Authenticate(username, password, std::string(),
+ captcha);
+}
- connection_manager()->set_client_id(lookup->cache_guid());
- syncer_thread()->CreateSyncer(username_for_share());
- MarkAndNotifyInitializationComplete();
- dir_change_hookup_.reset(lookup->AddChangeObserver(this));
- return true;
+void SyncManager::SyncInternal::AuthenticateWithLsid(const string& lsid) {
+ DCHECK(!lsid.empty());
+ auth_watcher()->AuthenticateWithLsid(lsid);
}
-bool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) {
- DCHECK_EQ(MessageLoop::current(), core_message_loop_);
- DCHECK(share_.name.empty());
- share_.name = credentials.email;
+bool SyncManager::SyncInternal::AuthenticateForUser(
+ const std::string& username, const std::string& auth_token) {
+ share_.authenticated_name = username;
- LOG(INFO) << "Signing in user: " << username_for_share();
- if (!OpenDirectory()) {
+ // 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();
return false;
}
- UpdateCredentials(credentials);
+ // 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);
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() {
- if (observer_) {
- observer_->OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS));
- }
+ auth_problem_ = AuthError::INVALID_GAIA_CREDENTIALS;
+ if (observer_)
+ observer_->OnAuthError(AuthError(auth_problem_));
}
void SyncManager::SyncInternal::SetPassphrase(
@@ -1525,6 +1642,15 @@ 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...";
@@ -1533,6 +1659,15 @@ 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.";
@@ -1544,7 +1679,7 @@ void SyncManager::SyncInternal::Shutdown() {
// Pump any messages the auth watcher, syncer thread, or talk
// mediator posted before they shut down. (See HandleSyncerEvent(),
- // and HandleTalkMediatorEvent() for the
+ // HandleAuthWatcherEvent(), and HandleTalkMediatorEvent() for the
// events that may be posted.)
{
CHECK(core_message_loop_);
@@ -1556,8 +1691,6 @@ void SyncManager::SyncInternal::Shutdown() {
net::NetworkChangeNotifier::RemoveObserver(this);
- connection_manager_hookup_.reset();
-
if (dir_manager()) {
dir_manager()->FinalSaveChangesForAll();
dir_manager()->Close(username_for_share());
@@ -1566,6 +1699,7 @@ 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();
@@ -1578,7 +1712,22 @@ 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();
- sync_manager_->RequestNudge();
+}
+
+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();
+ }
}
// Listen to model changes, filter out ones initiated by the sync API, and
@@ -1601,25 +1750,6 @@ 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
@@ -1851,11 +1981,105 @@ void SyncManager::SyncInternal::HandleChannelEvent(const SyncerEvent& event) {
observer_->OnStopSyncingPermanently();
return;
}
+}
- if (event.what_happened == SyncerEvent::UPDATED_TOKEN) {
- observer_->OnUpdatedToken(event.updated_token);
+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)
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(
@@ -1897,8 +2121,8 @@ void SyncManager::SyncInternal::TalkMediatorLogin(
<< "(talk_mediator_ is NULL)";
return;
}
- LOG(INFO) << "P2P: Trying talk mediator login.";
-
+ // TODO(akalin): Make talk_mediator automatically login on
+ // auth token change.
talk_mediator_->SetAuthToken(email, token, SYNC_SERVICE_NAME);
talk_mediator_->Login();
}
@@ -1960,7 +2184,7 @@ void SyncManager::SetupForTestMode(const std::wstring& test_username) {
void SyncManager::SyncInternal::SetupForTestMode(
const std::wstring& test_username) {
- share_.name = WideToUTF8(test_username);
+ share_.authenticated_name = WideToUTF8(test_username);
// Some tests are targeting only local db operations & integrity, and don't
// want syncer thread interference.
@@ -1968,8 +2192,18 @@ 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));
}
}
@@ -1979,7 +2213,7 @@ BaseTransaction::BaseTransaction(UserShare* share)
: lookup_(NULL) {
DCHECK(share && share->dir_manager.get());
lookup_ = new syncable::ScopedDirLookup(share->dir_manager.get(),
- share->name);
+ share->authenticated_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 16f8bd9..e4e8510 100644
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -107,14 +107,12 @@ struct UserShare {
// be shared across multiple threads (unlike Directory).
scoped_ptr<syncable::DirectoryManager> dir_manager;
- // 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;
+ // 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;
};
// A valid BaseNode will never have an ID of zero.
@@ -671,9 +669,6 @@ 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;
@@ -720,22 +715,52 @@ 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 SyncCredentials& credentials,
+ const char* lsid,
bool use_chrome_async_socket,
bool try_ssltcp_first,
browser_sync::NotificationMethod notification_method,
@@ -751,11 +776,15 @@ class SyncManager {
// called.
bool InitialSyncEndedForAllEnabledTypes();
- // 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);
+ // 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);
// Start the SyncerThread.
void StartSyncing();
diff --git a/chrome/browser/sync/engine/syncapi_unittest.cc b/chrome/browser/sync/engine/syncapi_unittest.cc
index b83c501..a77134b 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_.name = setter_upper_.name();
+ share_.authenticated_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 2cc2300..17de218 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,
- sessions::SyncSession* session,
+ AuthWatcher* auth_watcher,
const ClientToServerMessage& msg,
ClientToServerResponse* response) {
@@ -144,9 +144,12 @@ bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
std::string new_token =
http_response.update_client_auth_header;
if (!new_token.empty()) {
- SyncerEvent event(SyncerEvent::UPDATED_TOKEN);
- event.updated_token = new_token;
- session->context()->syncer_event_channel()->Notify(event);
+ // 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);
}
if (response->ParseFromString(rx)) {
@@ -186,7 +189,7 @@ bool SyncerProtoUtil::PostClientToServerMessage(
}
if (!PostAndProcessHeaders(session->context()->connection_manager(),
- session,
+ session->context()->auth_watcher(),
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 ca68ec3..39fcc5c 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,
- sessions::SyncSession* session,
+ browser_sync::AuthWatcher* authwatcher,
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 57cae0a..e6eb68b 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"),
+ : ServerConnectionManager("unused", 0, false, "version", "id"),
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 9f369ed8..800ddddb 100644
--- a/chrome/browser/sync/engine/syncer_thread.cc
+++ b/chrome/browser/sync/engine/syncer_thread.cc
@@ -17,10 +17,12 @@
#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"
@@ -73,12 +75,19 @@ 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());
@@ -89,6 +98,7 @@ 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());
@@ -577,18 +587,22 @@ void SyncerThread::HandleChannelEvent(const SyncerEvent& event) {
NudgeSyncImpl(event.nudge_delay_milliseconds, kUnknown);
}
-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();
+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();
+ }
}
// 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 158d759..8c71db4 100644
--- a/chrome/browser/sync/engine/syncer_thread.h
+++ b/chrome/browser/sync/engine/syncer_thread.h
@@ -29,6 +29,11 @@
class EventListenerHookup;
+namespace syncable {
+class DirectoryManager;
+struct DirectoryManagerEvent;
+}
+
namespace browser_sync {
class ModelSafeWorker;
@@ -133,9 +138,6 @@ 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);
@@ -228,6 +230,8 @@ 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.
@@ -319,6 +323,7 @@ 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 ded07f0..16328bd 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(),
- metadb_.manager(), this);
+ NULL, 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);
+ SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL, NULL);
scoped_refptr<SyncerThread> syncer_thread(new SyncerThread(context));
}
TEST_F(SyncerThreadTest, StartStop) {
- SyncSessionContext* context = new SyncSessionContext(NULL, NULL, NULL);
+ SyncSessionContext* context = new SyncSessionContext(NULL, 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);
+ SyncSessionContext* context = new SyncSessionContext(NULL, 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);
+ SyncSessionContext* context = new SyncSessionContext(NULL, 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,7 +673,6 @@ 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);
@@ -698,7 +697,6 @@ 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);
@@ -752,7 +750,6 @@ 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");
@@ -768,7 +765,6 @@ 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));
@@ -830,7 +826,6 @@ 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.
@@ -874,7 +869,6 @@ 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.
@@ -929,8 +923,6 @@ 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_));
@@ -1002,7 +994,6 @@ 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 0805c89..19be54e 100644
--- a/chrome/browser/sync/engine/syncer_types.h
+++ b/chrome/browser/sync/engine/syncer_types.h
@@ -78,8 +78,6 @@ 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,
@@ -145,9 +143,6 @@ 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 74e5122..0d9ab8e 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(),
+ context_.reset(new SyncSessionContext(mock_server_.get(), NULL,
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 c4e0963..b570c4f 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -10,7 +10,6 @@
#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"
@@ -22,25 +21,24 @@
#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,
@@ -77,8 +75,10 @@ void SyncBackendHost::Initialize(
const GURL& sync_service_url,
const syncable::ModelTypeSet& types,
URLRequestContextGetter* baseline_context_getter,
- const SyncCredentials& credentials,
+ const std::string& lsid,
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,10 +110,13 @@ void SyncBackendHost::Initialize(
}
InitCore(Core::DoInitializeOptions(
- sync_service_url,
+ sync_service_url, lsid.empty(),
MakeHttpBridgeFactory(baseline_context_getter),
- credentials,
+ MakeHttpBridgeFactory(baseline_context_getter),
+ lsid,
delete_sync_data_folder,
+ invalidate_sync_login,
+ invalidate_sync_xmpp_login,
use_chrome_async_socket,
try_ssltcp_first,
notification_method,
@@ -145,11 +148,12 @@ void SyncBackendHost::InitCore(const Core::DoInitializeOptions& options) {
options));
}
-void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) {
+void SyncBackendHost::Authenticate(const std::string& username,
+ const std::string& password,
+ const std::string& captcha) {
core_thread_.message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(core_.get(),
- &SyncBackendHost::Core::DoUpdateCredentials,
- credentials));
+ NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoAuthenticate,
+ username, password, captcha));
}
void SyncBackendHost::StartSyncingWithServer() {
@@ -340,15 +344,6 @@ 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();
@@ -437,9 +432,8 @@ 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.
@@ -451,11 +445,17 @@ 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.credentials,
+ options.lsid.c_str(),
options.use_chrome_async_socket,
options.try_ssltcp_first,
options.notification_method,
@@ -463,10 +463,11 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
DCHECK(success) << "Syncapi initialization failed!";
}
-void SyncBackendHost::Core::DoUpdateCredentials(
- const SyncCredentials& credentials) {
+void SyncBackendHost::Core::DoAuthenticate(const std::string& username,
+ const std::string& password,
+ const std::string& captcha) {
DCHECK(MessageLoop::current() == host_->core_thread_.message_loop());
- syncapi_->UpdateCredentials(credentials);
+ syncapi_->Authenticate(username.c_str(), password.c_str(), captcha.c_str());
}
void SyncBackendHost::Core::DoStartSyncing() {
@@ -623,7 +624,8 @@ bool SyncBackendHost::Core::IsCurrentThreadSafeForModel(
void SyncBackendHost::Core::OnAuthError(const AuthError& auth_error) {
- // Post to our core loop so we can modify state. Could be on another thread.
+ // We could be on SyncEngine_AuthWatcherThread. Post to our core loop so
+ // we can modify state.
host_->frontend_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &Core::HandleAuthErrorEventOnFrontendLoop,
auth_error));
@@ -658,11 +660,6 @@ 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 9e0a9f1..2b8680d 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -16,7 +16,6 @@
#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"
@@ -102,14 +101,17 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
void Initialize(const GURL& service_url,
const syncable::ModelTypeSet& types,
URLRequestContextGetter* baseline_context_getter,
- const sync_api::SyncCredentials& credentials,
+ const std::string& lsid,
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 from |frontend_loop| to update SyncCredentials.
- void UpdateCredentials(const sync_api::SyncCredentials& credentials);
+ // Called on |frontend_loop_| to kick off asynchronous authentication.
+ void Authenticate(const std::string& username, const std::string& password,
+ const std::string& captcha);
// This starts the SyncerThread running a Syncer object to communicate with
// sync servers. Until this is called, no changes will leave or enter this
@@ -206,22 +208,29 @@ 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,
- const sync_api::SyncCredentials& credentials,
+ sync_api::HttpPostProviderFactory* auth_http_bridge_factory,
+ const std::string& lsid,
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),
- credentials(credentials),
+ auth_http_bridge_factory(auth_http_bridge_factory),
+ lsid(lsid),
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),
@@ -230,7 +239,7 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
GURL service_url;
bool attempt_last_user_authentication;
sync_api::HttpPostProviderFactory* http_bridge_factory;
- sync_api::SyncCredentials credentials;
+ sync_api::HttpPostProviderFactory* auth_http_bridge_factory;
std::string lsid;
bool delete_sync_data_folder;
bool invalidate_sync_login;
@@ -251,9 +260,11 @@ 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 credential
- // update on behalf of SyncBackendHost::UpdateCredentials
- void DoUpdateCredentials(const sync_api::SyncCredentials& credentials);
+ // 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 the SyncBackendHost core_thread_ to tell the syncapi to start
// syncing (generally after initialization and authentication).
@@ -297,17 +308,14 @@ 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) {
- // 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);
+ DoInitialize(DoInitializeOptions(GURL(), false, factory, auth_factory,
+ std::string(), delete_sync_data_folder,
+ false, false, false, false,
+ notification_method, ""));
+ syncapi_->SetupForTestMode(test_user);
}
#endif
@@ -350,9 +358,6 @@ 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(
@@ -367,9 +372,6 @@ 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 a4a2550..1ca0473 100644
--- a/chrome/browser/sync/profile_sync_factory.h
+++ b/chrome/browser/sync/profile_sync_factory.h
@@ -6,9 +6,7 @@
#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"
@@ -50,8 +48,7 @@ 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(
- const std::string& cros_user) = 0;
+ virtual ProfileSyncService* CreateProfileSyncService() = 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 d6708cd..a5df306 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -76,11 +76,9 @@ ProfileSyncFactoryImpl::ProfileSyncFactoryImpl(Profile* profile,
command_line_(command_line) {
}
-ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService(
- const std::string& cros_user) {
-
+ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService() {
ProfileSyncService* pss = new ProfileSyncService(
- this, profile_, cros_user);
+ this, profile_, browser_defaults::kBootstrapSyncAuthentication);
// 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 233f3f1..ce535e5 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_factory_impl.h
@@ -6,8 +6,6 @@
#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"
@@ -20,8 +18,7 @@ class ProfileSyncFactoryImpl : public ProfileSyncFactory {
virtual ~ProfileSyncFactoryImpl() {}
// ProfileSyncFactory interface.
- virtual ProfileSyncService* CreateProfileSyncService(
- const std::string& cros_user);
+ virtual ProfileSyncService* CreateProfileSyncService();
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 26f47d1..908ccae 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 18cc30c..6c14d1e 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_METHOD1(CreateProfileSyncService,
- ProfileSyncService*(const std::string&));
+ MOCK_METHOD0(CreateProfileSyncService,
+ ProfileSyncService*(void));
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 567631d..5732ebf 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -30,10 +30,7 @@
#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"
@@ -47,7 +44,6 @@ using browser_sync::ChangeProcessor;
using browser_sync::DataTypeController;
using browser_sync::DataTypeManager;
using browser_sync::SyncBackendHost;
-using sync_api::SyncCredentials;
typedef GoogleServiceAuthError AuthError;
@@ -59,20 +55,20 @@ const char* ProfileSyncService::kDevServerUrl =
ProfileSyncService::ProfileSyncService(ProfileSyncFactory* factory,
Profile* profile,
- const std::string& cros_user)
+ bool bootstrap_sync_authentication)
: last_auth_error_(AuthError::None()),
factory_(factory),
profile_(profile),
- cros_user_(cros_user),
+ bootstrap_sync_authentication_(bootstrap_sync_authentication),
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)),
- token_migrator_(NULL) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)) {
DCHECK(factory);
DCHECK(profile);
registrar_.Add(this,
@@ -113,8 +109,10 @@ 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),
@@ -128,37 +126,6 @@ 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();
@@ -174,49 +141,24 @@ void ProfileSyncService::Initialize() {
return;
}
- RegisterAuthNotifications();
-
- // 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()) {
+ if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
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.
+
+ // 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();
}
- } 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();
- }
+ StartUp();
}
-
-}
-
-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(
@@ -290,7 +232,6 @@ 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.
@@ -328,29 +269,23 @@ 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(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.
+ // TODO(akalin): Gather all the command-line-controlled switches
+ // into an Options struct to make passing them down less annoying.
+ 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
@@ -359,17 +294,15 @@ 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(),
- credentials,
+ profile_->GetTokenService()->GetLsid(),
delete_sync_data_folder,
+ invalidate_sync_login,
+ invalidate_sync_xmpp_login,
use_chrome_async_socket_,
try_ssltcp_first,
notification_method_);
@@ -388,9 +321,7 @@ void ProfileSyncService::StartUp() {
return;
}
- DCHECK(AreCredentialsAvailable());
-
- LOG(INFO) << "ProfileSyncService bringing up backend host.";
+ LOG(INFO) << "ProfileSyncSerivce bringing up backend host.";
last_synced_time_ = base::Time::FromInternalValue(
profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
@@ -424,21 +355,31 @@ 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) << "Disabling sync for user.";
+ LOG(INFO) << "Clearing Sync DB.";
- // 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());
}
@@ -500,20 +441,29 @@ 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."
- << message;
+ LOG(ERROR) << "Unrecoverable error detected -- ProfileSyncService unusable.";
std::string location;
from_here.Write(true, true, &location);
LOG(ERROR) << location;
- // Shut all data types down.
- MessageLoop::current()->PostTask(FROM_HERE,
+ 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,
scoped_runnable_method_factory_.NewRunnableMethod(
&ProfileSyncService::Shutdown, true));
+ MessageLoop::current()->PostTask(FROM_HERE,
+ scoped_runnable_method_factory_.NewRunnableMethod(
+ &ProfileSyncService::StartUp));
+ }
}
void ProfileSyncService::OnBackendInitialized() {
@@ -522,12 +472,11 @@ 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 (!cros_user_.empty()) {
+ if (bootstrap_sync_authentication_) {
if (profile_->GetPrefs()->GetBoolean(prefs::kSyncSuppressStart)) {
ShowChooseDataTypes(NULL);
} else {
@@ -535,9 +484,8 @@ void ProfileSyncService::OnBackendInitialized() {
}
}
- if (HasSyncSetupCompleted()) {
+ if (HasSyncSetupCompleted())
ConfigureDataTypeManager();
- }
}
void ProfileSyncService::OnSyncCycleCompleted() {
@@ -545,16 +493,22 @@ void ProfileSyncService::OnSyncCycleCompleted() {
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
}
-void ProfileSyncService::UpdateAuthErrorState(
- const GoogleServiceAuthError& error) {
- last_auth_error_ = error;
+void ProfileSyncService::OnAuthError() {
+ last_auth_error_ = backend_->GetAuthError();
// 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()) {
+ if (WizardIsVisible() || expecting_first_run_auth_needed_event_) {
wizard_.Step(AuthError::NONE == last_auth_error_.state() ?
SyncSetupWizard::GAIA_SUCCESS : SyncSetupWizard::GAIA_LOGIN);
- } else {
+ }
+
+ if (expecting_first_run_auth_needed_event_) {
+ last_auth_error_ = AuthError::None();
+ expecting_first_run_auth_needed_event_ = false;
+ }
+
+ if (!WizardIsVisible()) {
auth_error_time_ == base::TimeTicks::Now();
}
@@ -569,10 +523,6 @@ void ProfileSyncService::UpdateAuthErrorState(
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);
@@ -583,12 +533,6 @@ 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;
@@ -600,10 +544,10 @@ void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) {
auth_error_time_ = base::TimeTicks(); // Reset auth_error_time_ to null.
}
- wizard_.SetParent(parent_window);
- wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
-
- FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+ if (last_auth_error_.state() != AuthError::NONE) {
+ wizard_.SetParent(parent_window);
+ wizard_.Step(SyncSetupWizard::GAIA_LOGIN);
+ }
}
void ProfileSyncService::ShowChooseDataTypes(gfx::NativeWindow parent_window) {
@@ -679,26 +623,16 @@ 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();
-
- // 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);
+ backend_->Authenticate(username, password, captcha);
}
void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything,
@@ -715,7 +649,7 @@ void ProfileSyncService::OnUserChoseDatatypes(bool sync_everything,
}
void ProfileSyncService::OnUserCancelledDialog() {
- if (!HasSyncSetupCompleted()) {
+ if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
// A sync dialog was aborted before authentication.
// Rollback.
expect_sync_configuration_aborted_ = true;
@@ -881,43 +815,10 @@ 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() && AreCredentialsAvailable()) {
+ else if (HasSyncSetupCompleted())
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 efa2cb2..c0f023f 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -15,14 +15,12 @@
#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"
@@ -36,7 +34,6 @@ 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
@@ -117,23 +114,13 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
ProfileSyncService(ProfileSyncFactory* factory_,
Profile* profile,
- const std::string& cros_user);
+ bool bootstrap_sync_authentication);
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
@@ -151,7 +138,8 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
void GetDataTypeControllerStates(
browser_sync::DataTypeController::StateMap* state_map) const;
- // Disables sync for user. Use ShowLoginDialog to enable.
+ // Enables/disables sync for user.
+ virtual void EnableForUser(gfx::NativeWindow parent_window);
virtual void DisableForUser();
// Whether sync is enabled by user or not.
@@ -169,9 +157,6 @@ 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
@@ -341,9 +326,6 @@ 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();
@@ -352,8 +334,10 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
return data_type_controllers_;
}
- // The wizard will try to read the auth state out of the profile sync
- // service using this member. Captcha and error state are reflected.
+ // 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!
GoogleServiceAuthError last_auth_error_;
// Our asynchronous backend to communicate with sync components living on
@@ -396,8 +380,11 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// The profile whose data we are synchronizing.
Profile* profile_;
- // Email for the ChromiumOS user, if we're running under ChromiumOS.
- std::string cros_user_;
+ // 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_;
// TODO(ncarter): Put this in a profile, once there is UI for it.
// This specifies where to find the sync server.
@@ -413,6 +400,17 @@ 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.
@@ -421,9 +419,6 @@ 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.
@@ -459,8 +454,6 @@ 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 d0884cc..e970457 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -31,7 +31,6 @@
#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"
@@ -138,7 +137,7 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
void StartSyncService(Task* task, bool will_fail_association) {
if (!service_.get()) {
service_.reset(
- new TestProfileSyncService(&factory_, &profile_, "test_user", false,
+ new TestProfileSyncService(&factory_, &profile_, false, false,
task));
AutofillDataTypeController* data_type_controller =
new AutofillDataTypeController(&factory_,
@@ -165,13 +164,6 @@ 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 3142baf..1b36c63 100644
--- a/chrome/browser/sync/profile_sync_service_mock.h
+++ b/chrome/browser/sync/profile_sync_service_mock.h
@@ -20,6 +20,7 @@ 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 ea53bf7..c989822 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -24,7 +24,6 @@
#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"
@@ -141,7 +140,7 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
int num_pause_expectations) {
if (!service_.get()) {
service_.reset(new TestProfileSyncService(&factory_, &profile_,
- "test_user", false, root_task));
+ false, false, root_task));
service_->set_num_expected_resumes(num_resume_expectations);
service_->set_num_expected_pauses(num_pause_expectations);
PasswordDataTypeController* data_type_controller =
@@ -156,13 +155,6 @@ 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 e1f3299..b706f7d 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -19,7 +19,6 @@
#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"
@@ -69,7 +68,7 @@ class ProfileSyncServicePreferenceTest
return false;
service_.reset(new TestProfileSyncService(
- &factory_, profile_.get(), "test", false, task));
+ &factory_, profile_.get(), false, false, task));
// Register the preference data type.
model_associator_ =
@@ -88,8 +87,6 @@ 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 23e4885..e12192b 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -26,7 +26,6 @@
#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"
@@ -111,7 +110,7 @@ class ProfileSyncServiceSessionTest
return false;
sync_service_.reset(new TestProfileSyncService(
- &factory_, profile(), "test user", false, task));
+ &factory_, profile(), false, false, task));
profile()->set_session_service(helper_.service());
// Register the session data type.
@@ -127,8 +126,6 @@ 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 e831e36..d38e6c9 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -15,7 +15,6 @@
#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"
@@ -41,7 +40,6 @@ 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()
@@ -56,7 +54,7 @@ class ProfileSyncServiceStartupTest : public testing::Test {
virtual void SetUp() {
service_.reset(new TestProfileSyncService(&factory_, &profile_,
- "test", true, NULL));
+ false, true, NULL));
service_->AddObserver(&observer_);
service_->set_num_expected_resumes(0);
service_->set_num_expected_pauses(0);
@@ -101,17 +99,12 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFirstTime)) {
Mock::VerifyAndClearExpectations(data_type_manager);
// Then start things up.
- EXPECT_CALL(*data_type_manager, Configure(_)).Times(2);
+ 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(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");
-
+ EXPECT_CALL(observer_, OnStateChanged()).Times(4);
+ service_->EnableForUser(NULL);
syncable::ModelTypeSet set;
set.insert(syncable::BOOKMARKS);
service_->OnUserChoseDatatypes(false, set);
@@ -126,9 +119,6 @@ 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();
}
@@ -140,8 +130,6 @@ 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();
}
@@ -150,8 +138,6 @@ 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.
@@ -178,13 +164,51 @@ 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 f913433..17137ea4 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -27,7 +27,6 @@
#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"
@@ -154,7 +153,7 @@ class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
void StartSyncService(Task* task) {
if (!service_.get()) {
service_.reset(
- new TestProfileSyncService(&factory_, &profile_, "test", false,
+ new TestProfileSyncService(&factory_, &profile_, false, false,
task));
TypedUrlDataTypeController* data_type_controller =
new TypedUrlDataTypeController(&factory_,
@@ -177,14 +176,7 @@ 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 8ea701a..bb366c7 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -15,7 +15,6 @@
#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"
@@ -33,7 +32,6 @@
#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"
@@ -248,10 +246,9 @@ 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(),
- "test", false, NULL));
+ false, false, NULL));
if (!set_initial_sync_ended)
service_->dont_set_initial_sync_ended_on_init();
@@ -270,9 +267,6 @@ 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();
}
@@ -473,15 +467,15 @@ TEST_F(ProfileSyncServiceTest, InitialState) {
TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
service_.reset(new TestProfileSyncService(&factory_, profile_.get(),
- "test", true, NULL));
+ false, true, NULL));
service_->set_num_expected_resumes(0);
- EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
+ EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
+ WillOnce(ReturnNewDataTypeManager());
EXPECT_CALL(factory_, CreateBookmarkSyncComponents(_, _)).Times(0);
service_->RegisterDataTypeController(
new browser_sync::BookmarkDataTypeController(&factory_,
profile_.get(),
service_.get()));
-
service_->Initialize();
service_.reset();
}
@@ -1355,9 +1349,9 @@ TEST_F(ProfileSyncServiceTestWithData, TestStartupWithOldSyncData) {
if (!service_.get()) {
service_.reset(
new TestProfileSyncService(&factory_, profile_.get(),
- "test", true, NULL));
+ false, 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(),
@@ -1382,25 +1376,26 @@ TEST_F(ProfileSyncServiceTestWithData, TestStartupWithOldSyncData) {
ASSERT_FALSE(service_->backend());
ASSERT_FALSE(service_->HasSyncSetupCompleted());
- // 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");
-
+ // This will actually start up the sync service.
+ service_->EnableForUser(NULL);
syncable::ModelTypeSet set;
set.insert(syncable::BOOKMARKS);
service_->OnUserChoseDatatypes(false, set);
- MessageLoop::current()->RunAllPending();
+ MessageLoop::current()->Run();
// 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));
- // This will still exist, but the text should have changed.
+ // 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);
+
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 4c6b63f..1e37a7c 100644
--- a/chrome/browser/sync/sessions/sync_session_context.h
+++ b/chrome/browser/sync/sessions/sync_session_context.h
@@ -31,6 +31,7 @@ class DirectoryManager;
namespace browser_sync {
+class AuthWatcher;
class ConflictResolver;
class ModelSafeWorkerRegistrar;
class ServerConnectionManager;
@@ -42,11 +43,13 @@ 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()),
@@ -65,6 +68,9 @@ class SyncSessionContext {
ServerConnectionManager* connection_manager() {
return connection_manager_;
}
+ AuthWatcher* auth_watcher() {
+ return auth_watcher_;
+ }
syncable::DirectoryManager* directory_manager() {
return directory_manager_;
}
@@ -119,6 +125,7 @@ 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 011f667..2bc4594 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, this));
+ context_.reset(new SyncSessionContext(NULL, 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, db.manager(), this));
+ context_.reset(new SyncSessionContext(NULL, 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
deleted file mode 100644
index 6f2a30c..0000000
--- a/chrome/browser/sync/signin_manager.cc
+++ /dev/null
@@ -1,95 +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/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
deleted file mode 100644
index a62514f..0000000
--- a/chrome/browser/sync/signin_manager.h
+++ /dev/null
@@ -1,81 +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.
-//
-// 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
deleted file mode 100644
index 208667c..0000000
--- a/chrome/browser/sync/signin_manager_unittest.cc
+++ /dev/null
@@ -1,93 +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/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 484d376..5ecd9b6 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, ""),
+ : ProfileSyncService(factory, profile, false),
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 32391ae..c7c1575 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->ShowLoginDialog(NULL);
- ProfileSyncService::SyncEvent(code); // UMA stats
+ service->EnableForUser(NULL);
+ ProfileSyncService::SyncEvent(code);
}
}
diff --git a/chrome/browser/sync/syncable/directory_manager.cc b/chrome/browser/sync/syncable/directory_manager.cc
index fbdeb46..0719c67 100644
--- a/chrome/browser/sync/syncable/directory_manager.cc
+++ b/chrome/browser/sync/syncable/directory_manager.cc
@@ -54,6 +54,17 @@ 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 0c0b55d..a6f0847 100644
--- a/chrome/browser/sync/syncable/directory_manager.h
+++ b/chrome/browser/sync/syncable/directory_manager.h
@@ -31,11 +31,14 @@ 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 0854a6b..aba7c42 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->name);
+ ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
if (!dir.good())
FAIL();
@@ -154,6 +154,7 @@ 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));
@@ -185,12 +186,10 @@ class TestProfileSyncService : public ProfileSyncService {
public:
TestProfileSyncService(ProfileSyncFactory* factory,
Profile* profile,
- const std::string& test_user,
+ bool bootstrap_sync_authentication,
bool synchronous_backend_initialization,
Task* initial_condition_setup_task)
- : ProfileSyncService(factory, profile,
- !test_user.empty() ?
- test_user : ""),
+ : ProfileSyncService(factory, profile, bootstrap_sync_authentication),
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
deleted file mode 100644
index 084bc40..0000000
--- a/chrome/browser/sync/token_migrator.cc
+++ /dev/null
@@ -1,53 +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/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
deleted file mode 100644
index 6ee3394..0000000
--- a/chrome/browser/sync/token_migrator.h
+++ /dev/null
@@ -1,53 +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 <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 9af444f..41b9ffa 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_->ShowLoginDialog(GetWindow()->GetNativeWindow());
+ sync_service_->EnableForUser(GetWindow()->GetNativeWindow());
ProfileSyncService::SyncEvent(ProfileSyncService::START_FROM_OPTIONS);
}
} else if (sender == sync_customize_button_) {