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

Side by Side Diff: chrome/browser/sync/notifier/p2p_notifier.cc

Issue 7745040: [Sync] Make P2PNotifier behave more like InvalidationNotifier (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 "chrome/browser/sync/notifier/p2p_notifier.h" 5 #include "chrome/browser/sync/notifier/p2p_notifier.h"
6 6
7 #include <algorithm>
8
9 #include "base/logging.h"
7 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
11 #include "base/json/json_reader.h"
12 #include "base/json/json_writer.h"
13 #include "base/values.h"
8 #include "chrome/browser/sync/notifier/sync_notifier_observer.h" 14 #include "chrome/browser/sync/notifier/sync_notifier_observer.h"
9 #include "chrome/browser/sync/protocol/service_constants.h" 15 #include "chrome/browser/sync/protocol/service_constants.h"
10 #include "chrome/browser/sync/syncable/model_type_payload_map.h" 16 #include "chrome/browser/sync/syncable/model_type_payload_map.h"
11 #include "jingle/notifier/listener/mediator_thread_impl.h"
12 #include "jingle/notifier/listener/talk_mediator_impl.h"
13 17
14 namespace sync_notifier { 18 namespace sync_notifier {
15 19
16 namespace { 20 namespace {
21
17 const char kSyncNotificationChannel[] = "http://www.google.com/chrome/sync"; 22 const char kSyncNotificationChannel[] = "http://www.google.com/chrome/sync";
18 const char kSyncNotificationData[] = "sync-ping-p2p"; 23
24 const char kNotifySelf[] = "notifySelf";
25 const char kNotifyOthers[] = "notifyOthers";
26 const char kNotifyAll[] = "notifyAll";
27
28 const char kSenderIdKey[] = "senderId";
29 const char kNotificationTypeKey[] = "notificationType";
30 const char kChangedTypesKey[] = "changedTypes";
31
19 } // namespace 32 } // namespace
20 33
21 P2PNotifier::P2PNotifier( 34 std::string P2PNotificationTargetToString(P2PNotificationTarget target) {
22 const notifier::NotifierOptions& notifier_options) 35 switch (target) {
23 : talk_mediator_( 36 case NOTIFY_SELF:
24 new notifier::TalkMediatorImpl( 37 return kNotifySelf;
25 new notifier::MediatorThreadImpl(notifier_options), 38 case NOTIFY_OTHERS:
26 notifier_options)), 39 return kNotifyOthers;
40 case NOTIFY_ALL:
41 return kNotifyAll;
42 default:
43 NOTREACHED();
44 return "";
45 }
46 }
47
48 P2PNotificationTarget P2PNotificationTargetFromString(
49 const std::string& target_str) {
50 if (target_str == kNotifySelf) {
51 return NOTIFY_SELF;
52 }
53 if (target_str == kNotifyOthers) {
54 return NOTIFY_OTHERS;
55 }
56 if (target_str == kNotifyAll) {
57 return NOTIFY_ALL;
58 }
59 LOG(WARNING) << "Could not parse " << target_str;
60 return NOTIFY_SELF;
61 }
62
63 P2PNotificationData::P2PNotificationData() : target_(NOTIFY_SELF) {}
64
65 P2PNotificationData::P2PNotificationData(
66 const std::string& sender_id,
67 P2PNotificationTarget target,
68 const syncable::ModelTypeSet& changed_types)
69 : sender_id_(sender_id),
70 target_(target),
71 changed_types_(changed_types) {}
72
73 P2PNotificationData::~P2PNotificationData() {}
74
75 bool P2PNotificationData::IsTargeted(const std::string& id) const {
76 switch (target_) {
77 case NOTIFY_SELF:
78 return sender_id_ == id;
79 case NOTIFY_OTHERS:
80 return sender_id_ != id;
81 case NOTIFY_ALL:
82 return true;
83 default:
84 NOTREACHED();
85 return false;
86 }
87 }
88
89 const syncable::ModelTypeSet& P2PNotificationData::GetChangedTypes() const {
90 return changed_types_;
91 }
92
93 bool P2PNotificationData::Equals(const P2PNotificationData& other) const {
94 return
95 (sender_id_ == other.sender_id_) &&
96 (target_ == other.target_) &&
97 (changed_types_ == other.changed_types_);
98 }
99
100 std::string P2PNotificationData::ToString() const {
101 scoped_ptr<DictionaryValue> dict(new DictionaryValue());
102 dict->SetString(kSenderIdKey, sender_id_);
103 dict->SetString(kNotificationTypeKey,
104 P2PNotificationTargetToString(target_));
105 dict->Set(kChangedTypesKey, syncable::ModelTypeSetToValue(changed_types_));
106 std::string json;
107 base::JSONWriter::Write(dict.get(), false /* pretty_print */, &json);
108 return json;
109 }
110
111 bool P2PNotificationData::FromString(const std::string& str) {
112 scoped_ptr<Value> data_value(
113 base::JSONReader::Read(str, false /* allow_trailing_comma */));
114 DictionaryValue* data_dict = NULL;
115 if (!data_value.get()) {
116 LOG(WARNING) << "Could not parse " << str;
117 return false;
118 }
119 if (!data_value->GetAsDictionary(&data_dict)) {
120 LOG(WARNING) << "Could not parse " << str << " as a dictionary";
121 return false;
122 }
123 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) {
124 LOG(WARNING) << "Could not find string value for " << kSenderIdKey;
125 }
126 std::string target_str;
127 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) {
128 LOG(WARNING) << "Could not find string value for "
129 << kNotificationTypeKey;
130 }
131 target_ = P2PNotificationTargetFromString(target_str);
132 ListValue* changed_types_list = NULL;
133 if (!data_dict->GetList(kChangedTypesKey, &changed_types_list)) {
134 LOG(WARNING) << "Could not find list value for "
135 << kChangedTypesKey;
136 return false;
137 }
138 changed_types_ = syncable::ModelTypeSetFromValue(*changed_types_list);
139 return true;
140 }
141
142 P2PNotifier::P2PNotifier(notifier::TalkMediator* talk_mediator)
143 : talk_mediator_(talk_mediator),
27 logged_in_(false), 144 logged_in_(false),
28 notifications_enabled_(false), 145 notifications_enabled_(false),
29 parent_message_loop_proxy_( 146 parent_message_loop_proxy_(
30 base::MessageLoopProxy::current()) { 147 base::MessageLoopProxy::current()) {
31 talk_mediator_->SetDelegate(this); 148 talk_mediator_->SetDelegate(this);
32 } 149 }
33 150
34 P2PNotifier::~P2PNotifier() { 151 P2PNotifier::~P2PNotifier() {
35 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 152 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
36 } 153 }
(...skipping 12 matching lines...) Expand all
49 observer_list_.RemoveObserver(observer); 166 observer_list_.RemoveObserver(observer);
50 167
51 // Logout after the last observer is removed. 168 // Logout after the last observer is removed.
52 if (observer_list_.size() == 0) { 169 if (observer_list_.size() == 0) {
53 talk_mediator_->Logout(); 170 talk_mediator_->Logout();
54 } 171 }
55 } 172 }
56 173
57 void P2PNotifier::SetUniqueId(const std::string& unique_id) { 174 void P2PNotifier::SetUniqueId(const std::string& unique_id) {
58 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 175 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
176 unique_id_ = unique_id;
59 } 177 }
60 178
61 void P2PNotifier::SetState(const std::string& state) { 179 void P2PNotifier::SetState(const std::string& state) {
62 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 180 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
63 } 181 }
64 182
65 void P2PNotifier::UpdateCredentials( 183 void P2PNotifier::UpdateCredentials(
66 const std::string& email, const std::string& token) { 184 const std::string& email, const std::string& token) {
67 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 185 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
68 // If already logged in, the new credentials will take effect on the 186 // If already logged in, the new credentials will take effect on the
(...skipping 10 matching lines...) Expand all
79 // There may be some subtle issues around case sensitivity of the 197 // There may be some subtle issues around case sensitivity of the
80 // from field, but it doesn't matter too much since this is only 198 // from field, but it doesn't matter too much since this is only
81 // used in p2p mode (which is only used in testing). 199 // used in p2p mode (which is only used in testing).
82 subscription.from = email; 200 subscription.from = email;
83 talk_mediator_->AddSubscription(subscription); 201 talk_mediator_->AddSubscription(subscription);
84 202
85 logged_in_ = true; 203 logged_in_ = true;
86 } 204 }
87 } 205 }
88 206
89 void P2PNotifier::UpdateEnabledTypes(const syncable::ModelTypeSet& types) { 207 void P2PNotifier::UpdateEnabledTypes(
208 const syncable::ModelTypeSet& enabled_types) {
90 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 209 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
91 enabled_types_ = types; 210 syncable::ModelTypeSet new_enabled_types;
92 MaybeEmitNotification(); 211 std::set_difference(enabled_types.begin(), enabled_types.end(),
212 enabled_types_.begin(), enabled_types_.end(),
213 std::inserter(new_enabled_types,
214 new_enabled_types.end()));
215 enabled_types_ = enabled_types;
216 const P2PNotificationData notification_data(
217 unique_id_, NOTIFY_SELF, new_enabled_types);
218 SendNotificationData(notification_data);
93 } 219 }
94 220
95 void P2PNotifier::SendNotification() { 221 void P2PNotifier::SendNotification(
222 const syncable::ModelTypeSet& changed_types) {
96 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 223 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
97 VLOG(1) << "Sending XMPP notification..."; 224 const P2PNotificationData notification_data(
98 notifier::Notification notification; 225 unique_id_, NOTIFY_OTHERS, changed_types);
99 notification.channel = kSyncNotificationChannel; 226 SendNotificationData(notification_data);
100 notification.data = kSyncNotificationData;
101 talk_mediator_->SendNotification(notification);
102 } 227 }
103 228
104 void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) { 229 void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) {
105 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 230 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
231 bool disabled_to_enabled = notifications_enabled && !notifications_enabled_;
106 notifications_enabled_ = notifications_enabled; 232 notifications_enabled_ = notifications_enabled;
107 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, 233 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
108 OnNotificationStateChange(notifications_enabled_)); 234 OnNotificationStateChange(notifications_enabled_));
109 MaybeEmitNotification(); 235 if (disabled_to_enabled) {
236 const P2PNotificationData notification_data(
237 unique_id_, NOTIFY_SELF, enabled_types_);
238 SendNotificationData(notification_data);
239 }
110 } 240 }
111 241
112 void P2PNotifier::OnIncomingNotification( 242 void P2PNotifier::OnIncomingNotification(
113 const notifier::Notification& notification) { 243 const notifier::Notification& notification) {
114 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 244 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
115 VLOG(1) << "Sync received P2P notification."; 245 VLOG(1) << "Received notification " << notification.ToString();
116 if (notification.channel != kSyncNotificationChannel) {
117 LOG(WARNING) << "Notification from unexpected source: "
118 << notification.channel;
119 }
120 MaybeEmitNotification();
121 }
122
123 void P2PNotifier::OnOutgoingNotification() {}
124
125 void P2PNotifier::MaybeEmitNotification() {
126 if (!logged_in_) { 246 if (!logged_in_) {
127 VLOG(1) << "Not logged in yet -- not emitting notification"; 247 VLOG(1) << "Not logged in yet -- not emitting notification";
128 return; 248 return;
129 } 249 }
130 if (!notifications_enabled_) { 250 if (!notifications_enabled_) {
131 VLOG(1) << "Notifications not enabled -- not emitting notification"; 251 VLOG(1) << "Notifications not enabled -- not emitting notification";
132 return; 252 return;
133 } 253 }
134 if (enabled_types_.empty()) { 254 if (notification.channel != kSyncNotificationChannel) {
135 VLOG(1) << "No enabled types -- not emitting notification"; 255 LOG(WARNING) << "Notification from unexpected source "
256 << notification.channel;
257 }
258 P2PNotificationData notification_data;
259 if (!notification_data.FromString(notification.data)) {
260 LOG(WARNING) << "Could not parse notification data from "
261 << notification.data;
262 notification_data =
263 P2PNotificationData(unique_id_, NOTIFY_ALL, enabled_types_);
264 }
265 if (!notification_data.IsTargeted(unique_id_)) {
266 VLOG(1) << "Not a target of the notification -- "
267 << "not emitting notification";
136 return; 268 return;
137 } 269 }
138 syncable::ModelTypePayloadMap type_payloads = 270 if (notification_data.GetChangedTypes().empty()) {
271 VLOG(1) << "No changed types -- not emitting notification";
272 return;
273 }
Nicolas Zea 2011/08/26 21:19:14 Should this check to see if the changed types are
akalin 2011/08/26 22:42:27 The InvalidationNotifier doesn't, so I don't think
274 const syncable::ModelTypePayloadMap& type_payloads =
139 syncable::ModelTypePayloadMapFromBitSet( 275 syncable::ModelTypePayloadMapFromBitSet(
Nicolas Zea 2011/08/26 21:19:14 We really need to standardize bitset vs set, but t
akalin 2011/08/26 22:42:27 Yeah. Although I think it's better to make a spec
140 syncable::ModelTypeBitSetFromSet(enabled_types_), std::string()); 276 syncable::ModelTypeBitSetFromSet(
277 notification_data.GetChangedTypes()), std::string());
141 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, 278 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
142 OnIncomingNotification(type_payloads)); 279 OnIncomingNotification(type_payloads));
143 } 280 }
144 281
282 void P2PNotifier::OnOutgoingNotification() {}
283
284 void P2PNotifier::SendNotificationDataForTest(
285 const P2PNotificationData& notification_data) {
286 SendNotificationData(notification_data);
287 }
288
289 void P2PNotifier::SendNotificationData(
290 const P2PNotificationData& notification_data) {
291 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
292 notifier::Notification notification;
293 notification.channel = kSyncNotificationChannel;
294 notification.data = notification_data.ToString();
295 VLOG(1) << "Sending XMPP notification: " << notification.ToString();
296 talk_mediator_->SendNotification(notification);
297 }
298
145 } // namespace sync_notifier 299 } // namespace sync_notifier
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698