summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-01 23:30:07 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-01 23:30:07 +0000
commit0eee054a1cb5ed5a1917ca457cca4b127290edb6 (patch)
tree038b7feed46165e781746bd13fe5b2994c1b3d6e
parent7312d0b76ac9c47e2e6eee7174c00e9d845213ca (diff)
downloadchromium_src-0eee054a1cb5ed5a1917ca457cca4b127290edb6.zip
chromium_src-0eee054a1cb5ed5a1917ca457cca4b127290edb6.tar.gz
chromium_src-0eee054a1cb5ed5a1917ca457cca4b127290edb6.tar.bz2
Make sure XMPP logins and notification sends are done on the sync
core thread only. BUG=none TEST=unit tests, manual testing of notifications Review URL: http://codereview.chromium.org/2326001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48675 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/engine/all_status.cc27
-rw-r--r--chrome/browser/sync/engine/all_status.h16
-rw-r--r--chrome/browser/sync/engine/auth_watcher.cc31
-rw-r--r--chrome/browser/sync/engine/auth_watcher.h23
-rw-r--r--chrome/browser/sync/engine/auth_watcher_unittest.cc13
-rw-r--r--chrome/browser/sync/engine/syncapi.cc158
6 files changed, 142 insertions, 126 deletions
diff --git a/chrome/browser/sync/engine/all_status.cc b/chrome/browser/sync/engine/all_status.cc
index 68d2513a..64ea9a7 100644
--- a/chrome/browser/sync/engine/all_status.cc
+++ b/chrome/browser/sync/engine/all_status.cc
@@ -17,7 +17,6 @@
#include "chrome/browser/sync/sessions/session_state.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/common/deprecated/event_sys-inl.h"
-#include "chrome/common/net/gaia/gaia_authenticator.h"
#include "chrome/common/net/notifier/listener/talk_mediator.h"
namespace browser_sync {
@@ -59,17 +58,6 @@ void AllStatus::WatchConnectionManager(ServerConnectionManager* conn_mgr) {
&AllStatus::HandleServerConnectionEvent));
}
-void AllStatus::WatchAuthenticator(gaia::GaiaAuthenticator* gaia) {
- gaia_hookup_.reset(NewEventListenerHookup(gaia->channel(), this,
- &AllStatus::HandleGaiaAuthEvent));
-}
-
-void AllStatus::WatchAuthWatcher(AuthWatcher* auth_watcher) {
- authwatcher_hookup_.reset(
- NewEventListenerHookup(auth_watcher->channel(), this,
- &AllStatus::HandleAuthWatcherEvent));
-}
-
void AllStatus::WatchSyncerThread(SyncerThread* syncer_thread) {
syncer_thread_hookup_.reset(
NewEventListenerHookup(syncer_thread->relay_channel(), this,
@@ -171,21 +159,6 @@ int AllStatus::CalcStatusChanges(Status* old_status) {
return what_changed;
}
-void AllStatus::HandleGaiaAuthEvent(const gaia::GaiaAuthEvent& gaia_event) {
- ScopedStatusLockWithNotify lock(this);
- switch (gaia_event.what_happened) {
- case gaia::GaiaAuthEvent::GAIA_AUTH_FAILED:
- status_.authenticated = false;
- break;
- case gaia::GaiaAuthEvent::GAIA_AUTH_SUCCEEDED:
- status_.authenticated = true;
- break;
- default:
- lock.set_notify_plan(DONT_NOTIFY);
- break;
- }
-}
-
void AllStatus::HandleAuthWatcherEvent(const AuthWatcherEvent& auth_event) {
ScopedStatusLockWithNotify lock(this);
switch (auth_event.what_happened) {
diff --git a/chrome/browser/sync/engine/all_status.h b/chrome/browser/sync/engine/all_status.h
index f19d6ca..d34a15a 100644
--- a/chrome/browser/sync/engine/all_status.h
+++ b/chrome/browser/sync/engine/all_status.h
@@ -15,14 +15,8 @@
#include "base/scoped_ptr.h"
#include "chrome/common/deprecated/event_sys.h"
-namespace gaia {
-class GaiaAuthenticator;
-struct GaiaAuthEvent;
-}
-
namespace browser_sync {
-class AuthWatcher;
class ScopedStatusLockWithNotify;
class ServerConnectionManager;
class Syncer;
@@ -100,14 +94,6 @@ class AllStatus {
void WatchConnectionManager(ServerConnectionManager* conn_mgr);
void HandleServerConnectionEvent(const ServerConnectionEvent& event);
- // Both WatchAuthenticator/HandleGaiaAuthEvent and WatchAuthWatcher/
- // HandleAuthWatcherEventachieve have the same goal; use only one of the
- // following two. (The AuthWatcher is watched under Windows; the
- // GaiaAuthenticator is watched under Mac/Linux.)
- void WatchAuthenticator(gaia::GaiaAuthenticator* gaia);
- void HandleGaiaAuthEvent(const gaia::GaiaAuthEvent& event);
-
- void WatchAuthWatcher(AuthWatcher* auth_watcher);
void HandleAuthWatcherEvent(const AuthWatcherEvent& event);
void WatchSyncerThread(SyncerThread* syncer_thread);
@@ -148,8 +134,6 @@ class AllStatus {
Status status_;
Channel* const channel_;
scoped_ptr<EventListenerHookup> conn_mgr_hookup_;
- scoped_ptr<EventListenerHookup> gaia_hookup_;
- scoped_ptr<EventListenerHookup> authwatcher_hookup_;
scoped_ptr<EventListenerHookup> 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
index e674ab3..569dbe9 100644
--- a/chrome/browser/sync/engine/auth_watcher.cc
+++ b/chrome/browser/sync/engine/auth_watcher.cc
@@ -14,7 +14,6 @@
#include "chrome/browser/sync/util/user_settings.h"
#include "chrome/common/deprecated/event_sys-inl.h"
#include "chrome/common/net/gaia/gaia_authenticator.h"
-#include "chrome/common/net/notifier/listener/talk_mediator.h"
// How authentication happens:
//
@@ -44,14 +43,12 @@ AuthWatcher::AuthWatcher(DirectoryManager* dirman,
const string& service_id,
const string& gaia_url,
UserSettings* user_settings,
- gaia::GaiaAuthenticator* gaia_auth,
- notifier::TalkMediator* talk_mediator)
+ gaia::GaiaAuthenticator* gaia_auth)
: gaia_(gaia_auth),
dirman_(dirman),
scm_(scm),
status_(NOT_AUTHENTICATED),
user_settings_(user_settings),
- talk_mediator_(talk_mediator),
auth_backend_thread_("SyncEngine_AuthWatcherThread"),
current_attempt_trigger_(AuthWatcherEvent::USER_INITIATED) {
@@ -101,16 +98,11 @@ void AuthWatcher::DoRenewAuthToken(const std::string& updated_token) {
LOG(INFO) << "Updating auth token:" << updated_token;
scm_->set_auth_token(updated_token);
gaia_->RenewAuthToken(updated_token); // Must be on AuthWatcher thread
- talk_mediator_->SetAuthToken(user_settings_->email(), updated_token,
- SYNC_SERVICE_NAME);
- // TODO(akalin): to see if we need to call Login() here, too.
-
user_settings_->SetAuthTokenForService(user_settings_->email(),
SYNC_SERVICE_NAME,
updated_token);
- AuthWatcherEvent event = { AuthWatcherEvent::AUTH_RENEWED };
- NotifyListeners(&event);
+ NotifyAuthChanged(user_settings_->email(), updated_token, true);
}
void AuthWatcher::AuthenticateWithLsid(const std::string& lsid) {
@@ -164,10 +156,6 @@ void AuthWatcher::DoAuthenticateWithToken(const std::string& gaia_email,
status_ = GAIA_AUTHENTICATED;
const std::string& share_name = email;
user_settings_->SwitchUser(email);
-
- // Set the authentication token for notifications
- talk_mediator_->SetAuthToken(email, auth_token, SYNC_SERVICE_NAME);
- talk_mediator_->Login();
scm_->set_auth_token(auth_token);
if (!was_authenticated) {
@@ -175,7 +163,7 @@ void AuthWatcher::DoAuthenticateWithToken(const std::string& gaia_email,
<< share_name << ")";
dirman_->Open(share_name);
}
- NotifyAuthSucceeded(email);
+ NotifyAuthChanged(email, auth_token, false);
return;
}
case Authenticator::BAD_AUTH_TOKEN:
@@ -210,7 +198,7 @@ bool AuthWatcher::AuthenticateLocally(string email) {
user_settings_->SwitchUser(email);
LOG(INFO) << "Opening DB for AuthenticateLocally (" << email << ")";
dirman_->Open(email);
- NotifyAuthSucceeded(email);
+ NotifyAuthChanged(email, "", false);
return true;
} else {
return false;
@@ -284,11 +272,18 @@ void AuthWatcher::DoAuthenticate(const AuthRequest& request) {
}
}
-void AuthWatcher::NotifyAuthSucceeded(const string& email) {
+void AuthWatcher::NotifyAuthChanged(const string& email,
+ const string& auth_token,
+ bool renewed) {
DCHECK_EQ(MessageLoop::current(), message_loop());
LOG(INFO) << "NotifyAuthSucceeded";
- AuthWatcherEvent event = { AuthWatcherEvent::AUTH_SUCCEEDED };
+ AuthWatcherEvent event = {
+ renewed ?
+ AuthWatcherEvent::AUTH_RENEWED :
+ AuthWatcherEvent::AUTH_SUCCEEDED
+ };
event.user_email = email;
+ event.auth_token = auth_token;
NotifyListeners(&event);
}
diff --git a/chrome/browser/sync/engine/auth_watcher.h b/chrome/browser/sync/engine/auth_watcher.h
index 60f3ed8..2f7b36a 100644
--- a/chrome/browser/sync/engine/auth_watcher.h
+++ b/chrome/browser/sync/engine/auth_watcher.h
@@ -21,10 +21,6 @@
#include "chrome/common/net/gaia/gaia_authenticator.h"
#include "testing/gtest/include/gtest/gtest_prod.h" // For FRIEND_TEST
-namespace notifier {
-class TalkMediator;
-}
-
namespace syncable {
struct DirectoryManagerEvent;
class DirectoryManager;
@@ -59,8 +55,10 @@ struct AuthWatcherEvent {
return event.what_happened == AUTHWATCHER_DESTROYED;
}
- // Used for AUTH_SUCCEEDED notification
+ // 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 {
@@ -92,8 +90,7 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
const std::string& service_id,
const std::string& gaia_url,
UserSettings* user_settings,
- gaia::GaiaAuthenticator* gaia_auth,
- notifier::TalkMediator* talk_mediator);
+ gaia::GaiaAuthenticator* gaia_auth);
~AuthWatcher();
typedef EventChannel<AuthWatcherEvent, Lock> Channel;
@@ -118,7 +115,6 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
// Use this to update only the token of the current email address.
void RenewAuthToken(const std::string& updated_token);
- void DoRenewAuthToken(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|.
@@ -139,10 +135,12 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
UserSettings* settings() const { return user_settings_; }
Status status() const { return (Status)status_; }
- protected:
+ private:
void ClearAuthenticationData();
- void NotifyAuthSucceeded(const std::string& email);
+ void NotifyAuthChanged(const std::string& email,
+ const std::string& auth_token,
+ bool renewed);
void HandleServerConnectionEvent(const ServerConnectionEvent& event);
void SaveUserSettings(const std::string& username,
@@ -150,7 +148,8 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
MessageLoop* message_loop() { return auth_backend_thread_.message_loop(); }
- private:
+ 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();
@@ -206,8 +205,6 @@ class AuthWatcher : public base::RefCountedThreadSafe<AuthWatcher> {
scoped_ptr<EventListenerHookup> connmgr_hookup_;
Status status_;
UserSettings* const user_settings_;
- // Interface to the notifications engine.
- notifier::TalkMediator* talk_mediator_;
scoped_ptr<Channel> channel_;
base::Thread auth_backend_thread_;
diff --git a/chrome/browser/sync/engine/auth_watcher_unittest.cc b/chrome/browser/sync/engine/auth_watcher_unittest.cc
index eb39772..e795d31 100644
--- a/chrome/browser/sync/engine/auth_watcher_unittest.cc
+++ b/chrome/browser/sync/engine/auth_watcher_unittest.cc
@@ -10,9 +10,7 @@
#include "chrome/browser/sync/engine/auth_watcher.h"
#include "chrome/browser/sync/util/user_settings.h"
#include "chrome/common/deprecated/event_sys-inl.h"
-#include "chrome/common/net/fake_network_change_notifier_thread.h"
#include "chrome/common/net/http_return.h"
-#include "chrome/common/net/notifier/listener/talk_mediator_impl.h"
#include "chrome/common/net/gaia/gaia_authenticator.h"
#include "chrome/test/sync/engine/mock_server_connection.h"
#include "chrome/test/sync/engine/test_directory_setter_upper.h"
@@ -98,12 +96,9 @@ class AuthWatcherTest : public testing::Test {
FilePath user_settings_path = temp_dir_.path().Append(kUserSettingsDB);
user_settings_->Init(user_settings_path);
gaia_auth_ = new GaiaAuthMockForAuthWatcher();
- fake_network_change_notifier_thread_.Start();
- talk_mediator_.reset(new notifier::TalkMediatorImpl(
- &fake_network_change_notifier_thread_, false));
auth_watcher_ = new AuthWatcher(metadb_.manager(), connection_.get(),
kTestUserAgent, kTestServiceId, kTestGaiaURL,
- user_settings_.get(), gaia_auth_, talk_mediator_.get());
+ user_settings_.get(), gaia_auth_);
authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(),
this, &AuthWatcherTest::HandleAuthWatcherEvent));
}
@@ -112,8 +107,6 @@ class AuthWatcherTest : public testing::Test {
metadb_.TearDown();
auth_watcher_->Shutdown();
EXPECT_FALSE(auth_watcher()->message_loop());
- talk_mediator_.reset();
- fake_network_change_notifier_thread_.Stop();
}
void HandleAuthWatcherEvent(const AuthWatcherEvent& event) {
@@ -151,10 +144,6 @@ class AuthWatcherTest : public testing::Test {
scoped_ptr<MockConnectionManager> connection_;
scoped_ptr<UserSettings> user_settings_;
GaiaAuthMockForAuthWatcher* gaia_auth_; // Owned by auth_watcher_.
- scoped_ptr<notifier::TalkMediator> talk_mediator_;
- // Needed by talk_mediator_.
- chrome_common_net::FakeNetworkChangeNotifierThread
- fake_network_change_notifier_thread_;
scoped_refptr<AuthWatcher> auth_watcher_;
// This is used to block the AuthWatcherThread when it raises events until we
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index b35a549..54a7188 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -15,6 +15,7 @@
#include "base/base64.h"
#include "base/lock.h"
#include "base/logging.h"
+#include "base/message_loop.h"
#include "base/platform_thread.h"
#include "base/scoped_ptr.h"
#include "base/sha1.h"
@@ -82,6 +83,13 @@ typedef GoogleServiceAuthError AuthError;
static const int kThreadExitTimeoutMsec = 60000;
static const int kSSLPort = 443;
+// We manage the lifetime of sync_api::SyncManager::SyncInternal ourselves.
+template <>
+struct RunnableMethodTraits<sync_api::SyncManager::SyncInternal> {
+ void RetainCallee(sync_api::SyncManager::SyncInternal*) {}
+ void ReleaseCallee(sync_api::SyncManager::SyncInternal*) {}
+};
+
namespace sync_api {
static const FilePath::CharType kBookmarkSyncUserSettingsDatabase[] =
@@ -774,16 +782,21 @@ class SyncManager::SyncInternal
static const int kPreferencesNudgeDelayMilliseconds;
public:
explicit SyncInternal(SyncManager* sync_manager)
- : observer_(NULL),
+ : core_message_loop_(NULL),
+ observer_(NULL),
auth_problem_(AuthError::NONE),
sync_manager_(sync_manager),
registrar_(NULL),
notification_pending_(false),
initialized_(false),
notification_method_(browser_sync::kDefaultNotificationMethod) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
}
- ~SyncInternal() { }
+ ~SyncInternal() {
+ DCHECK(!core_message_loop_);
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ }
bool Init(const FilePath& database_location,
const std::string& sync_server_and_path,
@@ -844,6 +857,10 @@ class SyncManager::SyncInternal
// on startup, to serve our UI needs.
void HandleAuthWatcherEvent(const AuthWatcherEvent& 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(
@@ -948,7 +965,10 @@ class SyncManager::SyncInternal
// already initialized, this is a no-op.
void MarkAndNotifyInitializationComplete();
- bool SendXMPPNotification();
+ // If there's a pending notification to be sent, either from the
+ // new_pending_notification flag or a previous unsuccessfully sent
+ // notification, tries to send a notification.
+ void SendPendingXMPPNotification(bool new_pending_notification);
// Determine if the parents or predecessors differ between the old and new
// versions of an entry stored in |a| and |b|. Note that a node's index may
@@ -1010,6 +1030,8 @@ class SyncManager::SyncInternal
// last user information, current sync-related URLs, and more.
scoped_ptr<UserSettings> user_settings_;
+ MessageLoop* core_message_loop_;
+
// Observer registered via SetObserver/RemoveObserver.
// WARNING: This can be NULL!
SyncManager::Observer* observer_;
@@ -1170,6 +1192,8 @@ bool SyncManager::SyncInternal::Init(
LOG(INFO) << "Starting SyncInternal initialization.";
+ 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.
@@ -1229,10 +1253,8 @@ bool SyncManager::SyncInternal::Init(
service_id,
gaia_url,
user_settings_.get(),
- gaia_auth,
- talk_mediator());
+ gaia_auth);
- allstatus_.WatchAuthWatcher(auth_watcher());
authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(),
this, &SyncInternal::HandleAuthWatcherEvent));
@@ -1291,7 +1313,20 @@ void SyncManager::SyncInternal::MarkAndNotifyInitializationComplete() {
observer_->OnInitializationComplete();
}
-bool SyncManager::SyncInternal::SendXMPPNotification() {
+void SyncManager::SyncInternal::SendPendingXMPPNotification(
+ bool new_pending_notification) {
+ DCHECK_EQ(MessageLoop::current(), core_message_loop_);
+ notification_pending_ = notification_pending_ || new_pending_notification;
+ if (!notification_pending_) {
+ LOG(INFO) << "Not sending notification: no pending notification";
+ return;
+ }
+ if (!talk_mediator_.get()) {
+ LOG(INFO) << "Not sending notification: shutting down "
+ << "(talk_mediator_ is NULL)";
+ return;
+ }
+ LOG(INFO) << "Sending XMPP notification...";
OutgoingNotificationData notification_data;
if (notification_method_ == browser_sync::NOTIFICATION_LEGACY) {
notification_data.service_id = browser_sync::kSyncLegacyServiceId;
@@ -1311,7 +1346,13 @@ bool SyncManager::SyncInternal::SendXMPPNotification() {
notification_data.require_subscription = false;
}
}
- return talk_mediator()->SendNotification(notification_data);
+ bool success = talk_mediator_->SendNotification(notification_data);
+ if (success) {
+ notification_pending_ = false;
+ LOG(INFO) << "Sent XMPP notification";
+ } else {
+ LOG(INFO) << "Could not send XMPP notification";
+ }
}
void SyncManager::SyncInternal::Authenticate(const std::string& username,
@@ -1389,11 +1430,15 @@ void SyncManager::SyncInternal::Shutdown() {
if (auth_watcher_) {
auth_watcher_->Shutdown();
auth_watcher_ = NULL;
+ authwatcher_hookup_.reset();
}
if (syncer_thread()) {
- if (!syncer_thread()->Stop(kThreadExitTimeoutMsec))
- DCHECK(false) << "Unable to stop the syncer, it won't be happy...";
+ if (!syncer_thread()->Stop(kThreadExitTimeoutMsec)) {
+ LOG(FATAL) << "Unable to stop the syncer, it won't be happy...";
+ }
+ syncer_event_.reset();
+ syncer_thread_ = NULL;
}
// Shutdown the xmpp buzz connection.
@@ -1405,6 +1450,18 @@ void SyncManager::SyncInternal::Shutdown() {
LOG(INFO) << "P2P: Mediator destroyed.";
}
+ // Pump any messages the auth watcher, syncer thread, or talk
+ // mediator posted before they shut down. (See HandleSyncerEvent(),
+ // HandleAuthWatcherEvent(), and HandleTalkMediatorEvent() for the
+ // events that may be posted.)
+ {
+ CHECK(core_message_loop_);
+ bool old_state = core_message_loop_->NestableTasksAllowed();
+ core_message_loop_->SetNestableTasksAllowed(true);
+ core_message_loop_->RunAllPending();
+ core_message_loop_->SetNestableTasksAllowed(old_state);
+ }
+
if (network_change_notifier_.get()) {
network_change_notifier_->RemoveObserver(this);
network_change_notifier_.reset();
@@ -1422,8 +1479,8 @@ void SyncManager::SyncInternal::Shutdown() {
// We don't want to process any more events.
dir_change_hookup_.reset();
- syncer_event_.reset();
- authwatcher_hookup_.reset();
+
+ core_message_loop_ = NULL;
}
void SyncManager::SyncInternal::OnIPAddressChanged() {
@@ -1635,33 +1692,14 @@ void SyncManager::SyncInternal::HandleSyncerEvent(const SyncerEvent& event) {
// TODO(chron): Consider changing this back to track has_more_to_sync
// only notify peers if a successful commit has occurred.
- if (event.snapshot->syncer_status.num_successful_commits > 0) {
- // We use a member variable here because talk may not have connected yet.
- // The notification must be stored until it can be sent.
- notification_pending_ = true;
- }
-
- // SyncCycles are started by the following events: creation of the syncer,
- // (re)connection to buzz, local changes, peer notifications of updates.
- // Peers will be notified of changes made while there is no buzz connection
- // immediately after a connection has been re-established.
- // the next sync cycle.
- // TODO(brg): Move this to TalkMediatorImpl as a SyncerThread event hook.
- if (notification_pending_ && talk_mediator()) {
- LOG(INFO) << "Sending XMPP notification...";
- bool success = SendXMPPNotification();
- if (success) {
- notification_pending_ = false;
- LOG(INFO) << "Sent XMPP notification";
- } else {
- LOG(INFO) << "Could not send XMPP notification";
- }
- } else {
- LOG(INFO) << "Didn't send XMPP notification!"
- << " event.snapshot.did_commit_items: "
- << event.snapshot->did_commit_items
- << " talk_mediator(): " << talk_mediator();
- }
+ bool new_pending_notification =
+ (event.snapshot->syncer_status.num_successful_commits > 0);
+ core_message_loop_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &SyncManager::SyncInternal::SendPendingXMPPNotification,
+ new_pending_notification));
}
if (event.what_happened == SyncerEvent::PAUSED) {
@@ -1677,6 +1715,7 @@ void SyncManager::SyncInternal::HandleSyncerEvent(const SyncerEvent& event) {
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
@@ -1688,6 +1727,7 @@ void SyncManager::SyncInternal::HandleAuthWatcherEvent(
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()) {
@@ -1716,6 +1756,23 @@ void SyncManager::SyncInternal::HandleAuthWatcherEvent(
}
if (InitialSyncEndedForAllEnabledTypes())
MarkAndNotifyInitializationComplete();
+
+ 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.
@@ -1765,8 +1822,29 @@ void SyncManager::SyncInternal::OnNotificationStateChange(
if (notifications_enabled) {
// Send a notification as soon as subscriptions are on
// (see http://code.google.com/p/chromium/issues/detail?id=38563 ).
- SendXMPPNotification();
+ core_message_loop_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &SyncManager::SyncInternal::SendPendingXMPPNotification,
+ true));
+ }
+}
+
+void SyncManager::SyncInternal::TalkMediatorLogin(
+ const std::string& email, const std::string& token) {
+ DCHECK_EQ(MessageLoop::current(), core_message_loop_);
+ DCHECK(!email.empty());
+ DCHECK(!token.empty());
+ if (!talk_mediator_.get()) {
+ LOG(INFO) << "Not logging in: shutting down "
+ << "(talk_mediator_ is NULL)";
+ return;
}
+ // TODO(akalin): Make talk_mediator automatically login on
+ // auth token change.
+ talk_mediator_->SetAuthToken(email, token, SYNC_SERVICE_NAME);
+ talk_mediator_->Login();
}
void SyncManager::SyncInternal::OnIncomingNotification(