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/internal_api/public/base/model_type_state_map.h" | |
15 #include "sync/notifier/invalidation_handler.h" | 14 #include "sync/notifier/invalidation_handler.h" |
16 #include "sync/notifier/invalidation_util.h" | 15 #include "sync/notifier/invalidation_util.h" |
17 | 16 |
18 namespace syncer { | 17 namespace syncer { |
19 | 18 |
20 const char kSyncP2PNotificationChannel[] = "http://www.google.com/chrome/sync"; | 19 const char kSyncP2PNotificationChannel[] = "http://www.google.com/chrome/sync"; |
21 | 20 |
22 namespace { | 21 namespace { |
23 | 22 |
24 const char kNotifySelf[] = "notifySelf"; | 23 const char kNotifySelf[] = "notifySelf"; |
25 const char kNotifyOthers[] = "notifyOthers"; | 24 const char kNotifyOthers[] = "notifyOthers"; |
26 const char kNotifyAll[] = "notifyAll"; | 25 const char kNotifyAll[] = "notifyAll"; |
27 | 26 |
28 const char kSenderIdKey[] = "senderId"; | 27 const char kSenderIdKey[] = "senderId"; |
29 const char kNotificationTypeKey[] = "notificationType"; | 28 const char kNotificationTypeKey[] = "notificationType"; |
30 const char kIdStateMapKey[] = "idStateMap"; | 29 const char kIdInvalidationMapKey[] = "idInvalidationMap"; |
31 const char kSourceKey[] = "source"; | 30 const char kSourceKey[] = "source"; |
32 | 31 |
33 } // namespace | 32 } // namespace |
34 | 33 |
35 std::string P2PNotificationTargetToString(P2PNotificationTarget target) { | 34 std::string P2PNotificationTargetToString(P2PNotificationTarget target) { |
36 switch (target) { | 35 switch (target) { |
37 case NOTIFY_SELF: | 36 case NOTIFY_SELF: |
38 return kNotifySelf; | 37 return kNotifySelf; |
39 case NOTIFY_OTHERS: | 38 case NOTIFY_OTHERS: |
40 return kNotifyOthers; | 39 return kNotifyOthers; |
(...skipping 26 matching lines...) Expand all Loading... |
67 } | 66 } |
68 return REMOTE_INVALIDATION; | 67 return REMOTE_INVALIDATION; |
69 } | 68 } |
70 | 69 |
71 P2PNotificationData::P2PNotificationData() | 70 P2PNotificationData::P2PNotificationData() |
72 : target_(NOTIFY_SELF), source_(REMOTE_INVALIDATION) {} | 71 : target_(NOTIFY_SELF), source_(REMOTE_INVALIDATION) {} |
73 | 72 |
74 P2PNotificationData::P2PNotificationData( | 73 P2PNotificationData::P2PNotificationData( |
75 const std::string& sender_id, | 74 const std::string& sender_id, |
76 P2PNotificationTarget target, | 75 P2PNotificationTarget target, |
77 const ObjectIdStateMap& id_state_map, | 76 const ObjectIdInvalidationMap& invalidation_map, |
78 IncomingInvalidationSource source) | 77 IncomingInvalidationSource source) |
79 : sender_id_(sender_id), | 78 : sender_id_(sender_id), |
80 target_(target), | 79 target_(target), |
81 id_state_map_(id_state_map), | 80 invalidation_map_(invalidation_map), |
82 source_(source) {} | 81 source_(source) {} |
83 | 82 |
84 P2PNotificationData::~P2PNotificationData() {} | 83 P2PNotificationData::~P2PNotificationData() {} |
85 | 84 |
86 bool P2PNotificationData::IsTargeted(const std::string& id) const { | 85 bool P2PNotificationData::IsTargeted(const std::string& id) const { |
87 switch (target_) { | 86 switch (target_) { |
88 case NOTIFY_SELF: | 87 case NOTIFY_SELF: |
89 return sender_id_ == id; | 88 return sender_id_ == id; |
90 case NOTIFY_OTHERS: | 89 case NOTIFY_OTHERS: |
91 return sender_id_ != id; | 90 return sender_id_ != id; |
92 case NOTIFY_ALL: | 91 case NOTIFY_ALL: |
93 return true; | 92 return true; |
94 default: | 93 default: |
95 NOTREACHED(); | 94 NOTREACHED(); |
96 return false; | 95 return false; |
97 } | 96 } |
98 } | 97 } |
99 | 98 |
100 const ObjectIdStateMap& P2PNotificationData::GetIdStateMap() const { | 99 const ObjectIdInvalidationMap& |
101 return id_state_map_; | 100 P2PNotificationData::GetIdInvalidationMap() const { |
| 101 return invalidation_map_; |
102 } | 102 } |
103 | 103 |
104 IncomingInvalidationSource P2PNotificationData::GetSource() const { | 104 IncomingInvalidationSource P2PNotificationData::GetSource() const { |
105 return source_; | 105 return source_; |
106 } | 106 } |
107 | 107 |
108 bool P2PNotificationData::Equals(const P2PNotificationData& other) const { | 108 bool P2PNotificationData::Equals(const P2PNotificationData& other) const { |
109 return | 109 return |
110 (sender_id_ == other.sender_id_) && | 110 (sender_id_ == other.sender_id_) && |
111 (target_ == other.target_) && | 111 (target_ == other.target_) && |
112 ObjectIdStateMapEquals(id_state_map_, other.id_state_map_) && | 112 ObjectIdInvalidationMapEquals(invalidation_map_, |
| 113 other.invalidation_map_) && |
113 (source_ == other.source_); | 114 (source_ == other.source_); |
114 } | 115 } |
115 | 116 |
116 std::string P2PNotificationData::ToString() const { | 117 std::string P2PNotificationData::ToString() const { |
117 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); | 118 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); |
118 dict->SetString(kSenderIdKey, sender_id_); | 119 dict->SetString(kSenderIdKey, sender_id_); |
119 dict->SetString(kNotificationTypeKey, | 120 dict->SetString(kNotificationTypeKey, |
120 P2PNotificationTargetToString(target_)); | 121 P2PNotificationTargetToString(target_)); |
121 dict->Set(kIdStateMapKey, ObjectIdStateMapToValue(id_state_map_).release()); | 122 dict->Set(kIdInvalidationMapKey, |
| 123 ObjectIdInvalidationMapToValue(invalidation_map_).release()); |
122 dict->SetInteger(kSourceKey, source_); | 124 dict->SetInteger(kSourceKey, source_); |
123 std::string json; | 125 std::string json; |
124 base::JSONWriter::Write(dict.get(), &json); | 126 base::JSONWriter::Write(dict.get(), &json); |
125 return json; | 127 return json; |
126 } | 128 } |
127 | 129 |
128 bool P2PNotificationData::ResetFromString(const std::string& str) { | 130 bool P2PNotificationData::ResetFromString(const std::string& str) { |
129 scoped_ptr<Value> data_value(base::JSONReader::Read(str)); | 131 scoped_ptr<Value> data_value(base::JSONReader::Read(str)); |
130 const base::DictionaryValue* data_dict = NULL; | 132 const base::DictionaryValue* data_dict = NULL; |
131 if (!data_value.get() || !data_value->GetAsDictionary(&data_dict)) { | 133 if (!data_value.get() || !data_value->GetAsDictionary(&data_dict)) { |
132 LOG(WARNING) << "Could not parse " << str << " as a dictionary"; | 134 LOG(WARNING) << "Could not parse " << str << " as a dictionary"; |
133 return false; | 135 return false; |
134 } | 136 } |
135 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) { | 137 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) { |
136 LOG(WARNING) << "Could not find string value for " << kSenderIdKey; | 138 LOG(WARNING) << "Could not find string value for " << kSenderIdKey; |
137 } | 139 } |
138 std::string target_str; | 140 std::string target_str; |
139 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) { | 141 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) { |
140 LOG(WARNING) << "Could not find string value for " | 142 LOG(WARNING) << "Could not find string value for " |
141 << kNotificationTypeKey; | 143 << kNotificationTypeKey; |
142 } | 144 } |
143 target_ = P2PNotificationTargetFromString(target_str); | 145 target_ = P2PNotificationTargetFromString(target_str); |
144 const base::ListValue* id_state_map_list = NULL; | 146 const base::ListValue* invalidation_map_list = NULL; |
145 if (!data_dict->GetList(kIdStateMapKey, &id_state_map_list) || | 147 if (!data_dict->GetList(kIdInvalidationMapKey, &invalidation_map_list) || |
146 !ObjectIdStateMapFromValue(*id_state_map_list, &id_state_map_)) { | 148 !ObjectIdInvalidationMapFromValue(*invalidation_map_list, |
147 LOG(WARNING) << "Could not parse " << kIdStateMapKey; | 149 &invalidation_map_)) { |
| 150 LOG(WARNING) << "Could not parse " << kIdInvalidationMapKey; |
148 } | 151 } |
149 int source_num = 0; | 152 int source_num = 0; |
150 if (!data_dict->GetInteger(kSourceKey, &source_num)) { | 153 if (!data_dict->GetInteger(kSourceKey, &source_num)) { |
151 LOG(WARNING) << "Could not find integer value for " << kSourceKey; | 154 LOG(WARNING) << "Could not find integer value for " << kSourceKey; |
152 } | 155 } |
153 source_ = P2PNotificationSourceFromInteger(source_num); | 156 source_ = P2PNotificationSourceFromInteger(source_num); |
154 return true; | 157 return true; |
155 } | 158 } |
156 | 159 |
157 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client, | 160 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client, |
(...skipping 22 matching lines...) Expand all Loading... |
180 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411). | 183 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411). |
181 DCHECK(thread_checker_.CalledOnValidThread()); | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
182 ObjectIdSet new_ids; | 185 ObjectIdSet new_ids; |
183 const ObjectIdSet& old_ids = registrar_.GetRegisteredIds(handler); | 186 const ObjectIdSet& old_ids = registrar_.GetRegisteredIds(handler); |
184 std::set_difference(ids.begin(), ids.end(), | 187 std::set_difference(ids.begin(), ids.end(), |
185 old_ids.begin(), old_ids.end(), | 188 old_ids.begin(), old_ids.end(), |
186 std::inserter(new_ids, new_ids.end()), | 189 std::inserter(new_ids, new_ids.end()), |
187 ObjectIdLessThan()); | 190 ObjectIdLessThan()); |
188 registrar_.UpdateRegisteredIds(handler, ids); | 191 registrar_.UpdateRegisteredIds(handler, ids); |
189 const P2PNotificationData notification_data( | 192 const P2PNotificationData notification_data( |
190 unique_id_, NOTIFY_SELF, ObjectIdSetToStateMap(new_ids, ""), | 193 unique_id_, NOTIFY_SELF, ObjectIdSetToInvalidationMap(new_ids, ""), |
191 REMOTE_INVALIDATION); | 194 REMOTE_INVALIDATION); |
192 SendNotificationData(notification_data); | 195 SendNotificationData(notification_data); |
193 } | 196 } |
194 | 197 |
195 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) { | 198 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) { |
196 DCHECK(thread_checker_.CalledOnValidThread()); | 199 DCHECK(thread_checker_.CalledOnValidThread()); |
197 registrar_.UnregisterHandler(handler); | 200 registrar_.UnregisterHandler(handler); |
198 } | 201 } |
199 | 202 |
200 InvalidatorState P2PInvalidator::GetInvalidatorState() const { | 203 InvalidatorState P2PInvalidator::GetInvalidatorState() const { |
(...skipping 21 matching lines...) Expand all Loading... |
222 // used in p2p mode (which is only used in testing). | 225 // used in p2p mode (which is only used in testing). |
223 subscription.from = email; | 226 subscription.from = email; |
224 push_client_->UpdateSubscriptions( | 227 push_client_->UpdateSubscriptions( |
225 notifier::SubscriptionList(1, subscription)); | 228 notifier::SubscriptionList(1, subscription)); |
226 // If already logged in, the new credentials will take effect on the | 229 // If already logged in, the new credentials will take effect on the |
227 // next reconnection. | 230 // next reconnection. |
228 push_client_->UpdateCredentials(email, token); | 231 push_client_->UpdateCredentials(email, token); |
229 logged_in_ = true; | 232 logged_in_ = true; |
230 } | 233 } |
231 | 234 |
232 void P2PInvalidator::SendInvalidation(const ObjectIdStateMap& id_state_map) { | 235 void P2PInvalidator::SendInvalidation( |
| 236 const ObjectIdInvalidationMap& invalidation_map) { |
233 DCHECK(thread_checker_.CalledOnValidThread()); | 237 DCHECK(thread_checker_.CalledOnValidThread()); |
234 const P2PNotificationData notification_data( | 238 const P2PNotificationData notification_data( |
235 unique_id_, send_notification_target_, id_state_map, | 239 unique_id_, send_notification_target_, invalidation_map, |
236 REMOTE_INVALIDATION); | 240 REMOTE_INVALIDATION); |
237 SendNotificationData(notification_data); | 241 SendNotificationData(notification_data); |
238 } | 242 } |
239 | 243 |
240 void P2PInvalidator::OnNotificationsEnabled() { | 244 void P2PInvalidator::OnNotificationsEnabled() { |
241 DCHECK(thread_checker_.CalledOnValidThread()); | 245 DCHECK(thread_checker_.CalledOnValidThread()); |
242 bool just_turned_on = (notifications_enabled_ == false); | 246 bool just_turned_on = (notifications_enabled_ == false); |
243 notifications_enabled_ = true; | 247 notifications_enabled_ = true; |
244 registrar_.UpdateInvalidatorState(INVALIDATIONS_ENABLED); | 248 registrar_.UpdateInvalidatorState(INVALIDATIONS_ENABLED); |
245 if (just_turned_on) { | 249 if (just_turned_on) { |
246 const P2PNotificationData notification_data( | 250 const P2PNotificationData notification_data( |
247 unique_id_, NOTIFY_SELF, | 251 unique_id_, NOTIFY_SELF, |
248 ObjectIdSetToStateMap(registrar_.GetAllRegisteredIds(), ""), | 252 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), ""), |
249 REMOTE_INVALIDATION); | 253 REMOTE_INVALIDATION); |
250 SendNotificationData(notification_data); | 254 SendNotificationData(notification_data); |
251 } | 255 } |
252 } | 256 } |
253 | 257 |
254 void P2PInvalidator::OnNotificationsDisabled( | 258 void P2PInvalidator::OnNotificationsDisabled( |
255 notifier::NotificationsDisabledReason reason) { | 259 notifier::NotificationsDisabledReason reason) { |
256 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
257 registrar_.UpdateInvalidatorState(FromNotifierReason(reason)); | 261 registrar_.UpdateInvalidatorState(FromNotifierReason(reason)); |
258 } | 262 } |
(...skipping 14 matching lines...) Expand all Loading... |
273 LOG(WARNING) << "Notification from unexpected source " | 277 LOG(WARNING) << "Notification from unexpected source " |
274 << notification.channel; | 278 << notification.channel; |
275 } | 279 } |
276 P2PNotificationData notification_data; | 280 P2PNotificationData notification_data; |
277 if (!notification_data.ResetFromString(notification.data)) { | 281 if (!notification_data.ResetFromString(notification.data)) { |
278 LOG(WARNING) << "Could not parse notification data from " | 282 LOG(WARNING) << "Could not parse notification data from " |
279 << notification.data; | 283 << notification.data; |
280 notification_data = | 284 notification_data = |
281 P2PNotificationData( | 285 P2PNotificationData( |
282 unique_id_, NOTIFY_ALL, | 286 unique_id_, NOTIFY_ALL, |
283 ObjectIdSetToStateMap(registrar_.GetAllRegisteredIds(), ""), | 287 ObjectIdSetToInvalidationMap(registrar_.GetAllRegisteredIds(), ""), |
284 REMOTE_INVALIDATION); | 288 REMOTE_INVALIDATION); |
285 } | 289 } |
286 if (!notification_data.IsTargeted(unique_id_)) { | 290 if (!notification_data.IsTargeted(unique_id_)) { |
287 DVLOG(1) << "Not a target of the notification -- " | 291 DVLOG(1) << "Not a target of the notification -- " |
288 << "not emitting notification"; | 292 << "not emitting notification"; |
289 return; | 293 return; |
290 } | 294 } |
291 registrar_.DispatchInvalidationsToHandlers( | 295 registrar_.DispatchInvalidationsToHandlers( |
292 notification_data.GetIdStateMap(), | 296 notification_data.GetIdInvalidationMap(), |
293 REMOTE_INVALIDATION); | 297 REMOTE_INVALIDATION); |
294 } | 298 } |
295 | 299 |
296 void P2PInvalidator::SendNotificationDataForTest( | 300 void P2PInvalidator::SendNotificationDataForTest( |
297 const P2PNotificationData& notification_data) { | 301 const P2PNotificationData& notification_data) { |
298 DCHECK(thread_checker_.CalledOnValidThread()); | 302 DCHECK(thread_checker_.CalledOnValidThread()); |
299 SendNotificationData(notification_data); | 303 SendNotificationData(notification_data); |
300 } | 304 } |
301 | 305 |
302 void P2PInvalidator::SendNotificationData( | 306 void P2PInvalidator::SendNotificationData( |
303 const P2PNotificationData& notification_data) { | 307 const P2PNotificationData& notification_data) { |
304 DCHECK(thread_checker_.CalledOnValidThread()); | 308 DCHECK(thread_checker_.CalledOnValidThread()); |
305 if (notification_data.GetIdStateMap().empty()) { | 309 if (notification_data.GetIdInvalidationMap().empty()) { |
306 DVLOG(1) << "Not sending XMPP notification with empty state map: " | 310 DVLOG(1) << "Not sending XMPP notification with empty state map: " |
307 << notification_data.ToString(); | 311 << notification_data.ToString(); |
308 return; | 312 return; |
309 } | 313 } |
310 notifier::Notification notification; | 314 notifier::Notification notification; |
311 notification.channel = kSyncP2PNotificationChannel; | 315 notification.channel = kSyncP2PNotificationChannel; |
312 notification.data = notification_data.ToString(); | 316 notification.data = notification_data.ToString(); |
313 DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); | 317 DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); |
314 push_client_->SendNotification(notification); | 318 push_client_->SendNotification(notification); |
315 } | 319 } |
316 | 320 |
317 } // namespace syncer | 321 } // namespace syncer |
OLD | NEW |