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
InvalidationNotifier(const notifier::NotifierOptions & notifier_options,const std::string & client_info)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
~InvalidationNotifier()36 InvalidationNotifier::~InvalidationNotifier() {
37 DCHECK(non_thread_safe_.CalledOnValidThread());
38 }
39
AddObserver(SyncNotifierObserver * observer)40 void InvalidationNotifier::AddObserver(SyncNotifierObserver* observer) {
41 DCHECK(non_thread_safe_.CalledOnValidThread());
42 observers_.AddObserver(observer);
43 }
44
RemoveObserver(SyncNotifierObserver * observer)45 void InvalidationNotifier::RemoveObserver(SyncNotifierObserver* observer) {
46 DCHECK(non_thread_safe_.CalledOnValidThread());
47 observers_.RemoveObserver(observer);
48 }
49
SetState(const std::string & state)50 void InvalidationNotifier::SetState(const std::string& state) {
51 DCHECK(non_thread_safe_.CalledOnValidThread());
52 invalidation_state_ = state;
53 }
54
UpdateCredentials(const std::string & email,const std::string & token)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
UpdateEnabledTypes(const syncable::ModelTypeSet & types)80 void InvalidationNotifier::UpdateEnabledTypes(
81 const syncable::ModelTypeSet& types) {
82 DCHECK(non_thread_safe_.CalledOnValidThread());
83 invalidation_client_.RegisterTypes(types);
84 }
85
SendNotification()86 void InvalidationNotifier::SendNotification() {
87 DCHECK(non_thread_safe_.CalledOnValidThread());
88 }
89
OnConnect(base::WeakPtr<talk_base::Task> base_task)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
OnDisconnect()110 void InvalidationNotifier::OnDisconnect() {
111 DCHECK(non_thread_safe_.CalledOnValidThread());
112 VLOG(1) << "OnDisconnect";
113 }
114
OnInvalidate(const syncable::ModelTypePayloadMap & type_payloads)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
OnSessionStatusChanged(bool has_session)122 void InvalidationNotifier::OnSessionStatusChanged(bool has_session) {
123 FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
124 OnNotificationStateChange(has_session));
125 }
126
WriteState(const std::string & state)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