Index: chrome/browser/sync/notifier/sync_notifier_impl.cc |
diff --git a/chrome/browser/sync/notifier/sync_notifier_impl.cc b/chrome/browser/sync/notifier/sync_notifier_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9a62e4c709c7c936ea729a92eb8cda446af69f25 |
--- /dev/null |
+++ b/chrome/browser/sync/notifier/sync_notifier_impl.cc |
@@ -0,0 +1,181 @@ |
+// Copyright (c) 2011 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/sync_notifier_impl.h" |
+ |
+#include "chrome/browser/sync/notifier/server_notifier_thread.h" |
+#include "chrome/browser/sync/protocol/service_constants.h" |
+#include "chrome/browser/sync/sessions/session_state.h" |
+#include "chrome/browser/sync/syncable/model_type.h" |
+#include "chrome/browser/sync/sync_constants.h" |
+#include "jingle/notifier/listener/mediator_thread_impl.h" |
+#include "jingle/notifier/listener/notification_constants.h" |
+ |
+using notifier::TalkMediator; |
+using notifier::TalkMediatorImpl; |
+namespace sync_notifier { |
+ |
+void SyncNotifierImpl::InitializeTalkMediator(const std::string& state, |
+ const notifier::NotifierOptions& notifier_options_) { |
+} |
+ |
+SyncNotifierImpl::SyncNotifierImpl( |
+ notifier::NotifierOptions* notifier_options) |
+ : notifier_options_(notifier_options) { } |
+ |
+SyncNotifierImpl::~SyncNotifierImpl() { |
+ // We NULL out talk_mediator_ so that any pending tasks do not |
+ // trigger further XMPP actions. |
+ // TODO(akalin): NULL the other member variables defensively, too. |
+ scoped_ptr<TalkMediator> talk_mediator(talk_mediator_.release()); |
+ |
+ // Shutdown the xmpp buzz connection. |
+ if (talk_mediator.get()) { |
+ VLOG(1) << "P2P: Mediator logout started."; |
+ talk_mediator->Logout(); |
+ VLOG(1) << "P2P: Mediator logout completed."; |
+ talk_mediator.reset(); |
+ |
+ // |server_notifier_thread_| is owned by |talk_mediator|. We NULL |
+ // it out here so as to not have a dangling pointer. |
+ server_notifier_thread_= NULL; |
+ VLOG(1) << "P2P: Mediator destroyed."; |
+ } |
+ |
+ delete notifier_options_; |
+} |
+ |
+void SyncNotifierImpl::AddObserver(SyncNotifierObserver* observer) { |
+ observer_list_.AddObserver(observer); |
+} |
+ |
+void SyncNotifierImpl::RemoveObserver(SyncNotifierObserver* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
+ |
+void SyncNotifierImpl::OnNotificationStateChange(bool notifications_enabled) { |
+ FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, |
+ OnNotificationStateChange(notifications_enabled)); |
+} |
+ |
+void SyncNotifierImpl::OnIncomingNotification( |
+ const IncomingNotificationData& notification_data) { |
+ browser_sync::sessions::TypePayloadMap model_types_with_payloads; |
+ |
+ // Check if the service url is a sync URL. An empty service URL is |
+ // treated as a legacy sync notification. If we're listening to |
+ // server-issued notifications, no need to check the service_url. |
+ if (notifier_options_->notification_method == |
+ notifier::NOTIFICATION_SERVER) { |
+ VLOG(1) << "Sync received server notification from " << |
+ notification_data.service_url << ": " << |
+ notification_data.service_specific_data; |
+ syncable::ModelTypeBitSet model_types; |
+ const std::string& model_type_list = notification_data.service_url; |
+ const std::string& notification_payload = |
+ notification_data.service_specific_data; |
+ |
+ if (!syncable::ModelTypeBitSetFromString(model_type_list, &model_types)) { |
+ LOG(DFATAL) << "Could not extract model types from server data."; |
+ model_types.set(); |
+ } |
+ |
+ model_types_with_payloads = |
+ browser_sync::sessions::MakeTypePayloadMapFromBitSet(model_types, |
+ notification_payload); |
+ } else if (notification_data.service_url.empty() || |
+ (notification_data.service_url == |
+ browser_sync::kSyncLegacyServiceUrl) || |
+ (notification_data.service_url == |
+ browser_sync::kSyncServiceUrl)) { |
+ VLOG(1) << "Sync received P2P notification."; |
+ |
+ // Catch for sync integration tests (uses p2p). Just set all enabled |
+ // datatypes. |
+ model_types_with_payloads = |
+ browser_sync::sessions::MakeTypePayloadMapFromBitSet( |
+ syncable::ModelTypeBitSetFromSet(enabled_types_), std::string()); |
+ } else { |
+ LOG(WARNING) << "Notification fron unexpected source: " |
+ << notification_data.service_url; |
+ } |
+ |
+ FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, |
+ OnIncomingNotification(model_types_with_payloads)); |
+} |
+ |
+void SyncNotifierImpl::WriteState(const std::string& state) { |
+ FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, |
+ StoreCookie(state)); |
+} |
+ |
+void SyncNotifierImpl::Login( |
+ const std::string& email, const std::string& token, |
+ const std::string& state) { |
+ if (notifier_options_->notification_method == |
+ notifier::NOTIFICATION_SERVER) { |
+ |
+ // |talk_mediator_| takes ownership of |sync_notifier_thread_| |
+ // but it is guaranteed that |sync_notifier_thread_| is destroyed only |
+ // when |talk_mediator_| is (see the comments in talk_mediator.h). |
+ server_notifier_thread_ = new sync_notifier::ServerNotifierThread( |
+ *notifier_options_, state, this); |
+ talk_mediator_.reset( |
+ new TalkMediatorImpl(server_notifier_thread_, |
+ notifier_options_->invalidate_xmpp_login, |
+ notifier_options_->allow_insecure_connection)); |
+ |
+ // Since we may be initialized more than once, make sure that any |
+ // newly created server notifier thread has the latest enabled types. |
+ server_notifier_thread_->UpdateEnabledTypes(enabled_types_); |
+ } else { |
+ notifier::MediatorThread* mediator_thread = |
+ new notifier::MediatorThreadImpl(*notifier_options_); |
+ talk_mediator_.reset( |
+ new TalkMediatorImpl(mediator_thread, |
+ notifier_options_->invalidate_xmpp_login, |
+ notifier_options_->allow_insecure_connection)); |
+ talk_mediator_->AddSubscribedServiceUrl(browser_sync::kSyncServiceUrl); |
+ server_notifier_thread_ = NULL; |
+ } |
+ talk_mediator()->SetDelegate(this); |
+ talk_mediator()->SetAuthToken(email, token, SYNC_SERVICE_NAME); |
+ talk_mediator()->Login(); |
+} |
+ |
+void SyncNotifierImpl::UpdateEnabledTypes(const syncable::ModelTypeSet& types) { |
+ enabled_types_ = types; |
+ if (server_notifier_thread_ != NULL) { |
+ server_notifier_thread_->UpdateEnabledTypes(types); |
+ } |
+} |
+ |
+void SyncNotifierImpl::SendNotification(bool* notification_pending) { |
+ if (!talk_mediator()) { |
+ VLOG(1) << "Not sending notification: shutting down (talk_mediator_ is " |
+ "NULL)"; |
+ return; |
+ } |
+ |
+ DCHECK_NE(notifier_options_->notification_method, |
+ notifier::NOTIFICATION_SERVER); |
+ VLOG(1) << "Sending XMPP notification..."; |
+ OutgoingNotificationData notification_data; |
+ notification_data.service_id = browser_sync::kSyncServiceId; |
+ notification_data.service_url = browser_sync::kSyncServiceUrl; |
+ notification_data.send_content = true; |
+ notification_data.priority = browser_sync::kSyncPriority; |
+ notification_data.write_to_cache_only = true; |
+ notification_data.service_specific_data = |
+ browser_sync::kSyncServiceSpecificData; |
+ notification_data.require_subscription = true; |
+ bool success = talk_mediator()->SendNotification(notification_data); |
+ if (success) { |
+ *notification_pending = false; |
+ VLOG(1) << "Sent XMPP notification"; |
+ } else { |
+ VLOG(1) << "Could not send XMPP notification"; |
+ } |
+} |
+} // namespace sync_notifier |