1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sync/notifier/invalidation_notifier.h" 6 7 #include "base/logging.h" 8 #include "base/message_loop_proxy.h" 9 #include "chrome/browser/sync/notifier/sync_notifier_observer.h" 10 #include "chrome/browser/sync/protocol/service_constants.h" 11 #include "chrome/browser/sync/syncable/model_type_payload_map.h" 12 #include "jingle/notifier/base/const_communicator.h" 13 #include "jingle/notifier/base/notifier_options_util.h" 14 #include "jingle/notifier/communicator/connection_options.h" 15 #include "net/base/host_port_pair.h" 16 #include "net/url_request/url_request_context.h" 17 #include "talk/xmpp/jid.h" 18 #include "talk/xmpp/xmppclientsettings.h" 19 20 namespace sync_notifier { 21 22 InvalidationNotifier::InvalidationNotifier( 23 const notifier::NotifierOptions& notifier_options, 24 const std::string& client_info) 25 : state_(STOPPED), 26 notifier_options_(notifier_options), 27 client_info_(client_info) { 28 DCHECK_EQ(notifier::NOTIFICATION_SERVER, 29 notifier_options.notification_method); 30 DCHECK(notifier_options_.request_context_getter); 31 // TODO(akalin): Replace NonThreadSafe checks with IO thread checks. 32 DCHECK(notifier_options_.request_context_getter->GetIOMessageLoopProxy()-> 33 BelongsToCurrentThread()); 34 } 35 36 InvalidationNotifier::~InvalidationNotifier() { 37 DCHECK(non_thread_safe_.CalledOnValidThread()); 38 } 39 40 void InvalidationNotifier::AddObserver(SyncNotifierObserver* observer) { 41 DCHECK(non_thread_safe_.CalledOnValidThread()); 42 observers_.AddObserver(observer); 43 } 44 45 void InvalidationNotifier::RemoveObserver(SyncNotifierObserver* observer) { 46 DCHECK(non_thread_safe_.CalledOnValidThread()); 47 observers_.RemoveObserver(observer); 48 } 49 50 void InvalidationNotifier::SetState(const std::string& state) { 51 DCHECK(non_thread_safe_.CalledOnValidThread()); 52 invalidation_state_ = state; 53 } 54 55 void InvalidationNotifier::UpdateCredentials( 56 const std::string& email, const std::string& token) { 57 DCHECK(non_thread_safe_.CalledOnValidThread()); 58 VLOG(1) << "Updating credentials for " << email; 59 buzz::XmppClientSettings xmpp_client_settings = 60 notifier::MakeXmppClientSettings(notifier_options_, 61 email, token, SYNC_SERVICE_NAME); 62 if (state_ >= CONNECTING) { 63 login_->UpdateXmppSettings(xmpp_client_settings); 64 } else { 65 notifier::ConnectionOptions options; 66 VLOG(1) << "First time updating credentials: connecting"; 67 login_.reset( 68 new notifier::Login(this, 69 xmpp_client_settings, 70 notifier::ConnectionOptions(), 71 notifier_options_.request_context_getter, 72 notifier::GetServerList(notifier_options_), 73 notifier_options_.try_ssltcp_first, 74 notifier_options_.auth_mechanism)); 75 login_->StartConnection(); 76 state_ = CONNECTING; 77 } 78 } 79 80 void InvalidationNotifier::UpdateEnabledTypes( 81 const syncable::ModelTypeSet& types) { 82 DCHECK(non_thread_safe_.CalledOnValidThread()); 83 invalidation_client_.RegisterTypes(types); 84 } 85 86 void InvalidationNotifier::SendNotification() { 87 DCHECK(non_thread_safe_.CalledOnValidThread()); 88 } 89 90 void InvalidationNotifier::OnConnect( 91 base::WeakPtr<talk_base::Task> base_task) { 92 DCHECK(non_thread_safe_.CalledOnValidThread()); 93 VLOG(1) << "OnConnect"; 94 if (state_ >= STARTED) { 95 invalidation_client_.ChangeBaseTask(base_task); 96 } else { 97 VLOG(1) << "First time connecting: starting invalidation client"; 98 // TODO(akalin): Make cache_guid() part of the client ID. If we 99 // do so and we somehow propagate it up to the server somehow, we 100 // can make it so that we won't receive any notifications that 101 // were generated from our own changes. 102 const std::string kClientId = "invalidation_notifier"; 103 invalidation_client_.Start( 104 kClientId, client_info_, invalidation_state_, this, this, base_task); 105 invalidation_state_.clear(); 106 state_ = STARTED; 107 } 108 } 109 110 void InvalidationNotifier::OnDisconnect() { 111 DCHECK(non_thread_safe_.CalledOnValidThread()); 112 VLOG(1) << "OnDisconnect"; 113 } 114 115 void InvalidationNotifier::OnInvalidate( 116 const syncable::ModelTypePayloadMap& type_payloads) { 117 DCHECK(non_thread_safe_.CalledOnValidThread()); 118 FOR_EACH_OBSERVER(SyncNotifierObserver, observers_, 119 OnIncomingNotification(type_payloads)); 120 } 121 122 void InvalidationNotifier::OnSessionStatusChanged(bool has_session) { 123 FOR_EACH_OBSERVER(SyncNotifierObserver, observers_, 124 OnNotificationStateChange(has_session)); 125 } 126 127 void InvalidationNotifier::WriteState(const std::string& state) { 128 DCHECK(non_thread_safe_.CalledOnValidThread()); 129 VLOG(1) << "WriteState"; 130 FOR_EACH_OBSERVER(SyncNotifierObserver, observers_, StoreState(state)); 131 } 132 133 } // namespace sync_notifier 134