OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/notifier/p2p_invalidator.h" | 5 #include "sync/notifier/p2p_invalidator.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "jingle/notifier/listener/push_client.h" | 13 #include "jingle/notifier/listener/push_client.h" |
14 #include "sync/notifier/invalidation_handler.h" | 14 #include "sync/notifier/invalidation_handler.h" |
15 #include "sync/notifier/invalidation_util.h" | 15 #include "sync/notifier/invalidation_util.h" |
16 | 16 |
17 namespace syncer { | 17 namespace syncer { |
18 | 18 |
19 const char kSyncP2PNotificationChannel[] = "http://www.google.com/chrome/sync"; | 19 const char kSyncP2PNotificationChannel[] = "http://www.google.com/chrome/sync"; |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 const char kNotifySelf[] = "notifySelf"; | 23 const char kNotifySelf[] = "notifySelf"; |
24 const char kNotifyOthers[] = "notifyOthers"; | 24 const char kNotifyOthers[] = "notifyOthers"; |
25 const char kNotifyAll[] = "notifyAll"; | 25 const char kNotifyAll[] = "notifyAll"; |
26 | 26 |
27 const char kSenderIdKey[] = "senderId"; | 27 const char kSenderIdKey[] = "senderId"; |
28 const char kNotificationTypeKey[] = "notificationType"; | 28 const char kNotificationTypeKey[] = "notificationType"; |
29 const char kIdInvalidationMapKey[] = "idInvalidationMap"; | 29 const char kIdInvalidationMapKey[] = "idInvalidationMap"; |
30 const char kSourceKey[] = "source"; | |
31 | 30 |
32 } // namespace | 31 } // namespace |
33 | 32 |
34 std::string P2PNotificationTargetToString(P2PNotificationTarget target) { | 33 std::string P2PNotificationTargetToString(P2PNotificationTarget target) { |
35 switch (target) { | 34 switch (target) { |
36 case NOTIFY_SELF: | 35 case NOTIFY_SELF: |
37 return kNotifySelf; | 36 return kNotifySelf; |
38 case NOTIFY_OTHERS: | 37 case NOTIFY_OTHERS: |
39 return kNotifyOthers; | 38 return kNotifyOthers; |
40 case NOTIFY_ALL: | 39 case NOTIFY_ALL: |
(...skipping 12 matching lines...) Expand all Loading... |
53 if (target_str == kNotifyOthers) { | 52 if (target_str == kNotifyOthers) { |
54 return NOTIFY_OTHERS; | 53 return NOTIFY_OTHERS; |
55 } | 54 } |
56 if (target_str == kNotifyAll) { | 55 if (target_str == kNotifyAll) { |
57 return NOTIFY_ALL; | 56 return NOTIFY_ALL; |
58 } | 57 } |
59 LOG(WARNING) << "Could not parse " << target_str; | 58 LOG(WARNING) << "Could not parse " << target_str; |
60 return NOTIFY_SELF; | 59 return NOTIFY_SELF; |
61 } | 60 } |
62 | 61 |
63 IncomingInvalidationSource P2PNotificationSourceFromInteger(int source_num) { | |
64 if (source_num == LOCAL_INVALIDATION) { | |
65 return LOCAL_INVALIDATION; | |
66 } | |
67 return REMOTE_INVALIDATION; | |
68 } | |
69 | |
70 P2PNotificationData::P2PNotificationData() | 62 P2PNotificationData::P2PNotificationData() |
71 : target_(NOTIFY_SELF), source_(REMOTE_INVALIDATION) {} | 63 : target_(NOTIFY_SELF) {} |
72 | 64 |
73 P2PNotificationData::P2PNotificationData( | 65 P2PNotificationData::P2PNotificationData( |
74 const std::string& sender_id, | 66 const std::string& sender_id, |
75 P2PNotificationTarget target, | 67 P2PNotificationTarget target, |
76 const ObjectIdInvalidationMap& invalidation_map, | 68 const ObjectIdInvalidationMap& invalidation_map) |
77 IncomingInvalidationSource source) | |
78 : sender_id_(sender_id), | 69 : sender_id_(sender_id), |
79 target_(target), | 70 target_(target), |
80 invalidation_map_(invalidation_map), | 71 invalidation_map_(invalidation_map) {} |
81 source_(source) {} | |
82 | 72 |
83 P2PNotificationData::~P2PNotificationData() {} | 73 P2PNotificationData::~P2PNotificationData() {} |
84 | 74 |
85 bool P2PNotificationData::IsTargeted(const std::string& id) const { | 75 bool P2PNotificationData::IsTargeted(const std::string& id) const { |
86 switch (target_) { | 76 switch (target_) { |
87 case NOTIFY_SELF: | 77 case NOTIFY_SELF: |
88 return sender_id_ == id; | 78 return sender_id_ == id; |
89 case NOTIFY_OTHERS: | 79 case NOTIFY_OTHERS: |
90 return sender_id_ != id; | 80 return sender_id_ != id; |
91 case NOTIFY_ALL: | 81 case NOTIFY_ALL: |
92 return true; | 82 return true; |
93 default: | 83 default: |
94 NOTREACHED(); | 84 NOTREACHED(); |
95 return false; | 85 return false; |
96 } | 86 } |
97 } | 87 } |
98 | 88 |
99 const ObjectIdInvalidationMap& | 89 const ObjectIdInvalidationMap& |
100 P2PNotificationData::GetIdInvalidationMap() const { | 90 P2PNotificationData::GetIdInvalidationMap() const { |
101 return invalidation_map_; | 91 return invalidation_map_; |
102 } | 92 } |
103 | 93 |
104 IncomingInvalidationSource P2PNotificationData::GetSource() const { | |
105 return source_; | |
106 } | |
107 | |
108 bool P2PNotificationData::Equals(const P2PNotificationData& other) const { | 94 bool P2PNotificationData::Equals(const P2PNotificationData& other) const { |
109 return | 95 return |
110 (sender_id_ == other.sender_id_) && | 96 (sender_id_ == other.sender_id_) && |
111 (target_ == other.target_) && | 97 (target_ == other.target_) && |
112 ObjectIdInvalidationMapEquals(invalidation_map_, | 98 ObjectIdInvalidationMapEquals(invalidation_map_, |
113 other.invalidation_map_) && | 99 other.invalidation_map_); |
114 (source_ == other.source_); | |
115 } | 100 } |
116 | 101 |
117 std::string P2PNotificationData::ToString() const { | 102 std::string P2PNotificationData::ToString() const { |
118 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); | 103 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); |
119 dict->SetString(kSenderIdKey, sender_id_); | 104 dict->SetString(kSenderIdKey, sender_id_); |
120 dict->SetString(kNotificationTypeKey, | 105 dict->SetString(kNotificationTypeKey, |
121 P2PNotificationTargetToString(target_)); | 106 P2PNotificationTargetToString(target_)); |
122 dict->Set(kIdInvalidationMapKey, | 107 dict->Set(kIdInvalidationMapKey, |
123 ObjectIdInvalidationMapToValue(invalidation_map_).release()); | 108 ObjectIdInvalidationMapToValue(invalidation_map_).release()); |
124 dict->SetInteger(kSourceKey, source_); | |
125 std::string json; | 109 std::string json; |
126 base::JSONWriter::Write(dict.get(), &json); | 110 base::JSONWriter::Write(dict.get(), &json); |
127 return json; | 111 return json; |
128 } | 112 } |
129 | 113 |
130 bool P2PNotificationData::ResetFromString(const std::string& str) { | 114 bool P2PNotificationData::ResetFromString(const std::string& str) { |
131 scoped_ptr<Value> data_value(base::JSONReader::Read(str)); | 115 scoped_ptr<Value> data_value(base::JSONReader::Read(str)); |
132 const base::DictionaryValue* data_dict = NULL; | 116 const base::DictionaryValue* data_dict = NULL; |
133 if (!data_value.get() || !data_value->GetAsDictionary(&data_dict)) { | 117 if (!data_value.get() || !data_value->GetAsDictionary(&data_dict)) { |
134 LOG(WARNING) << "Could not parse " << str << " as a dictionary"; | 118 LOG(WARNING) << "Could not parse " << str << " as a dictionary"; |
135 return false; | 119 return false; |
136 } | 120 } |
137 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) { | 121 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) { |
138 LOG(WARNING) << "Could not find string value for " << kSenderIdKey; | 122 LOG(WARNING) << "Could not find string value for " << kSenderIdKey; |
139 } | 123 } |
140 std::string target_str; | 124 std::string target_str; |
141 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) { | 125 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) { |
142 LOG(WARNING) << "Could not find string value for " | 126 LOG(WARNING) << "Could not find string value for " |
143 << kNotificationTypeKey; | 127 << kNotificationTypeKey; |
144 } | 128 } |
145 target_ = P2PNotificationTargetFromString(target_str); | 129 target_ = P2PNotificationTargetFromString(target_str); |
146 const base::ListValue* invalidation_map_list = NULL; | 130 const base::ListValue* invalidation_map_list = NULL; |
147 if (!data_dict->GetList(kIdInvalidationMapKey, &invalidation_map_list) || | 131 if (!data_dict->GetList(kIdInvalidationMapKey, &invalidation_map_list) || |
148 !ObjectIdInvalidationMapFromValue(*invalidation_map_list, | 132 !ObjectIdInvalidationMapFromValue(*invalidation_map_list, |
149 &invalidation_map_)) { | 133 &invalidation_map_)) { |
150 LOG(WARNING) << "Could not parse " << kIdInvalidationMapKey; | 134 LOG(WARNING) << "Could not parse " << kIdInvalidationMapKey; |
151 } | 135 } |
152 int source_num = 0; | |
153 if (!data_dict->GetInteger(kSourceKey, &source_num)) { | |
154 LOG(WARNING) << "Could not find integer value for " << kSourceKey; | |
155 } | |
156 source_ = P2PNotificationSourceFromInteger(source_num); | |
157 return true; | 136 return true; |
158 } | 137 } |
159 | 138 |
160 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client, | 139 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client, |
161 P2PNotificationTarget send_notification_target) | 140 P2PNotificationTarget send_notification_target) |
162 : push_client_(push_client.Pass()), | 141 : push_client_(push_client.Pass()), |
163 logged_in_(false), | 142 logged_in_(false), |
164 notifications_enabled_(false), | 143 notifications_enabled_(false), |
165 send_notification_target_(send_notification_target) { | 144 send_notification_target_(send_notification_target) { |
166 DCHECK(send_notification_target_ == NOTIFY_OTHERS || | 145 DCHECK(send_notification_target_ == NOTIFY_OTHERS || |
(...skipping 16 matching lines...) Expand all Loading... |
183 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411). | 162 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411). |
184 DCHECK(thread_checker_.CalledOnValidThread()); | 163 DCHECK(thread_checker_.CalledOnValidThread()); |
185 ObjectIdSet new_ids; | 164 ObjectIdSet new_ids; |
186 const ObjectIdSet& old_ids = registrar_.GetRegisteredIds(handler); | 165 const ObjectIdSet& old_ids = registrar_.GetRegisteredIds(handler); |
187 std::set_difference(ids.begin(), ids.end(), | 166 std::set_difference(ids.begin(), ids.end(), |
188 old_ids.begin(), old_ids.end(), | 167 old_ids.begin(), old_ids.end(), |
189 std::inserter(new_ids, new_ids.end()), | 168 std::inserter(new_ids, new_ids.end()), |
190 ObjectIdLessThan()); | 169 ObjectIdLessThan()); |
191 registrar_.UpdateRegisteredIds(handler, ids); | 170 registrar_.UpdateRegisteredIds(handler, ids); |
192 const P2PNotificationData notification_data( | 171 const P2PNotificationData notification_data( |
193 unique_id_, NOTIFY_SELF, ObjectIdSetToInvalidationMap(new_ids, ""), | 172 unique_id_, NOTIFY_SELF, ObjectIdSetToInvalidationMap(new_ids, "")); |
194 REMOTE_INVALIDATION); | |
195 SendNotificationData(notification_data); | 173 SendNotificationData(notification_data); |
196 } | 174 } |
197 | 175 |
198 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) { | 176 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) { |
199 DCHECK(thread_checker_.CalledOnValidThread()); | 177 DCHECK(thread_checker_.CalledOnValidThread()); |
200 registrar_.UnregisterHandler(handler); | 178 registrar_.UnregisterHandler(handler); |
201 } | 179 } |
202 | 180 |
203 InvalidatorState P2PInvalidator::GetInvalidatorState() const { | 181 InvalidatorState P2PInvalidator::GetInvalidatorState() const { |
204 DCHECK(thread_checker_.CalledOnValidThread()); | 182 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 19 matching lines...) Expand all Loading... |
224 // If already logged in, the new credentials will take effect on the | 202 // If already logged in, the new credentials will take effect on the |
225 // next reconnection. | 203 // next reconnection. |
226 push_client_->UpdateCredentials(email, token); | 204 push_client_->UpdateCredentials(email, token); |
227 logged_in_ = true; | 205 logged_in_ = true; |
228 } | 206 } |
229 | 207 |
230 void P2PInvalidator::SendInvalidation( | 208 void P2PInvalidator::SendInvalidation( |
231 const ObjectIdInvalidationMap& invalidation_map) { | 209 const ObjectIdInvalidationMap& invalidation_map) { |
232 DCHECK(thread_checker_.CalledOnValidThread()); | 210 DCHECK(thread_checker_.CalledOnValidThread()); |
233 const P2PNotificationData notification_data( | 211 const P2PNotificationData notification_data( |
234 unique_id_, send_notification_target_, invalidation_map, | 212 unique_id_, send_notification_target_, invalidation_map); |
235 REMOTE_INVALIDATION); | |
236 SendNotificationData(notification_data); | 213 SendNotificationData(notification_data); |
237 } | 214 } |
238 | 215 |
239 void P2PInvalidator::OnNotificationsEnabled() { | 216 void P2PInvalidator::OnNotificationsEnabled() { |
240 DCHECK(thread_checker_.CalledOnValidThread()); | 217 DCHECK(thread_checker_.CalledOnValidThread()); |
241 bool just_turned_on = (notifications_enabled_ == false); | 218 bool just_turned_on = (notifications_enabled_ == false); |
242 notifications_enabled_ = true; | 219 notifications_enabled_ = true; |
243 registrar_.UpdateInvalidatorState(INVALIDATIONS_ENABLED); | 220 registrar_.UpdateInvalidatorState(INVALIDATIONS_ENABLED); |
244 if (just_turned_on) { | 221 if (just_turned_on) { |
245 const P2PNotificationData notification_data( | 222 const P2PNotificationData notification_data( |
246 unique_id_, NOTIFY_SELF, | 223 unique_id_, NOTIFY_SELF, |
247 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), ""), | 224 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), "")); |
248 REMOTE_INVALIDATION); | |
249 SendNotificationData(notification_data); | 225 SendNotificationData(notification_data); |
250 } | 226 } |
251 } | 227 } |
252 | 228 |
253 void P2PInvalidator::OnNotificationsDisabled( | 229 void P2PInvalidator::OnNotificationsDisabled( |
254 notifier::NotificationsDisabledReason reason) { | 230 notifier::NotificationsDisabledReason reason) { |
255 DCHECK(thread_checker_.CalledOnValidThread()); | 231 DCHECK(thread_checker_.CalledOnValidThread()); |
256 registrar_.UpdateInvalidatorState(FromNotifierReason(reason)); | 232 registrar_.UpdateInvalidatorState(FromNotifierReason(reason)); |
257 } | 233 } |
258 | 234 |
(...skipping 13 matching lines...) Expand all Loading... |
272 LOG(WARNING) << "Notification from unexpected source " | 248 LOG(WARNING) << "Notification from unexpected source " |
273 << notification.channel; | 249 << notification.channel; |
274 } | 250 } |
275 P2PNotificationData notification_data; | 251 P2PNotificationData notification_data; |
276 if (!notification_data.ResetFromString(notification.data)) { | 252 if (!notification_data.ResetFromString(notification.data)) { |
277 LOG(WARNING) << "Could not parse notification data from " | 253 LOG(WARNING) << "Could not parse notification data from " |
278 << notification.data; | 254 << notification.data; |
279 notification_data = | 255 notification_data = |
280 P2PNotificationData( | 256 P2PNotificationData( |
281 unique_id_, NOTIFY_ALL, | 257 unique_id_, NOTIFY_ALL, |
282 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), ""), | 258 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), "")); |
283 REMOTE_INVALIDATION); | |
284 } | 259 } |
285 if (!notification_data.IsTargeted(unique_id_)) { | 260 if (!notification_data.IsTargeted(unique_id_)) { |
286 DVLOG(1) << "Not a target of the notification -- " | 261 DVLOG(1) << "Not a target of the notification -- " |
287 << "not emitting notification"; | 262 << "not emitting notification"; |
288 return; | 263 return; |
289 } | 264 } |
290 registrar_.DispatchInvalidationsToHandlers( | 265 registrar_.DispatchInvalidationsToHandlers( |
291 notification_data.GetIdInvalidationMap(), | 266 notification_data.GetIdInvalidationMap()); |
292 REMOTE_INVALIDATION); | |
293 } | 267 } |
294 | 268 |
295 void P2PInvalidator::SendNotificationDataForTest( | 269 void P2PInvalidator::SendNotificationDataForTest( |
296 const P2PNotificationData& notification_data) { | 270 const P2PNotificationData& notification_data) { |
297 DCHECK(thread_checker_.CalledOnValidThread()); | 271 DCHECK(thread_checker_.CalledOnValidThread()); |
298 SendNotificationData(notification_data); | 272 SendNotificationData(notification_data); |
299 } | 273 } |
300 | 274 |
301 void P2PInvalidator::SendNotificationData( | 275 void P2PInvalidator::SendNotificationData( |
302 const P2PNotificationData& notification_data) { | 276 const P2PNotificationData& notification_data) { |
303 DCHECK(thread_checker_.CalledOnValidThread()); | 277 DCHECK(thread_checker_.CalledOnValidThread()); |
304 if (notification_data.GetIdInvalidationMap().empty()) { | 278 if (notification_data.GetIdInvalidationMap().empty()) { |
305 DVLOG(1) << "Not sending XMPP notification with empty state map: " | 279 DVLOG(1) << "Not sending XMPP notification with empty state map: " |
306 << notification_data.ToString(); | 280 << notification_data.ToString(); |
307 return; | 281 return; |
308 } | 282 } |
309 notifier::Notification notification; | 283 notifier::Notification notification; |
310 notification.channel = kSyncP2PNotificationChannel; | 284 notification.channel = kSyncP2PNotificationChannel; |
311 notification.data = notification_data.ToString(); | 285 notification.data = notification_data.ToString(); |
312 DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); | 286 DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); |
313 push_client_->SendNotification(notification); | 287 push_client_->SendNotification(notification); |
314 } | 288 } |
315 | 289 |
316 } // namespace syncer | 290 } // namespace syncer |
OLD | NEW |