Index: chrome/browser/sync/notifier/listener/talk_mediator_impl.cc |
=================================================================== |
--- chrome/browser/sync/notifier/listener/talk_mediator_impl.cc (revision 0) |
+++ chrome/browser/sync/notifier/listener/talk_mediator_impl.cc (revision 0) |
@@ -0,0 +1,275 @@ |
+// Copyright (c) 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/notifier/listener/talk_mediator_impl.h" |
+ |
+#include "base/logging.h" |
+#include "chrome/browser/sync/engine/auth_watcher.h" |
+#include "chrome/browser/sync/engine/syncer_thread.h" |
+#include "chrome/browser/sync/notifier/listener/mediator_thread_impl.h" |
+#include "chrome/browser/sync/util/event_sys-inl.h" |
+#include "talk/base/cryptstring.h" |
+#include "talk/base/ssladapter.h" |
+#include "talk/xmpp/xmppclientsettings.h" |
+#include "talk/xmpp/xmppengine.h" |
+ |
+namespace browser_sync { |
+ |
+// Before any authorization event from TalkMediatorImpl, we need to initialize |
+// the SSL library. |
+class SslInitializationSingleton { |
+ public: |
+ virtual ~SslInitializationSingleton() { |
+ talk_base::CleanupSSL(); |
+ }; |
+ |
+ void RegisterClient() {} |
+ |
+ static SslInitializationSingleton* GetInstance() { |
+ MutexLock lock(&mutex_); |
+ if (!instance_.get()) { |
+ instance_.reset(new SslInitializationSingleton()); |
+ } |
+ return instance_.get(); |
+ } |
+ |
+ private: |
+ typedef PThreadScopedLock<PThreadMutex> MutexLock; |
+ |
+ SslInitializationSingleton() { |
+ talk_base::InitializeSSL(); |
+ }; |
+ |
+ // The single instance of this class. |
+ static PThreadMutex mutex_; |
+ static scoped_ptr<SslInitializationSingleton> instance_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SslInitializationSingleton); |
+}; |
+ |
+// Declaration of class scoped static variables. |
+PThreadMutex SslInitializationSingleton::mutex_; |
+scoped_ptr<SslInitializationSingleton> SslInitializationSingleton::instance_; |
+ |
+TalkMediatorImpl::TalkMediatorImpl() |
+ : mediator_thread_(new MediatorThreadImpl()) { |
+ // Ensure the SSL library is initialized. |
+ SslInitializationSingleton::GetInstance()->RegisterClient(); |
+ |
+ // Construct the callback channel with the shutdown event. |
+ TalkMediatorInitialization(false); |
+} |
+ |
+TalkMediatorImpl::TalkMediatorImpl(MediatorThread *thread) |
+ : mediator_thread_(thread) { |
+ // When testing we do not initialize the SSL library. |
+ TalkMediatorInitialization(true); |
+} |
+ |
+void TalkMediatorImpl::TalkMediatorInitialization(bool should_connect) { |
+ TalkMediatorEvent done = { TalkMediatorEvent::TALKMEDIATOR_DESTROYED }; |
+ channel_.reset(new TalkMediatorChannel(done)); |
+ if (should_connect) { |
+ mediator_thread_->SignalStateChange.connect( |
+ this, |
+ &TalkMediatorImpl::MediatorThreadMessageHandler); |
+ state_.connected = 1; |
+ } |
+ mediator_thread_->Start(); |
+ state_.started = 1; |
+} |
+ |
+TalkMediatorImpl::~TalkMediatorImpl() { |
+ if (state_.started) { |
+ Logout(); |
+ } |
+} |
+ |
+void TalkMediatorImpl::AuthWatcherEventHandler( |
+ const AuthWatcherEvent& auth_event) { |
+ MutexLock lock(&mutex_); |
+ switch (auth_event.what_happened) { |
+ case AuthWatcherEvent::AUTHWATCHER_DESTROYED: |
+ case AuthWatcherEvent::GAIA_AUTH_FAILED: |
+ case AuthWatcherEvent::SERVICE_AUTH_FAILED: |
+ case AuthWatcherEvent::SERVICE_CONNECTION_FAILED: |
+ // We have failed to connect to the buzz server, and we maintain a |
+ // decreased polling interval and stay in a flaky connection mode. |
+ // Note that the failure is on the authwatcher's side and can not be |
+ // resolved without manual retry. |
+ break; |
+ case AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START: |
+ // TODO(brg) : We are restarting the authentication attempt. We need to |
+ // insure this code path is stable. |
+ break; |
+ case AuthWatcherEvent::AUTH_SUCCEEDED: |
+ if (!state_.logged_in) { |
+ DoLogin(); |
+ } |
+ break; |
+ default: |
+ // Do nothing |
+ break; |
+ } |
+} |
+ |
+void TalkMediatorImpl::WatchAuthWatcher(AuthWatcher* watcher) { |
+ auth_hookup_.reset(NewEventListenerHookup( |
+ watcher->channel(), |
+ this, |
+ &TalkMediatorImpl::AuthWatcherEventHandler)); |
+} |
+ |
+bool TalkMediatorImpl::Login() { |
+ MutexLock lock(&mutex_); |
+ return DoLogin(); |
+} |
+ |
+bool TalkMediatorImpl::DoLogin() { |
+ // Connect to the mediator thread and start it processing messages. |
+ if (!state_.connected) { |
+ mediator_thread_->SignalStateChange.connect( |
+ this, |
+ &TalkMediatorImpl::MediatorThreadMessageHandler); |
+ state_.connected = 1; |
+ } |
+ if (state_.initialized && !state_.logged_in) { |
+ mediator_thread_->Login(xmpp_settings_); |
+ state_.logged_in = 1; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+bool TalkMediatorImpl::Logout() { |
+ MutexLock lock(&mutex_); |
+ // We do not want to be called back during logout since we may be closing. |
+ if (state_.connected) { |
+ mediator_thread_->SignalStateChange.disconnect(this); |
+ state_.connected = 0; |
+ } |
+ if (state_.started) { |
+ mediator_thread_->Logout(); |
+ state_.started = 0; |
+ state_.logged_in = 0; |
+ state_.subscribed = 0; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+bool TalkMediatorImpl::SendNotification() { |
+ MutexLock lock(&mutex_); |
+ if (state_.logged_in && state_.subscribed) { |
+ mediator_thread_->SendNotification(); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+TalkMediatorChannel* TalkMediatorImpl::channel() const { |
+ return channel_.get(); |
+} |
+ |
+bool TalkMediatorImpl::SetAuthToken(const std::string& email, |
+ const std::string& token) { |
+ MutexLock lock(&mutex_); |
+ |
+ // Verify that we can create a JID from the email provided. |
+ buzz::Jid jid = buzz::Jid(email); |
+ if (jid.node().empty() || !jid.IsValid()) { |
+ return false; |
+ } |
+ |
+ // Construct the XmppSettings object for login to buzz. |
+ xmpp_settings_.set_user(jid.node()); |
+ xmpp_settings_.set_resource("chrome-sync"); |
+ xmpp_settings_.set_host(jid.domain()); |
+ xmpp_settings_.set_use_tls(true); |
+ xmpp_settings_.set_auth_cookie(token); |
+ |
+ state_.initialized = 1; |
+ return true; |
+} |
+ |
+void TalkMediatorImpl::MediatorThreadMessageHandler( |
+ MediatorThread::MediatorMessage message) { |
+ LOG(INFO) << "P2P: MediatorThread has passed a message"; |
+ switch (message) { |
+ case MediatorThread::MSG_LOGGED_IN: |
+ OnLogin(); |
+ break; |
+ case MediatorThread::MSG_LOGGED_OUT: |
+ OnLogout(); |
+ break; |
+ case MediatorThread::MSG_SUBSCRIPTION_SUCCESS: |
+ OnSubscriptionSuccess(); |
+ break; |
+ case MediatorThread::MSG_SUBSCRIPTION_FAILURE: |
+ OnSubscriptionFailure(); |
+ break; |
+ case MediatorThread::MSG_NOTIFICATION_RECEIVED: |
+ OnNotificationReceived(); |
+ break; |
+ case MediatorThread::MSG_NOTIFICATION_SENT: |
+ OnNotificationSent(); |
+ break; |
+ default: |
+ LOG(WARNING) << "P2P: Unknown message returned from mediator thread."; |
+ break; |
+ } |
+} |
+ |
+void TalkMediatorImpl::OnLogin() { |
+ LOG(INFO) << "P2P: Logged in."; |
+ MutexLock lock(&mutex_); |
+ // ListenForUpdates enables the ListenTask. This is done before |
+ // SubscribeForUpdates. |
+ mediator_thread_->ListenForUpdates(); |
+ mediator_thread_->SubscribeForUpdates(); |
+ TalkMediatorEvent event = { TalkMediatorEvent::LOGIN_SUCCEEDED }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+void TalkMediatorImpl::OnLogout() { |
+ LOG(INFO) << "P2P: Logged off."; |
+ OnSubscriptionFailure(); |
+ MutexLock lock(&mutex_); |
+ state_.logged_in = 0; |
+ TalkMediatorEvent event = { TalkMediatorEvent::LOGOUT_SUCCEEDED }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+void TalkMediatorImpl::OnSubscriptionSuccess() { |
+ LOG(INFO) << "P2P: Update subscription active."; |
+ MutexLock lock(&mutex_); |
+ state_.subscribed = 1; |
+ TalkMediatorEvent event = { TalkMediatorEvent::SUBSCRIPTIONS_ON }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+void TalkMediatorImpl::OnSubscriptionFailure() { |
+ LOG(INFO) << "P2P: Update subscription failure."; |
+ MutexLock lock(&mutex_); |
+ state_.subscribed = 0; |
+ TalkMediatorEvent event = { TalkMediatorEvent::SUBSCRIPTIONS_OFF }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+void TalkMediatorImpl::OnNotificationReceived() { |
+ LOG(INFO) << "P2P: Updates are available on the server."; |
+ MutexLock lock(&mutex_); |
+ TalkMediatorEvent event = { TalkMediatorEvent::NOTIFICATION_RECEIVED }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+void TalkMediatorImpl::OnNotificationSent() { |
+ LOG(INFO) << |
+ "P2P: Peers were notified that updates are available on the server."; |
+ MutexLock lock(&mutex_); |
+ TalkMediatorEvent event = { TalkMediatorEvent::NOTIFICATION_SENT }; |
+ channel_->NotifyListeners(event); |
+} |
+ |
+} // namespace browser_sync |
Property changes on: chrome\browser\sync\notifier\listener\talk_mediator_impl.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |