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

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: fix copyright Created 9 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
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::ResetFromString(const std::string& str) {
112 scoped_ptr<Value> data_value(
113 base::JSONReader::Read(str, false /* allow_trailing_comma */));
114 if (!data_value.get()) {
115 LOG(WARNING) << "Could not parse " << str;
116 return false;
117 }
118 if (!data_value->IsType(Value::TYPE_DICTIONARY)) {
119 LOG(WARNING) << "Could not parse " << str << " as a dictionary";
120 return false;
121 }
122 // TODO(akalin): Use Values::AsDictionary() when it becomes
123 // available.
124 DictionaryValue* data_dict =
125 static_cast<DictionaryValue*>(data_value.get());
126 if (!data_dict->GetString(kSenderIdKey, &sender_id_)) {
127 LOG(WARNING) << "Could not find string value for " << kSenderIdKey;
128 }
129 std::string target_str;
130 if (!data_dict->GetString(kNotificationTypeKey, &target_str)) {
131 LOG(WARNING) << "Could not find string value for "
132 << kNotificationTypeKey;
133 }
134 target_ = P2PNotificationTargetFromString(target_str);
135 ListValue* changed_types_list = NULL;
136 if (!data_dict->GetList(kChangedTypesKey, &changed_types_list)) {
137 LOG(WARNING) << "Could not find list value for "
138 << kChangedTypesKey;
139 return false;
140 }
141 changed_types_ = syncable::ModelTypeSetFromValue(*changed_types_list);
142 return true;
143 }
144
145 P2PNotifier::P2PNotifier(notifier::TalkMediator* talk_mediator)
146 : talk_mediator_(talk_mediator),
27 logged_in_(false), 147 logged_in_(false),
28 notifications_enabled_(false), 148 notifications_enabled_(false),
29 parent_message_loop_proxy_( 149 parent_message_loop_proxy_(
30 base::MessageLoopProxy::current()) { 150 base::MessageLoopProxy::current()) {
31 talk_mediator_->SetDelegate(this); 151 talk_mediator_->SetDelegate(this);
32 } 152 }
33 153
34 P2PNotifier::~P2PNotifier() { 154 P2PNotifier::~P2PNotifier() {
35 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 155 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
36 } 156 }
(...skipping 12 matching lines...) Expand all
49 observer_list_.RemoveObserver(observer); 169 observer_list_.RemoveObserver(observer);
50 170
51 // Logout after the last observer is removed. 171 // Logout after the last observer is removed.
52 if (observer_list_.size() == 0) { 172 if (observer_list_.size() == 0) {
53 talk_mediator_->Logout(); 173 talk_mediator_->Logout();
54 } 174 }
55 } 175 }
56 176
57 void P2PNotifier::SetUniqueId(const std::string& unique_id) { 177 void P2PNotifier::SetUniqueId(const std::string& unique_id) {
58 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 178 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
179 unique_id_ = unique_id;
59 } 180 }
60 181
61 void P2PNotifier::SetState(const std::string& state) { 182 void P2PNotifier::SetState(const std::string& state) {
62 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 183 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
63 } 184 }
64 185
65 void P2PNotifier::UpdateCredentials( 186 void P2PNotifier::UpdateCredentials(
66 const std::string& email, const std::string& token) { 187 const std::string& email, const std::string& token) {
67 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 188 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
68 // If already logged in, the new credentials will take effect on the 189 // 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 200 // 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 201 // from field, but it doesn't matter too much since this is only
81 // used in p2p mode (which is only used in testing). 202 // used in p2p mode (which is only used in testing).
82 subscription.from = email; 203 subscription.from = email;
83 talk_mediator_->AddSubscription(subscription); 204 talk_mediator_->AddSubscription(subscription);
84 205
85 logged_in_ = true; 206 logged_in_ = true;
86 } 207 }
87 } 208 }
88 209
89 void P2PNotifier::UpdateEnabledTypes(const syncable::ModelTypeSet& types) { 210 void P2PNotifier::UpdateEnabledTypes(
211 const syncable::ModelTypeSet& enabled_types) {
90 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 212 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
91 enabled_types_ = types; 213 syncable::ModelTypeSet new_enabled_types;
92 MaybeEmitNotification(); 214 std::set_difference(enabled_types.begin(), enabled_types.end(),
215 enabled_types_.begin(), enabled_types_.end(),
216 std::inserter(new_enabled_types,
217 new_enabled_types.end()));
218 enabled_types_ = enabled_types;
219 const P2PNotificationData notification_data(
220 unique_id_, NOTIFY_SELF, new_enabled_types);
221 SendNotificationData(notification_data);
93 } 222 }
94 223
95 void P2PNotifier::SendNotification() { 224 void P2PNotifier::SendNotification(
225 const syncable::ModelTypeSet& changed_types) {
96 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 226 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
97 VLOG(1) << "Sending XMPP notification..."; 227 const P2PNotificationData notification_data(
98 notifier::Notification notification; 228 unique_id_, NOTIFY_OTHERS, changed_types);
99 notification.channel = kSyncNotificationChannel; 229 SendNotificationData(notification_data);
100 notification.data = kSyncNotificationData;
101 talk_mediator_->SendNotification(notification);
102 } 230 }
103 231
104 void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) { 232 void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) {
105 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 233 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
234 bool disabled_to_enabled = notifications_enabled && !notifications_enabled_;
106 notifications_enabled_ = notifications_enabled; 235 notifications_enabled_ = notifications_enabled;
107 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, 236 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
108 OnNotificationStateChange(notifications_enabled_)); 237 OnNotificationStateChange(notifications_enabled_));
109 MaybeEmitNotification(); 238 if (disabled_to_enabled) {
239 const P2PNotificationData notification_data(
240 unique_id_, NOTIFY_SELF, enabled_types_);
241 SendNotificationData(notification_data);
242 }
110 } 243 }
111 244
112 void P2PNotifier::OnIncomingNotification( 245 void P2PNotifier::OnIncomingNotification(
113 const notifier::Notification& notification) { 246 const notifier::Notification& notification) {
114 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); 247 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
115 VLOG(1) << "Sync received P2P notification."; 248 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_) { 249 if (!logged_in_) {
127 VLOG(1) << "Not logged in yet -- not emitting notification"; 250 VLOG(1) << "Not logged in yet -- not emitting notification";
128 return; 251 return;
129 } 252 }
130 if (!notifications_enabled_) { 253 if (!notifications_enabled_) {
131 VLOG(1) << "Notifications not enabled -- not emitting notification"; 254 VLOG(1) << "Notifications not enabled -- not emitting notification";
132 return; 255 return;
133 } 256 }
134 if (enabled_types_.empty()) { 257 if (notification.channel != kSyncNotificationChannel) {
135 VLOG(1) << "No enabled types -- not emitting notification"; 258 LOG(WARNING) << "Notification from unexpected source "
259 << notification.channel;
260 }
261 P2PNotificationData notification_data;
262 if (!notification_data.ResetFromString(notification.data)) {
263 LOG(WARNING) << "Could not parse notification data from "
264 << notification.data;
265 notification_data =
266 P2PNotificationData(unique_id_, NOTIFY_ALL, enabled_types_);
267 }
268 if (!notification_data.IsTargeted(unique_id_)) {
269 VLOG(1) << "Not a target of the notification -- "
270 << "not emitting notification";
136 return; 271 return;
137 } 272 }
138 syncable::ModelTypePayloadMap type_payloads = 273 if (notification_data.GetChangedTypes().empty()) {
274 VLOG(1) << "No changed types -- not emitting notification";
275 return;
276 }
277 const syncable::ModelTypePayloadMap& type_payloads =
139 syncable::ModelTypePayloadMapFromBitSet( 278 syncable::ModelTypePayloadMapFromBitSet(
140 syncable::ModelTypeBitSetFromSet(enabled_types_), std::string()); 279 syncable::ModelTypeBitSetFromSet(
280 notification_data.GetChangedTypes()), std::string());
141 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, 281 FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
142 OnIncomingNotification(type_payloads)); 282 OnIncomingNotification(type_payloads));
143 } 283 }
144 284
285 void P2PNotifier::OnOutgoingNotification() {}
286
287 void P2PNotifier::SendNotificationDataForTest(
288 const P2PNotificationData& notification_data) {
289 SendNotificationData(notification_data);
290 }
291
292 void P2PNotifier::SendNotificationData(
293 const P2PNotificationData& notification_data) {
294 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
295 notifier::Notification notification;
296 notification.channel = kSyncNotificationChannel;
297 notification.data = notification_data.ToString();
298 VLOG(1) << "Sending XMPP notification: " << notification.ToString();
299 talk_mediator_->SendNotification(notification);
300 }
301
145 } // namespace sync_notifier 302 } // namespace sync_notifier
OLDNEW
« no previous file with comments | « chrome/browser/sync/notifier/p2p_notifier.h ('k') | chrome/browser/sync/notifier/p2p_notifier_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698