| 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/sessions/nudge_tracker.h" | 5 #include "sync/sessions/nudge_tracker.h" | 
| 6 | 6 | 
| 7 #include "sync/internal_api/public/base/model_type_invalidation_map.h" | 7 #include "sync/internal_api/public/base/model_type_invalidation_map.h" | 
|  | 8 #include "sync/internal_api/public/sessions/sync_source_info.h" | 
| 8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" | 
| 9 | 10 | 
| 10 namespace syncer { | 11 namespace syncer { | 
| 11 | 12 | 
| 12 namespace { | 13 namespace { | 
| 13 | 14 | 
| 14 ModelTypeSet ParamsMeaningAllEnabledTypes() { | 15 testing::AssertionResult ModelTypeSetEquals(ModelTypeSet a, ModelTypeSet b) { | 
| 15   ModelTypeSet request_params(BOOKMARKS, AUTOFILL); | 16   if (a.Equals(b)) { | 
| 16   return request_params; | 17     return testing::AssertionSuccess(); | 
| 17 } | 18   } else { | 
| 18 | 19     return testing::AssertionFailure() | 
| 19 ModelTypeSet ParamsMeaningJustOneEnabledType() { | 20         << "Left side " << ModelTypeSetToString(a) | 
| 20   return ModelTypeSet(AUTOFILL); | 21         << ", does not match rigth side: " << ModelTypeSetToString(b); | 
|  | 22   } | 
| 21 } | 23 } | 
| 22 | 24 | 
| 23 }  // namespace | 25 }  // namespace | 
| 24 | 26 | 
| 25 namespace sessions { | 27 namespace sessions { | 
| 26 | 28 | 
| 27 TEST(NudgeTrackerTest, CoalesceSources) { | 29 class NudgeTrackerTest : public ::testing::Test { | 
| 28   ModelTypeInvalidationMap one_type = | 30  public: | 
| 29       ModelTypeSetToInvalidationMap( | 31   static size_t GetHintBufferSize() { | 
| 30           ParamsMeaningJustOneEnabledType(), | 32     // Assumes that no test has adjusted this size. | 
| 31           std::string()); | 33     return NudgeTracker::kDefaultMaxPayloadsPerType; | 
| 32   ModelTypeInvalidationMap all_types = | 34   } | 
| 33       ModelTypeSetToInvalidationMap( | 35 | 
| 34           ParamsMeaningAllEnabledTypes(), | 36   bool InvalidationsOutOfSync(const NudgeTracker& nudge_tracker) { | 
| 35           std::string()); | 37     // We don't currently track invalidations out of sync on a per-type basis. | 
| 36   sessions::SyncSourceInfo source_one( | 38     sync_pb::GetUpdateTriggers gu_trigger; | 
| 37       sync_pb::GetUpdatesCallerInfo::NOTIFICATION, one_type); | 39     nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
| 38   sessions::SyncSourceInfo source_two( | 40     return gu_trigger.invalidations_out_of_sync(); | 
| 39       sync_pb::GetUpdatesCallerInfo::LOCAL, all_types); | 41   } | 
| 40 | 42 | 
| 41   NudgeTracker tracker; | 43   int ProtoLocallyModifiedCount(const NudgeTracker& nudge_tracker, | 
| 42   EXPECT_TRUE(tracker.IsEmpty()); | 44                                 ModelType type) { | 
| 43 | 45     sync_pb::GetUpdateTriggers gu_trigger; | 
| 44   tracker.CoalesceSources(source_one); | 46     nudge_tracker.FillProtoMessage(type, &gu_trigger); | 
| 45   EXPECT_EQ(source_one.updates_source, tracker.source_info().updates_source); | 47     return gu_trigger.local_modification_nudges(); | 
| 46 | 48   } | 
| 47   tracker.CoalesceSources(source_two); | 49 | 
| 48   EXPECT_EQ(source_two.updates_source, tracker.source_info().updates_source); | 50   int ProtoRefreshRequestedCount(const NudgeTracker& nudge_tracker, | 
| 49 } | 51                                  ModelType type) { | 
| 50 | 52     sync_pb::GetUpdateTriggers gu_trigger; | 
| 51 TEST(NudgeTrackerTest, LocallyModifiedTypes_WithInvalidationFirst) { | 53     nudge_tracker.FillProtoMessage(type, &gu_trigger); | 
| 52   ModelTypeInvalidationMap one_type = | 54     return gu_trigger.datatype_refresh_nudges(); | 
| 53       ModelTypeSetToInvalidationMap( | 55   } | 
| 54           ParamsMeaningJustOneEnabledType(), | 56 }; | 
| 55           std::string()); | 57 | 
| 56   ModelTypeInvalidationMap all_types = | 58 // Exercise an empty NudgeTracker. | 
| 57       ModelTypeSetToInvalidationMap( | 59 // Use with valgrind to detect uninitialized members. | 
| 58           ParamsMeaningAllEnabledTypes(), | 60 TEST_F(NudgeTrackerTest, EmptyNudgeTracker) { | 
| 59           std::string()); | 61   NudgeTracker nudge_tracker; | 
| 60   sessions::SyncSourceInfo source_one( | 62 | 
| 61       sync_pb::GetUpdatesCallerInfo::NOTIFICATION, all_types); | 63   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, | 
| 62   sessions::SyncSourceInfo source_two( | 64             nudge_tracker.updates_source()); | 
| 63       sync_pb::GetUpdatesCallerInfo::LOCAL, one_type); | 65   EXPECT_TRUE(nudge_tracker.GetLocallyModifiedTypes().Empty()); | 
| 64 | 66 | 
| 65   NudgeTracker tracker; | 67   sync_pb::GetUpdateTriggers gu_trigger; | 
| 66   EXPECT_TRUE(tracker.IsEmpty()); | 68   nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
| 67   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Empty()); | 69 | 
| 68 | 70   SyncSourceInfo source_info = nudge_tracker.GetSourceInfo(); | 
| 69   tracker.CoalesceSources(source_one); | 71   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, | 
| 70   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Empty()); | 72             source_info.updates_source); | 
| 71 | 73 } | 
| 72   tracker.CoalesceSources(source_two); | 74 | 
| 73   // TODO: This result is wrong, but that's how the code has always been.  A | 75 // Verify that nudges override each other based on a priority order. | 
| 74   // local invalidation for a single type should mean that we have only one | 76 // LOCAL < DATATYPE_REFRESH < NOTIFICATION | 
| 75   // locally modified source.  It should not "inherit" the list of data types | 77 TEST_F(NudgeTrackerTest, SourcePriorities) { | 
| 76   // from the previous source. | 78   NudgeTracker nudge_tracker; | 
| 77   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Equals( | 79 | 
| 78           ParamsMeaningAllEnabledTypes())); | 80   // Track a local nudge. | 
| 79 } | 81   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS)); | 
| 80 | 82   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL, | 
| 81 TEST(NudgeTrackerTest, LocallyModifiedTypes_WithInvalidationSecond) { | 83             nudge_tracker.updates_source()); | 
| 82   ModelTypeInvalidationMap one_type = | 84 | 
| 83       ModelTypeSetToInvalidationMap( | 85   // A refresh request will override it. | 
| 84           ParamsMeaningJustOneEnabledType(), | 86   nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(TYPED_URLS)); | 
| 85           std::string()); | 87   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH, | 
| 86   ModelTypeInvalidationMap all_types = | 88             nudge_tracker.updates_source()); | 
| 87       ModelTypeSetToInvalidationMap( | 89 | 
| 88           ParamsMeaningAllEnabledTypes(), | 90   // Another local nudge will not be enough to change it. | 
| 89           std::string()); | 91   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS)); | 
| 90   sessions::SyncSourceInfo source_one( | 92   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH, | 
| 91       sync_pb::GetUpdatesCallerInfo::LOCAL, one_type); | 93             nudge_tracker.updates_source()); | 
| 92   sessions::SyncSourceInfo source_two( | 94 | 
| 93       sync_pb::GetUpdatesCallerInfo::NOTIFICATION, all_types); | 95   // An invalidation will override the refresh request source. | 
| 94 | 96   ModelTypeInvalidationMap invalidation_map = | 
| 95   NudgeTracker tracker; | 97       ModelTypeSetToInvalidationMap(ModelTypeSet(PREFERENCES), | 
| 96   EXPECT_TRUE(tracker.IsEmpty()); | 98                                     std::string("hint")); | 
| 97   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Empty()); | 99   nudge_tracker.RecordRemoteInvalidation(invalidation_map); | 
| 98 | 100   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION, | 
| 99   tracker.CoalesceSources(source_one); | 101             nudge_tracker.updates_source()); | 
| 100   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Equals( | 102 | 
| 101           ParamsMeaningJustOneEnabledType())); | 103   // Neither local nudges nor refresh requests will override it. | 
| 102 | 104   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS)); | 
| 103   tracker.CoalesceSources(source_two); | 105   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION, | 
| 104 | 106             nudge_tracker.updates_source()); | 
| 105   // TODO: This result is wrong, but that's how the code has always been. | 107   nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(TYPED_URLS)); | 
| 106   // The receipt of an invalidation should have no effect on the set of | 108   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION, | 
| 107   // locally modified types. | 109             nudge_tracker.updates_source()); | 
| 108   EXPECT_TRUE(tracker.GetLocallyModifiedTypes().Empty()); | 110 } | 
|  | 111 | 
|  | 112 // Verify locally modified type coalescing and independence from other nudges. | 
|  | 113 TEST_F(NudgeTrackerTest, LocallyModifiedTypes) { | 
|  | 114   NudgeTracker nudge_tracker; | 
|  | 115 | 
|  | 116   // Start with a notification.  Verify it has no effect. | 
|  | 117   ModelTypeInvalidationMap invalidation_map1 = | 
|  | 118       ModelTypeSetToInvalidationMap(ModelTypeSet(PREFERENCES), | 
|  | 119                                     std::string("hint")); | 
|  | 120   nudge_tracker.RecordRemoteInvalidation(invalidation_map1); | 
|  | 121   EXPECT_TRUE(nudge_tracker.GetLocallyModifiedTypes().Empty()); | 
|  | 122 | 
|  | 123   // Record a local bookmark change.  Verify it was registered correctly. | 
|  | 124   nudge_tracker.RecordLocalChange(ModelTypeSet(BOOKMARKS)); | 
|  | 125   EXPECT_TRUE(ModelTypeSetEquals( | 
|  | 126           ModelTypeSet(BOOKMARKS), | 
|  | 127           nudge_tracker.GetLocallyModifiedTypes())); | 
|  | 128 | 
|  | 129   // Record a notification and a refresh request.  Verify they have no effect. | 
|  | 130   ModelTypeInvalidationMap invalidation_map2 = | 
|  | 131       ModelTypeSetToInvalidationMap(ModelTypeSet(PASSWORDS), | 
|  | 132                                     std::string("hint")); | 
|  | 133   nudge_tracker.RecordRemoteInvalidation(invalidation_map2); | 
|  | 134   EXPECT_TRUE(ModelTypeSetEquals( | 
|  | 135           ModelTypeSet(BOOKMARKS), | 
|  | 136           nudge_tracker.GetLocallyModifiedTypes())); | 
|  | 137 | 
|  | 138   nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(AUTOFILL)); | 
|  | 139   EXPECT_TRUE(ModelTypeSetEquals( | 
|  | 140           ModelTypeSet(BOOKMARKS), | 
|  | 141           nudge_tracker.GetLocallyModifiedTypes())); | 
|  | 142 | 
|  | 143   // Record another local nudge.  Verify it was coalesced correctly. | 
|  | 144   nudge_tracker.RecordLocalChange(ModelTypeSet(THEMES)); | 
|  | 145   EXPECT_TRUE(ModelTypeSetEquals( | 
|  | 146           ModelTypeSet(THEMES, BOOKMARKS), | 
|  | 147           nudge_tracker.GetLocallyModifiedTypes())); | 
|  | 148 } | 
|  | 149 | 
|  | 150 TEST_F(NudgeTrackerTest, HintCoalescing) { | 
|  | 151   NudgeTracker nudge_tracker; | 
|  | 152 | 
|  | 153   // Easy case: record one hint. | 
|  | 154   { | 
|  | 155     ModelTypeInvalidationMap invalidation_map = | 
|  | 156         ModelTypeSetToInvalidationMap(ModelTypeSet(BOOKMARKS), | 
|  | 157                                       std::string("bm_hint_1")); | 
|  | 158     nudge_tracker.RecordRemoteInvalidation(invalidation_map); | 
|  | 159 | 
|  | 160     sync_pb::GetUpdateTriggers gu_trigger; | 
|  | 161     nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
|  | 162     ASSERT_EQ(1, gu_trigger.notification_hint_size()); | 
|  | 163     EXPECT_EQ("bm_hint_1", gu_trigger.notification_hint(0)); | 
|  | 164     EXPECT_FALSE(gu_trigger.client_dropped_hints()); | 
|  | 165   } | 
|  | 166 | 
|  | 167   // Record a second hint for the same type. | 
|  | 168   { | 
|  | 169     ModelTypeInvalidationMap invalidation_map = | 
|  | 170         ModelTypeSetToInvalidationMap(ModelTypeSet(BOOKMARKS), | 
|  | 171                                       std::string("bm_hint_2")); | 
|  | 172     nudge_tracker.RecordRemoteInvalidation(invalidation_map); | 
|  | 173 | 
|  | 174     sync_pb::GetUpdateTriggers gu_trigger; | 
|  | 175     nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
|  | 176     ASSERT_EQ(2, gu_trigger.notification_hint_size()); | 
|  | 177 | 
|  | 178     // Expect the most hint recent is last in the list. | 
|  | 179     EXPECT_EQ("bm_hint_1", gu_trigger.notification_hint(0)); | 
|  | 180     EXPECT_EQ("bm_hint_2", gu_trigger.notification_hint(1)); | 
|  | 181     EXPECT_FALSE(gu_trigger.client_dropped_hints()); | 
|  | 182   } | 
|  | 183 | 
|  | 184   // Record a hint for a different type. | 
|  | 185   { | 
|  | 186     ModelTypeInvalidationMap invalidation_map = | 
|  | 187         ModelTypeSetToInvalidationMap(ModelTypeSet(PASSWORDS), | 
|  | 188                                       std::string("pw_hint_1")); | 
|  | 189     nudge_tracker.RecordRemoteInvalidation(invalidation_map); | 
|  | 190 | 
|  | 191     // Re-verify the bookmarks to make sure they're unaffected. | 
|  | 192     sync_pb::GetUpdateTriggers bm_gu_trigger; | 
|  | 193     nudge_tracker.FillProtoMessage(BOOKMARKS, &bm_gu_trigger); | 
|  | 194     ASSERT_EQ(2, bm_gu_trigger.notification_hint_size()); | 
|  | 195     EXPECT_EQ("bm_hint_1", bm_gu_trigger.notification_hint(0)); | 
|  | 196     EXPECT_EQ("bm_hint_2", | 
|  | 197               bm_gu_trigger.notification_hint(1)); // most recent last. | 
|  | 198     EXPECT_FALSE(bm_gu_trigger.client_dropped_hints()); | 
|  | 199 | 
|  | 200     // Verify the new type, too. | 
|  | 201     sync_pb::GetUpdateTriggers pw_gu_trigger; | 
|  | 202     nudge_tracker.FillProtoMessage(PASSWORDS, &pw_gu_trigger); | 
|  | 203     ASSERT_EQ(1, pw_gu_trigger.notification_hint_size()); | 
|  | 204     EXPECT_EQ("pw_hint_1", pw_gu_trigger.notification_hint(0)); | 
|  | 205     EXPECT_FALSE(pw_gu_trigger.client_dropped_hints()); | 
|  | 206   } | 
|  | 207 } | 
|  | 208 | 
|  | 209 TEST_F(NudgeTrackerTest, DropHintsLocally) { | 
|  | 210   NudgeTracker nudge_tracker; | 
|  | 211   ModelTypeInvalidationMap invalidation_map = | 
|  | 212       ModelTypeSetToInvalidationMap(ModelTypeSet(BOOKMARKS), | 
|  | 213                                     std::string("hint")); | 
|  | 214 | 
|  | 215   for (size_t i = 0; i < GetHintBufferSize(); ++i) { | 
|  | 216     nudge_tracker.RecordRemoteInvalidation(invalidation_map); | 
|  | 217   } | 
|  | 218   { | 
|  | 219     sync_pb::GetUpdateTriggers gu_trigger; | 
|  | 220     nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
|  | 221     EXPECT_EQ(GetHintBufferSize(), | 
|  | 222               static_cast<size_t>(gu_trigger.notification_hint_size())); | 
|  | 223     EXPECT_FALSE(gu_trigger.client_dropped_hints()); | 
|  | 224   } | 
|  | 225 | 
|  | 226   // Force an overflow. | 
|  | 227   ModelTypeInvalidationMap invalidation_map2 = | 
|  | 228       ModelTypeSetToInvalidationMap(ModelTypeSet(BOOKMARKS), | 
|  | 229                                     std::string("new_hint")); | 
|  | 230   nudge_tracker.RecordRemoteInvalidation(invalidation_map2); | 
|  | 231 | 
|  | 232   { | 
|  | 233     sync_pb::GetUpdateTriggers gu_trigger; | 
|  | 234     nudge_tracker.FillProtoMessage(BOOKMARKS, &gu_trigger); | 
|  | 235     EXPECT_EQ(GetHintBufferSize(), | 
|  | 236               static_cast<size_t>(gu_trigger.notification_hint_size())); | 
|  | 237     EXPECT_TRUE(gu_trigger.client_dropped_hints()); | 
|  | 238 | 
|  | 239     // Verify the newest hint was not dropped and is the last in the list. | 
|  | 240     EXPECT_EQ("new_hint", gu_trigger.notification_hint(GetHintBufferSize()-1)); | 
|  | 241 | 
|  | 242     // Verify the oldest hint, too. | 
|  | 243     EXPECT_EQ("hint", gu_trigger.notification_hint(0)); | 
|  | 244   } | 
|  | 245 } | 
|  | 246 | 
|  | 247 // TODO(rlarocque): Add trickles support.  See crbug.com/223437. | 
|  | 248 // TEST_F(NudgeTrackerTest, DropHintsAtServer); | 
|  | 249 | 
|  | 250 // Checks the behaviour of the invalidations-out-of-sync flag. | 
|  | 251 TEST_F(NudgeTrackerTest, EnableDisableInvalidations) { | 
|  | 252   NudgeTracker nudge_tracker; | 
|  | 253 | 
|  | 254   // By default, assume we're out of sync with the invalidation server. | 
|  | 255   EXPECT_TRUE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 256 | 
|  | 257   // Simply enabling invalidations does not bring us back into sync. | 
|  | 258   nudge_tracker.OnInvalidationsEnabled(); | 
|  | 259   EXPECT_TRUE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 260 | 
|  | 261   // We must successfully complete a sync cycle while invalidations are enabled | 
|  | 262   // to be sure that we're in sync. | 
|  | 263   nudge_tracker.RecordSuccessfulSyncCycle(); | 
|  | 264   EXPECT_FALSE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 265 | 
|  | 266   // If the invalidator malfunctions, we go become unsynced again. | 
|  | 267   nudge_tracker.OnInvalidationsDisabled(); | 
|  | 268   EXPECT_TRUE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 269 | 
|  | 270   // A sync cycle while invalidations are disabled won't reset the flag. | 
|  | 271   nudge_tracker.RecordSuccessfulSyncCycle(); | 
|  | 272   EXPECT_TRUE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 273 | 
|  | 274   // Nor will the re-enabling of invalidations be sufficient, even now that | 
|  | 275   // we've had a successful sync cycle. | 
|  | 276   nudge_tracker.RecordSuccessfulSyncCycle(); | 
|  | 277   EXPECT_TRUE(InvalidationsOutOfSync(nudge_tracker)); | 
|  | 278 } | 
|  | 279 | 
|  | 280 // Tests that locally modified types are correctly written out to the | 
|  | 281 // GetUpdateTriggers proto. | 
|  | 282 TEST_F(NudgeTrackerTest, WriteLocallyModifiedTypesToProto) { | 
|  | 283   NudgeTracker nudge_tracker; | 
|  | 284 | 
|  | 285   // Should not be locally modified by default. | 
|  | 286   EXPECT_EQ(0, ProtoLocallyModifiedCount(nudge_tracker, PREFERENCES)); | 
|  | 287 | 
|  | 288   // Record a local bookmark change.  Verify it was registered correctly. | 
|  | 289   nudge_tracker.RecordLocalChange(ModelTypeSet(PREFERENCES)); | 
|  | 290   EXPECT_EQ(1, ProtoLocallyModifiedCount(nudge_tracker, PREFERENCES)); | 
|  | 291 | 
|  | 292   // Record a successful sync cycle.  Verify the count is cleared. | 
|  | 293   nudge_tracker.RecordSuccessfulSyncCycle(); | 
|  | 294   EXPECT_EQ(0, ProtoLocallyModifiedCount(nudge_tracker, PREFERENCES)); | 
|  | 295 } | 
|  | 296 | 
|  | 297 // Tests that refresh requested types are correctly written out to the | 
|  | 298 // GetUpdateTriggers proto. | 
|  | 299 TEST_F(NudgeTrackerTest, WriteRefreshRequestedTypesToProto) { | 
|  | 300   NudgeTracker nudge_tracker; | 
|  | 301 | 
|  | 302   // There should be no refresh requested by default. | 
|  | 303   EXPECT_EQ(0, ProtoRefreshRequestedCount(nudge_tracker, SESSIONS)); | 
|  | 304 | 
|  | 305   // Record a local refresh request.  Verify it was registered correctly. | 
|  | 306   nudge_tracker.RecordLocalRefreshRequest(ModelTypeSet(SESSIONS)); | 
|  | 307   EXPECT_EQ(1, ProtoRefreshRequestedCount(nudge_tracker, SESSIONS)); | 
|  | 308 | 
|  | 309   // Record a successful sync cycle.  Verify the count is cleared. | 
|  | 310   nudge_tracker.RecordSuccessfulSyncCycle(); | 
|  | 311   EXPECT_EQ(0, ProtoRefreshRequestedCount(nudge_tracker, SESSIONS)); | 
| 109 } | 312 } | 
| 110 | 313 | 
| 111 }  // namespace sessions | 314 }  // namespace sessions | 
| 112 }  // namespace syncer | 315 }  // namespace syncer | 
| OLD | NEW | 
|---|