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 "chrome/browser/sync/glue/chrome_sync_notification_bridge.h" | 5 #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h" |
6 | 6 |
7 #include <cstddef> | 7 #include <cstddef> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/memory/weak_ptr.h" | 12 #include "base/memory/weak_ptr.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "base/sequenced_task_runner.h" | 14 #include "base/sequenced_task_runner.h" |
15 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
16 #include "base/test/test_timeouts.h" | 16 #include "base/test/test_timeouts.h" |
17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
18 #include "chrome/common/chrome_notification_types.h" | 18 #include "chrome/common/chrome_notification_types.h" |
19 #include "chrome/test/base/profile_mock.h" | 19 #include "chrome/test/base/profile_mock.h" |
20 #include "content/public/browser/notification_details.h" | 20 #include "content/public/browser/notification_details.h" |
21 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
22 #include "content/public/test/test_browser_thread.h" | 22 #include "content/public/test/test_browser_thread.h" |
23 #include "sync/internal_api/public/base/model_type.h" | 23 #include "sync/internal_api/public/base/model_type.h" |
24 #include "sync/internal_api/public/base/model_type_payload_map.h" | 24 #include "sync/internal_api/public/base/model_type_state_map.h" |
25 #include "sync/notifier/sync_notifier_observer.h" | 25 #include "sync/notifier/sync_notifier_observer.h" |
26 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
27 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
28 | 28 |
29 namespace browser_sync { | 29 namespace browser_sync { |
30 namespace { | 30 namespace { |
31 | 31 |
32 using ::testing::Mock; | 32 using ::testing::Mock; |
33 using ::testing::NiceMock; | 33 using ::testing::NiceMock; |
34 using ::testing::StrictMock; | 34 using ::testing::StrictMock; |
35 using content::BrowserThread; | 35 using content::BrowserThread; |
36 | 36 |
37 // Receives a ChromeSyncNotificationBridge to register to, and an expected | 37 // Receives a ChromeSyncNotificationBridge to register to, and an expected |
38 // ModelTypePayloadMap. ReceivedProperNotification() will return true only | 38 // ModelTypeStateMap. ReceivedProperNotification() will return true only |
39 // if the observer has received a notification with the proper source and | 39 // if the observer has received a notification with the proper source and |
40 // payload. | 40 // state. |
41 // Note: Because this object lives on the sync thread, we use a fake | 41 // Note: Because this object lives on the sync thread, we use a fake |
42 // (vs a mock) so we don't have to worry about possible thread safety | 42 // (vs a mock) so we don't have to worry about possible thread safety |
43 // issues within GTest/GMock. | 43 // issues within GTest/GMock. |
44 class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver { | 44 class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver { |
45 public: | 45 public: |
46 FakeSyncNotifierObserver( | 46 FakeSyncNotifierObserver( |
47 const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner, | 47 const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner, |
48 ChromeSyncNotificationBridge* bridge, | 48 ChromeSyncNotificationBridge* bridge, |
49 const syncer::ObjectIdPayloadMap& expected_payloads, | 49 const syncer::ObjectIdStateMap& expected_states, |
50 syncer::IncomingNotificationSource expected_source) | 50 syncer::IncomingNotificationSource expected_source) |
51 : sync_task_runner_(sync_task_runner), | 51 : sync_task_runner_(sync_task_runner), |
52 bridge_(bridge), | 52 bridge_(bridge), |
53 received_improper_notification_(false), | 53 received_improper_notification_(false), |
54 notification_count_(0), | 54 notification_count_(0), |
55 expected_payloads_(expected_payloads), | 55 expected_states_(expected_states), |
56 expected_source_(expected_source) { | 56 expected_source_(expected_source) { |
57 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); | 57 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); |
58 bridge_->RegisterHandler(this); | 58 bridge_->RegisterHandler(this); |
59 const syncer::ObjectIdSet& ids = | 59 const syncer::ObjectIdSet& ids = |
60 syncer::ObjectIdPayloadMapToSet(expected_payloads); | 60 syncer::ObjectIdStateMapToSet(expected_states); |
61 bridge_->UpdateRegisteredIds(this, ids); | 61 bridge_->UpdateRegisteredIds(this, ids); |
62 } | 62 } |
63 | 63 |
64 virtual ~FakeSyncNotifierObserver() { | 64 virtual ~FakeSyncNotifierObserver() { |
65 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); | 65 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); |
66 bridge_->UnregisterHandler(this); | 66 bridge_->UnregisterHandler(this); |
67 } | 67 } |
68 | 68 |
69 // SyncNotifierObserver implementation. | 69 // SyncNotifierObserver implementation. |
70 virtual void OnIncomingNotification( | 70 virtual void OnIncomingNotification( |
71 const syncer::ObjectIdPayloadMap& id_payloads, | 71 const syncer::ObjectIdStateMap& id_state_map, |
72 syncer::IncomingNotificationSource source) OVERRIDE { | 72 syncer::IncomingNotificationSource source) OVERRIDE { |
73 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); | 73 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); |
74 notification_count_++; | 74 notification_count_++; |
75 if (source != expected_source_) { | 75 if (source != expected_source_) { |
76 LOG(ERROR) << "Received notification with wrong source"; | 76 LOG(ERROR) << "Received notification with wrong source"; |
77 received_improper_notification_ = true; | 77 received_improper_notification_ = true; |
78 } | 78 } |
79 if (expected_payloads_ != id_payloads) { | 79 if (expected_states_ != id_state_map) { |
80 LOG(ERROR) << "Received wrong payload"; | 80 LOG(ERROR) << "Received wrong state"; |
81 received_improper_notification_ = true; | 81 received_improper_notification_ = true; |
82 } | 82 } |
83 } | 83 } |
84 virtual void OnNotificationsEnabled() OVERRIDE { | 84 virtual void OnNotificationsEnabled() OVERRIDE { |
85 NOTREACHED(); | 85 NOTREACHED(); |
86 } | 86 } |
87 virtual void OnNotificationsDisabled( | 87 virtual void OnNotificationsDisabled( |
88 syncer::NotificationsDisabledReason reason) OVERRIDE { | 88 syncer::NotificationsDisabledReason reason) OVERRIDE { |
89 NOTREACHED(); | 89 NOTREACHED(); |
90 } | 90 } |
91 | 91 |
92 bool ReceivedProperNotification() const { | 92 bool ReceivedProperNotification() const { |
93 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); | 93 DCHECK(sync_task_runner_->RunsTasksOnCurrentThread()); |
94 return (notification_count_ == 1) && !received_improper_notification_; | 94 return (notification_count_ == 1) && !received_improper_notification_; |
95 } | 95 } |
96 | 96 |
97 private: | 97 private: |
98 const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; | 98 const scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; |
99 ChromeSyncNotificationBridge* const bridge_; | 99 ChromeSyncNotificationBridge* const bridge_; |
100 bool received_improper_notification_; | 100 bool received_improper_notification_; |
101 size_t notification_count_; | 101 size_t notification_count_; |
102 const syncer::ObjectIdPayloadMap expected_payloads_; | 102 const syncer::ObjectIdStateMap expected_states_; |
103 const syncer::IncomingNotificationSource expected_source_; | 103 const syncer::IncomingNotificationSource expected_source_; |
104 }; | 104 }; |
105 | 105 |
106 class ChromeSyncNotificationBridgeTest : public testing::Test { | 106 class ChromeSyncNotificationBridgeTest : public testing::Test { |
107 public: | 107 public: |
108 ChromeSyncNotificationBridgeTest() | 108 ChromeSyncNotificationBridgeTest() |
109 : ui_thread_(BrowserThread::UI), | 109 : ui_thread_(BrowserThread::UI), |
110 sync_thread_("Sync thread"), | 110 sync_thread_("Sync thread"), |
111 sync_observer_(NULL), | 111 sync_observer_(NULL), |
112 sync_observer_notification_failure_(false), | 112 sync_observer_notification_failure_(false), |
(...skipping 22 matching lines...) Expand all Loading... |
135 void VerifyAndDestroyObserver() { | 135 void VerifyAndDestroyObserver() { |
136 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( | 136 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( |
137 FROM_HERE, | 137 FROM_HERE, |
138 base::Bind(&ChromeSyncNotificationBridgeTest:: | 138 base::Bind(&ChromeSyncNotificationBridgeTest:: |
139 VerifyAndDestroyObserverOnSyncThread, | 139 VerifyAndDestroyObserverOnSyncThread, |
140 base::Unretained(this)))); | 140 base::Unretained(this)))); |
141 BlockForSyncThread(); | 141 BlockForSyncThread(); |
142 } | 142 } |
143 | 143 |
144 void CreateObserverWithExpectations( | 144 void CreateObserverWithExpectations( |
145 const syncer::ModelTypePayloadMap& expected_payloads, | 145 const syncer::ModelTypeStateMap& expected_states, |
146 syncer::IncomingNotificationSource expected_source) { | 146 syncer::IncomingNotificationSource expected_source) { |
147 const syncer::ObjectIdPayloadMap& expected_id_payloads = | 147 const syncer::ObjectIdStateMap& expected_id_state_map = |
148 syncer::ModelTypePayloadMapToObjectIdPayloadMap(expected_payloads); | 148 syncer::ModelTypeStateMapToObjectIdStateMap(expected_states); |
149 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( | 149 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( |
150 FROM_HERE, | 150 FROM_HERE, |
151 base::Bind( | 151 base::Bind( |
152 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread, | 152 &ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread, |
153 base::Unretained(this), | 153 base::Unretained(this), |
154 expected_id_payloads, | 154 expected_id_state_map, |
155 expected_source))); | 155 expected_source))); |
156 BlockForSyncThread(); | 156 BlockForSyncThread(); |
157 } | 157 } |
158 | 158 |
159 void UpdateBridgeEnabledTypes(syncer::ModelTypeSet enabled_types) { | 159 void UpdateBridgeEnabledTypes(syncer::ModelTypeSet enabled_types) { |
160 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( | 160 ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask( |
161 FROM_HERE, | 161 FROM_HERE, |
162 base::Bind( | 162 base::Bind( |
163 &ChromeSyncNotificationBridgeTest:: | 163 &ChromeSyncNotificationBridgeTest:: |
164 UpdateBridgeEnabledTypesOnSyncThread, | 164 UpdateBridgeEnabledTypesOnSyncThread, |
165 base::Unretained(this), | 165 base::Unretained(this), |
166 enabled_types))); | 166 enabled_types))); |
167 BlockForSyncThread(); | 167 BlockForSyncThread(); |
168 } | 168 } |
169 | 169 |
170 void TriggerRefreshNotification( | 170 void TriggerRefreshNotification( |
171 int type, | 171 int type, |
172 const syncer::ModelTypePayloadMap& payload_map) { | 172 const syncer::ModelTypeStateMap& state_map) { |
173 content::NotificationService::current()->Notify( | 173 content::NotificationService::current()->Notify( |
174 type, | 174 type, |
175 content::Source<Profile>(&mock_profile_), | 175 content::Source<Profile>(&mock_profile_), |
176 content::Details<const syncer::ModelTypePayloadMap>(&payload_map)); | 176 content::Details<const syncer::ModelTypeStateMap>(&state_map)); |
177 } | 177 } |
178 | 178 |
179 private: | 179 private: |
180 void VerifyAndDestroyObserverOnSyncThread() { | 180 void VerifyAndDestroyObserverOnSyncThread() { |
181 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); | 181 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); |
182 if (!sync_observer_) { | 182 if (!sync_observer_) { |
183 sync_observer_notification_failure_ = true; | 183 sync_observer_notification_failure_ = true; |
184 } else { | 184 } else { |
185 sync_observer_notification_failure_ = | 185 sync_observer_notification_failure_ = |
186 !sync_observer_->ReceivedProperNotification(); | 186 !sync_observer_->ReceivedProperNotification(); |
187 delete sync_observer_; | 187 delete sync_observer_; |
188 sync_observer_ = NULL; | 188 sync_observer_ = NULL; |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 void CreateObserverOnSyncThread( | 192 void CreateObserverOnSyncThread( |
193 const syncer::ObjectIdPayloadMap& expected_payloads, | 193 const syncer::ObjectIdStateMap& expected_states, |
194 syncer::IncomingNotificationSource expected_source) { | 194 syncer::IncomingNotificationSource expected_source) { |
195 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); | 195 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); |
196 sync_observer_ = new FakeSyncNotifierObserver( | 196 sync_observer_ = new FakeSyncNotifierObserver( |
197 sync_thread_.message_loop_proxy(), | 197 sync_thread_.message_loop_proxy(), |
198 bridge_.get(), | 198 bridge_.get(), |
199 expected_payloads, | 199 expected_states, |
200 expected_source); | 200 expected_source); |
201 } | 201 } |
202 | 202 |
203 void UpdateBridgeEnabledTypesOnSyncThread( | 203 void UpdateBridgeEnabledTypesOnSyncThread( |
204 syncer::ModelTypeSet enabled_types) { | 204 syncer::ModelTypeSet enabled_types) { |
205 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); | 205 DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread()); |
206 bridge_->UpdateEnabledTypes(enabled_types); | 206 bridge_->UpdateEnabledTypes(enabled_types); |
207 } | 207 } |
208 | 208 |
209 void SignalOnSyncThread() { | 209 void SignalOnSyncThread() { |
(...skipping 17 matching lines...) Expand all Loading... |
227 NiceMock<ProfileMock> mock_profile_; | 227 NiceMock<ProfileMock> mock_profile_; |
228 // Created/used/destroyed on sync thread. | 228 // Created/used/destroyed on sync thread. |
229 FakeSyncNotifierObserver* sync_observer_; | 229 FakeSyncNotifierObserver* sync_observer_; |
230 bool sync_observer_notification_failure_; | 230 bool sync_observer_notification_failure_; |
231 scoped_ptr<ChromeSyncNotificationBridge> bridge_; | 231 scoped_ptr<ChromeSyncNotificationBridge> bridge_; |
232 base::WaitableEvent done_; | 232 base::WaitableEvent done_; |
233 }; | 233 }; |
234 | 234 |
235 // Adds an observer on the sync thread, triggers a local refresh | 235 // Adds an observer on the sync thread, triggers a local refresh |
236 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION | 236 // notification, and ensures the bridge posts a LOCAL_NOTIFICATION |
237 // with the proper payload to it. | 237 // with the proper state to it. |
238 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) { | 238 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotification) { |
239 syncer::ModelTypePayloadMap payload_map; | 239 syncer::ModelTypeStateMap state_map; |
240 payload_map[syncer::SESSIONS] = ""; | 240 state_map.insert( |
241 CreateObserverWithExpectations(payload_map, syncer::LOCAL_NOTIFICATION); | 241 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); |
| 242 CreateObserverWithExpectations(state_map, syncer::LOCAL_NOTIFICATION); |
242 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, | 243 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, |
243 payload_map); | 244 state_map); |
244 VerifyAndDestroyObserver(); | 245 VerifyAndDestroyObserver(); |
245 } | 246 } |
246 | 247 |
247 // Adds an observer on the sync thread, triggers a remote refresh | 248 // Adds an observer on the sync thread, triggers a remote refresh |
248 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION | 249 // notification, and ensures the bridge posts a REMOTE_NOTIFICATION |
249 // with the proper payload to it. | 250 // with the proper state to it. |
250 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) { | 251 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotification) { |
251 syncer::ModelTypePayloadMap payload_map; | 252 syncer::ModelTypeStateMap state_map; |
252 payload_map[syncer::SESSIONS] = ""; | 253 state_map.insert( |
253 CreateObserverWithExpectations(payload_map, syncer::REMOTE_NOTIFICATION); | 254 std::make_pair(syncer::SESSIONS, syncer::InvalidationState())); |
| 255 CreateObserverWithExpectations(state_map, syncer::REMOTE_NOTIFICATION); |
254 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, | 256 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, |
255 payload_map); | 257 state_map); |
256 VerifyAndDestroyObserver(); | 258 VerifyAndDestroyObserver(); |
257 } | 259 } |
258 | 260 |
259 // Adds an observer on the sync thread, triggers a local refresh | 261 // Adds an observer on the sync thread, triggers a local refresh |
260 // notification with empty payload map and ensures the bridge posts a | 262 // notification with empty state map and ensures the bridge posts a |
261 // LOCAL_NOTIFICATION with the proper payload to it. | 263 // LOCAL_NOTIFICATION with the proper state to it. |
262 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) { | 264 TEST_F(ChromeSyncNotificationBridgeTest, LocalNotificationEmptyPayloadMap) { |
263 const syncer::ModelTypeSet enabled_types( | 265 const syncer::ModelTypeSet enabled_types( |
264 syncer::BOOKMARKS, syncer::PASSWORDS); | 266 syncer::BOOKMARKS, syncer::PASSWORDS); |
265 const syncer::ModelTypePayloadMap enabled_types_payload_map = | 267 const syncer::ModelTypeStateMap enabled_types_state_map = |
266 syncer::ModelTypePayloadMapFromEnumSet(enabled_types, std::string()); | 268 syncer::ModelTypeStateMapFromEnumSet(enabled_types, std::string()); |
267 CreateObserverWithExpectations( | 269 CreateObserverWithExpectations( |
268 enabled_types_payload_map, syncer::LOCAL_NOTIFICATION); | 270 enabled_types_state_map, syncer::LOCAL_NOTIFICATION); |
269 UpdateBridgeEnabledTypes(enabled_types); | 271 UpdateBridgeEnabledTypes(enabled_types); |
270 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, | 272 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, |
271 syncer::ModelTypePayloadMap()); | 273 syncer::ModelTypeStateMap()); |
272 VerifyAndDestroyObserver(); | 274 VerifyAndDestroyObserver(); |
273 } | 275 } |
274 | 276 |
275 // Adds an observer on the sync thread, triggers a remote refresh | 277 // Adds an observer on the sync thread, triggers a remote refresh |
276 // notification with empty payload map and ensures the bridge posts a | 278 // notification with empty state map and ensures the bridge posts a |
277 // REMOTE_NOTIFICATION with the proper payload to it. | 279 // REMOTE_NOTIFICATION with the proper state to it. |
278 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) { | 280 TEST_F(ChromeSyncNotificationBridgeTest, RemoteNotificationEmptyPayloadMap) { |
279 const syncer::ModelTypeSet enabled_types( | 281 const syncer::ModelTypeSet enabled_types( |
280 syncer::BOOKMARKS, syncer::TYPED_URLS); | 282 syncer::BOOKMARKS, syncer::TYPED_URLS); |
281 const syncer::ModelTypePayloadMap enabled_types_payload_map = | 283 const syncer::ModelTypeStateMap enabled_types_state_map = |
282 syncer::ModelTypePayloadMapFromEnumSet(enabled_types, std::string()); | 284 syncer::ModelTypeStateMapFromEnumSet(enabled_types, std::string()); |
283 CreateObserverWithExpectations( | 285 CreateObserverWithExpectations( |
284 enabled_types_payload_map, syncer::REMOTE_NOTIFICATION); | 286 enabled_types_state_map, syncer::REMOTE_NOTIFICATION); |
285 UpdateBridgeEnabledTypes(enabled_types); | 287 UpdateBridgeEnabledTypes(enabled_types); |
286 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, | 288 TriggerRefreshNotification(chrome::NOTIFICATION_SYNC_REFRESH_REMOTE, |
287 syncer::ModelTypePayloadMap()); | 289 syncer::ModelTypeStateMap()); |
288 VerifyAndDestroyObserver(); | 290 VerifyAndDestroyObserver(); |
289 } | 291 } |
290 | 292 |
291 } // namespace | 293 } // namespace |
292 } // namespace browser_sync | 294 } // namespace browser_sync |
OLD | NEW |