Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: sync/notifier/p2p_invalidator.cc

Issue 10874096: [Sync] Rework Invalidator-related unit tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sync/notifier/p2p_invalidator.h ('k') | sync/notifier/p2p_invalidator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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" 14 #include "sync/internal_api/public/base/model_type_state_map.h"
15 #include "sync/notifier/invalidation_handler.h" 15 #include "sync/notifier/invalidation_handler.h"
16 #include "sync/notifier/invalidation_util.h" 16 #include "sync/notifier/invalidation_util.h"
17 17
18 namespace syncer { 18 namespace syncer {
19 19
20 const char* kSyncP2PNotificationChannel = "http://www.google.com/chrome/sync"; 20 const char kSyncP2PNotificationChannel[] = "http://www.google.com/chrome/sync";
21 21
22 namespace { 22 namespace {
23 23
24 const char kNotifySelf[] = "notifySelf"; 24 const char kNotifySelf[] = "notifySelf";
25 const char kNotifyOthers[] = "notifyOthers"; 25 const char kNotifyOthers[] = "notifyOthers";
26 const char kNotifyAll[] = "notifyAll"; 26 const char kNotifyAll[] = "notifyAll";
27 27
28 const char kSenderIdKey[] = "senderId"; 28 const char kSenderIdKey[] = "senderId";
29 const char kNotificationTypeKey[] = "notificationType"; 29 const char kNotificationTypeKey[] = "notificationType";
30 const char kChangedTypesKey[] = "changedTypes"; 30 const char kIdStateMapKey[] = "idStateMap";
31 const char kSourceKey[] = "source";
31 32
32 } // namespace 33 } // namespace
33 34
34 std::string P2PNotificationTargetToString(P2PNotificationTarget target) { 35 std::string P2PNotificationTargetToString(P2PNotificationTarget target) {
35 switch (target) { 36 switch (target) {
36 case NOTIFY_SELF: 37 case NOTIFY_SELF:
37 return kNotifySelf; 38 return kNotifySelf;
38 case NOTIFY_OTHERS: 39 case NOTIFY_OTHERS:
39 return kNotifyOthers; 40 return kNotifyOthers;
40 case NOTIFY_ALL: 41 case NOTIFY_ALL:
(...skipping 12 matching lines...) Expand all
53 if (target_str == kNotifyOthers) { 54 if (target_str == kNotifyOthers) {
54 return NOTIFY_OTHERS; 55 return NOTIFY_OTHERS;
55 } 56 }
56 if (target_str == kNotifyAll) { 57 if (target_str == kNotifyAll) {
57 return NOTIFY_ALL; 58 return NOTIFY_ALL;
58 } 59 }
59 LOG(WARNING) << "Could not parse " << target_str; 60 LOG(WARNING) << "Could not parse " << target_str;
60 return NOTIFY_SELF; 61 return NOTIFY_SELF;
61 } 62 }
62 63
63 P2PNotificationData::P2PNotificationData() : target_(NOTIFY_SELF) {} 64 IncomingNotificationSource P2PNotificationSourceFromInteger(int source_num) {
65 if (source_num == LOCAL_NOTIFICATION) {
66 return LOCAL_NOTIFICATION;
67 }
68 return REMOTE_NOTIFICATION;
69 }
70
71 P2PNotificationData::P2PNotificationData()
72 : target_(NOTIFY_SELF), source_(REMOTE_NOTIFICATION) {}
64 73
65 P2PNotificationData::P2PNotificationData( 74 P2PNotificationData::P2PNotificationData(
66 const std::string& sender_id, 75 const std::string& sender_id,
67 P2PNotificationTarget target, 76 P2PNotificationTarget target,
68 ModelTypeSet changed_types) 77 const ObjectIdStateMap& id_state_map,
78 IncomingNotificationSource source)
69 : sender_id_(sender_id), 79 : sender_id_(sender_id),
70 target_(target), 80 target_(target),
71 changed_types_(changed_types) {} 81 id_state_map_(id_state_map),
82 source_(source) {}
72 83
73 P2PNotificationData::~P2PNotificationData() {} 84 P2PNotificationData::~P2PNotificationData() {}
74 85
75 bool P2PNotificationData::IsTargeted(const std::string& id) const { 86 bool P2PNotificationData::IsTargeted(const std::string& id) const {
76 switch (target_) { 87 switch (target_) {
77 case NOTIFY_SELF: 88 case NOTIFY_SELF:
78 return sender_id_ == id; 89 return sender_id_ == id;
79 case NOTIFY_OTHERS: 90 case NOTIFY_OTHERS:
80 return sender_id_ != id; 91 return sender_id_ != id;
81 case NOTIFY_ALL: 92 case NOTIFY_ALL:
82 return true; 93 return true;
83 default: 94 default:
84 NOTREACHED(); 95 NOTREACHED();
85 return false; 96 return false;
86 } 97 }
87 } 98 }
88 99
89 ModelTypeSet P2PNotificationData::GetChangedTypes() const { 100 const ObjectIdStateMap& P2PNotificationData::GetIdStateMap() const {
90 return changed_types_; 101 return id_state_map_;
102 }
103
104 IncomingNotificationSource P2PNotificationData::GetSource() const {
105 return source_;
91 } 106 }
92 107
93 bool P2PNotificationData::Equals(const P2PNotificationData& other) const { 108 bool P2PNotificationData::Equals(const P2PNotificationData& other) const {
94 return 109 return
95 (sender_id_ == other.sender_id_) && 110 (sender_id_ == other.sender_id_) &&
96 (target_ == other.target_) && 111 (target_ == other.target_) &&
97 changed_types_.Equals(other.changed_types_); 112 ObjectIdStateMapEquals(id_state_map_, other.id_state_map_) &&
113 (source_ == other.source_);
98 } 114 }
99 115
100 std::string P2PNotificationData::ToString() const { 116 std::string P2PNotificationData::ToString() const {
101 scoped_ptr<DictionaryValue> dict(new DictionaryValue()); 117 scoped_ptr<DictionaryValue> dict(new DictionaryValue());
102 dict->SetString(kSenderIdKey, sender_id_); 118 dict->SetString(kSenderIdKey, sender_id_);
103 dict->SetString(kNotificationTypeKey, 119 dict->SetString(kNotificationTypeKey,
104 P2PNotificationTargetToString(target_)); 120 P2PNotificationTargetToString(target_));
105 dict->Set(kChangedTypesKey, ModelTypeSetToValue(changed_types_)); 121 dict->Set(kIdStateMapKey, ObjectIdStateMapToValue(id_state_map_).release());
122 dict->SetInteger(kSourceKey, source_);
106 std::string json; 123 std::string json;
107 base::JSONWriter::Write(dict.get(), &json); 124 base::JSONWriter::Write(dict.get(), &json);
108 return json; 125 return json;
109 } 126 }
110 127
111 bool P2PNotificationData::ResetFromString(const std::string& str) { 128 bool P2PNotificationData::ResetFromString(const std::string& str) {
112 scoped_ptr<Value> data_value(base::JSONReader::Read(str)); 129 scoped_ptr<Value> data_value(base::JSONReader::Read(str));
113 if (!data_value.get()) { 130 const base::DictionaryValue* data_dict = NULL;
114 LOG(WARNING) << "Could not parse " << str; 131 if (!data_value.get() || !data_value->GetAsDictionary(&data_dict)) {
115 return false;
116 }
117 if (!data_value->IsType(Value::TYPE_DICTIONARY)) {
118 LOG(WARNING) << "Could not parse " << str << " as a dictionary"; 132 LOG(WARNING) << "Could not parse " << str << " as a dictionary";
119 return false; 133 return false;
120 } 134 }
121 // TODO(akalin): Use Values::AsDictionary() when it becomes
122 // available.
123 DictionaryValue* data_dict =
124 static_cast<DictionaryValue*>(data_value.get());
125 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) { 135 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) {
126 LOG(WARNING) << "Could not find string value for " << kSenderIdKey; 136 LOG(WARNING) << "Could not find string value for " << kSenderIdKey;
127 } 137 }
128 std::string target_str; 138 std::string target_str;
129 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) { 139 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) {
130 LOG(WARNING) << "Could not find string value for " 140 LOG(WARNING) << "Could not find string value for "
131 << kNotificationTypeKey; 141 << kNotificationTypeKey;
132 } 142 }
133 target_ = P2PNotificationTargetFromString(target_str); 143 target_ = P2PNotificationTargetFromString(target_str);
134 ListValue* changed_types_list = NULL; 144 const base::ListValue* id_state_map_list = NULL;
135 if (!data_dict->GetList(kChangedTypesKey, &changed_types_list)) { 145 if (!data_dict->GetList(kIdStateMapKey, &id_state_map_list) ||
136 LOG(WARNING) << "Could not find list value for " 146 !ObjectIdStateMapFromValue(*id_state_map_list, &id_state_map_)) {
137 << kChangedTypesKey; 147 LOG(WARNING) << "Could not parse " << kIdStateMapKey;
138 return false;
139 } 148 }
140 changed_types_ = ModelTypeSetFromValue(*changed_types_list); 149 int source_num = 0;
150 if (!data_dict->GetInteger(kSourceKey, &source_num)) {
151 LOG(WARNING) << "Could not find integer value for " << kSourceKey;
152 }
153 source_ = P2PNotificationSourceFromInteger(source_num);
141 return true; 154 return true;
142 } 155 }
143 156
144 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client, 157 P2PInvalidator::P2PInvalidator(scoped_ptr<notifier::PushClient> push_client,
145 P2PNotificationTarget send_notification_target) 158 P2PNotificationTarget send_notification_target)
146 : push_client_(push_client.Pass()), 159 : push_client_(push_client.Pass()),
147 logged_in_(false), 160 logged_in_(false),
148 notifications_enabled_(false), 161 notifications_enabled_(false),
149 send_notification_target_(send_notification_target) { 162 send_notification_target_(send_notification_target) {
150 DCHECK(send_notification_target_ == NOTIFY_OTHERS || 163 DCHECK(send_notification_target_ == NOTIFY_OTHERS ||
151 send_notification_target_ == NOTIFY_ALL); 164 send_notification_target_ == NOTIFY_ALL);
152 push_client_->AddObserver(this); 165 push_client_->AddObserver(this);
153 } 166 }
154 167
155 P2PInvalidator::~P2PInvalidator() { 168 P2PInvalidator::~P2PInvalidator() {
156 DCHECK(thread_checker_.CalledOnValidThread()); 169 DCHECK(thread_checker_.CalledOnValidThread());
157 push_client_->RemoveObserver(this); 170 push_client_->RemoveObserver(this);
158 } 171 }
159 172
160 void P2PInvalidator::RegisterHandler(InvalidationHandler* handler) { 173 void P2PInvalidator::RegisterHandler(InvalidationHandler* handler) {
161 DCHECK(thread_checker_.CalledOnValidThread()); 174 DCHECK(thread_checker_.CalledOnValidThread());
162 registrar_.RegisterHandler(handler); 175 registrar_.RegisterHandler(handler);
163 } 176 }
164 177
165 void P2PInvalidator::UpdateRegisteredIds(InvalidationHandler* handler, 178 void P2PInvalidator::UpdateRegisteredIds(InvalidationHandler* handler,
166 const ObjectIdSet& ids) { 179 const ObjectIdSet& ids) {
167 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411). 180 // TODO(akalin): Handle arbitrary object IDs (http://crbug.com/140411).
168 DCHECK(thread_checker_.CalledOnValidThread()); 181 DCHECK(thread_checker_.CalledOnValidThread());
182 ObjectIdSet new_ids;
183 const ObjectIdSet& old_ids = registrar_.GetRegisteredIds(handler);
184 std::set_difference(ids.begin(), ids.end(),
185 old_ids.begin(), old_ids.end(),
186 std::inserter(new_ids, new_ids.end()),
187 ObjectIdLessThan());
169 registrar_.UpdateRegisteredIds(handler, ids); 188 registrar_.UpdateRegisteredIds(handler, ids);
170 const ModelTypeSet enabled_types =
171 ObjectIdSetToModelTypeSet(registrar_.GetAllRegisteredIds());
172 const ModelTypeSet new_enabled_types =
173 Difference(enabled_types, enabled_types_);
174 const P2PNotificationData notification_data( 189 const P2PNotificationData notification_data(
175 unique_id_, NOTIFY_SELF, new_enabled_types); 190 unique_id_, NOTIFY_SELF, ObjectIdSetToStateMap(new_ids, ""),
191 REMOTE_NOTIFICATION);
176 SendNotificationData(notification_data); 192 SendNotificationData(notification_data);
177 enabled_types_ = enabled_types;
178 } 193 }
179 194
180 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) { 195 void P2PInvalidator::UnregisterHandler(InvalidationHandler* handler) {
181 DCHECK(thread_checker_.CalledOnValidThread()); 196 DCHECK(thread_checker_.CalledOnValidThread());
182 registrar_.UnregisterHandler(handler); 197 registrar_.UnregisterHandler(handler);
183 } 198 }
184 199
185 void P2PInvalidator::SetUniqueId(const std::string& unique_id) { 200 void P2PInvalidator::SetUniqueId(const std::string& unique_id) {
186 DCHECK(thread_checker_.CalledOnValidThread()); 201 DCHECK(thread_checker_.CalledOnValidThread());
187 unique_id_ = unique_id; 202 unique_id_ = unique_id;
(...skipping 14 matching lines...) Expand all
202 // used in p2p mode (which is only used in testing). 217 // used in p2p mode (which is only used in testing).
203 subscription.from = email; 218 subscription.from = email;
204 push_client_->UpdateSubscriptions( 219 push_client_->UpdateSubscriptions(
205 notifier::SubscriptionList(1, subscription)); 220 notifier::SubscriptionList(1, subscription));
206 // If already logged in, the new credentials will take effect on the 221 // If already logged in, the new credentials will take effect on the
207 // next reconnection. 222 // next reconnection.
208 push_client_->UpdateCredentials(email, token); 223 push_client_->UpdateCredentials(email, token);
209 logged_in_ = true; 224 logged_in_ = true;
210 } 225 }
211 226
212 void P2PInvalidator::SendNotification(ModelTypeSet changed_types) { 227 void P2PInvalidator::SendNotification(const ObjectIdStateMap& id_state_map) {
213 DCHECK(thread_checker_.CalledOnValidThread()); 228 DCHECK(thread_checker_.CalledOnValidThread());
214 const P2PNotificationData notification_data( 229 const P2PNotificationData notification_data(
215 unique_id_, send_notification_target_, changed_types); 230 unique_id_, send_notification_target_, id_state_map,
231 REMOTE_NOTIFICATION);
216 SendNotificationData(notification_data); 232 SendNotificationData(notification_data);
217 } 233 }
218 234
219 void P2PInvalidator::OnNotificationsEnabled() { 235 void P2PInvalidator::OnNotificationsEnabled() {
220 DCHECK(thread_checker_.CalledOnValidThread()); 236 DCHECK(thread_checker_.CalledOnValidThread());
221 bool just_turned_on = (notifications_enabled_ == false); 237 bool just_turned_on = (notifications_enabled_ == false);
222 notifications_enabled_ = true; 238 notifications_enabled_ = true;
223 registrar_.EmitOnNotificationsEnabled(); 239 registrar_.EmitOnNotificationsEnabled();
224 if (just_turned_on) { 240 if (just_turned_on) {
225 const P2PNotificationData notification_data( 241 const P2PNotificationData notification_data(
226 unique_id_, NOTIFY_SELF, enabled_types_); 242 unique_id_, NOTIFY_SELF,
243 ObjectIdSetToStateMap(registrar_.GetAllRegisteredIds(), ""),
244 REMOTE_NOTIFICATION);
227 SendNotificationData(notification_data); 245 SendNotificationData(notification_data);
228 } 246 }
229 } 247 }
230 248
231 void P2PInvalidator::OnNotificationsDisabled( 249 void P2PInvalidator::OnNotificationsDisabled(
232 notifier::NotificationsDisabledReason reason) { 250 notifier::NotificationsDisabledReason reason) {
233 DCHECK(thread_checker_.CalledOnValidThread()); 251 DCHECK(thread_checker_.CalledOnValidThread());
234 registrar_.EmitOnNotificationsDisabled(FromNotifierReason(reason)); 252 registrar_.EmitOnNotificationsDisabled(FromNotifierReason(reason));
235 } 253 }
236 254
(...skipping 11 matching lines...) Expand all
248 } 266 }
249 if (notification.channel != kSyncP2PNotificationChannel) { 267 if (notification.channel != kSyncP2PNotificationChannel) {
250 LOG(WARNING) << "Notification from unexpected source " 268 LOG(WARNING) << "Notification from unexpected source "
251 << notification.channel; 269 << notification.channel;
252 } 270 }
253 P2PNotificationData notification_data; 271 P2PNotificationData notification_data;
254 if (!notification_data.ResetFromString(notification.data)) { 272 if (!notification_data.ResetFromString(notification.data)) {
255 LOG(WARNING) << "Could not parse notification data from " 273 LOG(WARNING) << "Could not parse notification data from "
256 << notification.data; 274 << notification.data;
257 notification_data = 275 notification_data =
258 P2PNotificationData(unique_id_, NOTIFY_ALL, enabled_types_); 276 P2PNotificationData(
277 unique_id_, NOTIFY_ALL,
278 ObjectIdSetToStateMap(registrar_.GetAllRegisteredIds(), ""),
279 REMOTE_NOTIFICATION);
259 } 280 }
260 if (!notification_data.IsTargeted(unique_id_)) { 281 if (!notification_data.IsTargeted(unique_id_)) {
261 DVLOG(1) << "Not a target of the notification -- " 282 DVLOG(1) << "Not a target of the notification -- "
262 << "not emitting notification"; 283 << "not emitting notification";
263 return; 284 return;
264 } 285 }
265 const ModelTypeSet types_to_notify =
266 Intersection(enabled_types_, notification_data.GetChangedTypes());
267 if (types_to_notify.Empty()) {
268 DVLOG(1) << "No enabled and changed types -- not emitting notification";
269 return;
270 }
271 const ModelTypeStateMap& type_state_map = ModelTypeSetToStateMap(
272 notification_data.GetChangedTypes(), std::string());
273 registrar_.DispatchInvalidationsToHandlers( 286 registrar_.DispatchInvalidationsToHandlers(
274 ModelTypeStateMapToObjectIdStateMap(type_state_map), 287 notification_data.GetIdStateMap(),
275 REMOTE_NOTIFICATION); 288 REMOTE_NOTIFICATION);
276 } 289 }
277 290
278 void P2PInvalidator::SendNotificationDataForTest( 291 void P2PInvalidator::SendNotificationDataForTest(
279 const P2PNotificationData& notification_data) { 292 const P2PNotificationData& notification_data) {
280 DCHECK(thread_checker_.CalledOnValidThread()); 293 DCHECK(thread_checker_.CalledOnValidThread());
281 SendNotificationData(notification_data); 294 SendNotificationData(notification_data);
282 } 295 }
283 296
284 void P2PInvalidator::SendNotificationData( 297 void P2PInvalidator::SendNotificationData(
285 const P2PNotificationData& notification_data) { 298 const P2PNotificationData& notification_data) {
286 DCHECK(thread_checker_.CalledOnValidThread()); 299 DCHECK(thread_checker_.CalledOnValidThread());
287 if (notification_data.GetChangedTypes().Empty()) { 300 if (notification_data.GetIdStateMap().empty()) {
288 DVLOG(1) << "Not sending XMPP notification with no changed types: " 301 DVLOG(1) << "Not sending XMPP notification with empty state map: "
289 << notification_data.ToString(); 302 << notification_data.ToString();
290 return; 303 return;
291 } 304 }
292 notifier::Notification notification; 305 notifier::Notification notification;
293 notification.channel = kSyncP2PNotificationChannel; 306 notification.channel = kSyncP2PNotificationChannel;
294 notification.data = notification_data.ToString(); 307 notification.data = notification_data.ToString();
295 DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); 308 DVLOG(1) << "Sending XMPP notification: " << notification.ToString();
296 push_client_->SendNotification(notification); 309 push_client_->SendNotification(notification);
297 } 310 }
298 311
299 } // namespace syncer 312 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/notifier/p2p_invalidator.h ('k') | sync/notifier/p2p_invalidator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698