OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/sessions2/sessions_sync_manager.h" | 5 #include "chrome/browser/sync/sessions2/sessions_sync_manager.h" |
6 | 6 |
7 #include "base/strings/string_util.h" | 7 #include "base/strings/string_util.h" |
8 #include "chrome/browser/chrome_notification_types.h" | 8 #include "chrome/browser/chrome_notification_types.h" |
9 #include "chrome/browser/sessions/session_id.h" | 9 #include "chrome/browser/sessions/session_id.h" |
10 #include "chrome/browser/sessions/session_tab_helper.h" | 10 #include "chrome/browser/sessions/session_tab_helper.h" |
11 #include "chrome/browser/sessions/session_types.h" | 11 #include "chrome/browser/sessions/session_types.h" |
12 #include "chrome/browser/sync/glue/device_info.h" | 12 #include "chrome/browser/sync/glue/device_info.h" |
13 #include "chrome/browser/sync/glue/session_sync_test_helper.h" | 13 #include "chrome/browser/sync/glue/session_sync_test_helper.h" |
14 #include "chrome/browser/sync/glue/synced_tab_delegate.h" | 14 #include "chrome/browser/sync/glue/synced_tab_delegate.h" |
| 15 #include "chrome/browser/sync/sessions2/notification_service_sessions_router.h" |
15 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h" | 16 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h" |
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 17 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
17 #include "chrome/test/base/browser_with_test_window_test.h" | 18 #include "chrome/test/base/browser_with_test_window_test.h" |
18 #include "components/sessions/serialized_navigation_entry_test_helper.h" | 19 #include "components/sessions/serialized_navigation_entry_test_helper.h" |
19 #include "content/public/browser/navigation_entry.h" | 20 #include "content/public/browser/navigation_entry.h" |
20 #include "content/public/browser/notification_details.h" | 21 #include "content/public/browser/notification_details.h" |
21 #include "content/public/browser/notification_service.h" | 22 #include "content/public/browser/notification_service.h" |
22 #include "content/public/browser/notification_source.h" | 23 #include "content/public/browser/notification_source.h" |
23 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
24 #include "sync/api/sync_error_factory_mock.h" | 25 #include "sync/api/sync_error_factory_mock.h" |
(...skipping 10 matching lines...) Expand all Loading... |
35 | 36 |
36 namespace { | 37 namespace { |
37 | 38 |
38 class TestSyncProcessorStub : public syncer::SyncChangeProcessor { | 39 class TestSyncProcessorStub : public syncer::SyncChangeProcessor { |
39 public: | 40 public: |
40 explicit TestSyncProcessorStub(syncer::SyncChangeList* output) | 41 explicit TestSyncProcessorStub(syncer::SyncChangeList* output) |
41 : output_(output) {} | 42 : output_(output) {} |
42 virtual syncer::SyncError ProcessSyncChanges( | 43 virtual syncer::SyncError ProcessSyncChanges( |
43 const tracked_objects::Location& from_here, | 44 const tracked_objects::Location& from_here, |
44 const syncer::SyncChangeList& change_list) OVERRIDE { | 45 const syncer::SyncChangeList& change_list) OVERRIDE { |
| 46 if (error_.IsSet()) { |
| 47 syncer::SyncError error = error_; |
| 48 error_ = syncer::SyncError(); |
| 49 return error; |
| 50 } |
| 51 |
45 if (output_) | 52 if (output_) |
46 output_->assign(change_list.begin(), change_list.end()); | 53 output_->insert(output_->end(), change_list.begin(), change_list.end()); |
| 54 |
47 return syncer::SyncError(); | 55 return syncer::SyncError(); |
48 } | 56 } |
49 | 57 |
50 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) | 58 virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) |
51 const OVERRIDE { | 59 const OVERRIDE { |
52 return syncer::SyncDataList(); | 60 return syncer::SyncDataList(); |
53 } | 61 } |
| 62 |
| 63 void FailProcessSyncChangesWith(const syncer::SyncError& error) { |
| 64 error_ = error; |
| 65 } |
| 66 |
54 private: | 67 private: |
| 68 syncer::SyncError error_; |
55 syncer::SyncChangeList* output_; | 69 syncer::SyncChangeList* output_; |
56 }; | 70 }; |
57 | 71 |
58 syncer::SyncChange MakeRemoteChange( | 72 syncer::SyncChange MakeRemoteChange( |
59 int64 id, | 73 int64 id, |
60 const sync_pb::SessionSpecifics& specifics, | 74 const sync_pb::SessionSpecifics& specifics, |
61 SyncChange::SyncChangeType type) { | 75 SyncChange::SyncChangeType type) { |
62 sync_pb::EntitySpecifics entity; | 76 sync_pb::EntitySpecifics entity; |
63 entity.mutable_session()->CopyFrom(specifics); | 77 entity.mutable_session()->CopyFrom(specifics); |
64 return syncer::SyncChange( | 78 return syncer::SyncChange( |
(...skipping 20 matching lines...) Expand all Loading... |
85 void AddTabsToSyncDataList(const std::vector<sync_pb::SessionSpecifics> tabs, | 99 void AddTabsToSyncDataList(const std::vector<sync_pb::SessionSpecifics> tabs, |
86 syncer::SyncDataList* list) { | 100 syncer::SyncDataList* list) { |
87 for (size_t i = 0; i < tabs.size(); i++) { | 101 for (size_t i = 0; i < tabs.size(); i++) { |
88 sync_pb::EntitySpecifics entity; | 102 sync_pb::EntitySpecifics entity; |
89 entity.mutable_session()->CopyFrom(tabs[i]); | 103 entity.mutable_session()->CopyFrom(tabs[i]); |
90 list->push_back(SyncData::CreateRemoteData( | 104 list->push_back(SyncData::CreateRemoteData( |
91 i + 2, entity, base::Time())); | 105 i + 2, entity, base::Time())); |
92 } | 106 } |
93 } | 107 } |
94 | 108 |
| 109 class DummyRouter : public LocalSessionEventRouter { |
| 110 public: |
| 111 virtual ~DummyRouter() {} |
| 112 virtual void StartRoutingTo(LocalSessionEventHandler* handler) OVERRIDE {} |
| 113 virtual void Stop() OVERRIDE {} |
| 114 }; |
| 115 |
| 116 scoped_ptr<LocalSessionEventRouter> NewDummyRouter() { |
| 117 return scoped_ptr<LocalSessionEventRouter>(new DummyRouter()); |
| 118 } |
| 119 |
95 } // namespace | 120 } // namespace |
96 | 121 |
97 class SessionsSyncManagerTest | 122 class SessionsSyncManagerTest |
98 : public BrowserWithTestWindowTest, | 123 : public BrowserWithTestWindowTest, |
99 public SessionsSyncManager::SyncInternalApiDelegate { | 124 public SessionsSyncManager::SyncInternalApiDelegate { |
100 public: | 125 public: |
101 SessionsSyncManagerTest() {} | 126 SessionsSyncManagerTest() : test_processor_(NULL) {} |
102 | 127 |
103 virtual void SetUp() OVERRIDE { | 128 virtual void SetUp() OVERRIDE { |
104 BrowserWithTestWindowTest::SetUp(); | 129 BrowserWithTestWindowTest::SetUp(); |
105 manager_.reset(new SessionsSyncManager(profile(), this)); | 130 browser_sync::NotificationServiceSessionsRouter* router( |
| 131 new browser_sync::NotificationServiceSessionsRouter( |
| 132 profile(), syncer::SyncableService::StartSyncFlare())); |
| 133 manager_.reset(new SessionsSyncManager(profile(), this, |
| 134 scoped_ptr<LocalSessionEventRouter>(router))); |
106 } | 135 } |
107 | 136 |
108 virtual void TearDown() OVERRIDE { | 137 virtual void TearDown() OVERRIDE { |
| 138 test_processor_ = NULL; |
109 helper()->Reset(); | 139 helper()->Reset(); |
110 manager_.reset(); | 140 manager_.reset(); |
111 BrowserWithTestWindowTest::TearDown(); | 141 BrowserWithTestWindowTest::TearDown(); |
112 } | 142 } |
113 | 143 |
114 virtual scoped_ptr<DeviceInfo> GetLocalDeviceInfo() const OVERRIDE { | 144 virtual scoped_ptr<DeviceInfo> GetLocalDeviceInfo() const OVERRIDE { |
115 return scoped_ptr<DeviceInfo>( | 145 return scoped_ptr<DeviceInfo>( |
116 new DeviceInfo(GetLocalSyncCacheGUID(), | 146 new DeviceInfo(GetLocalSyncCacheGUID(), |
117 "Wayne Gretzky's Hacking Box", | 147 "Wayne Gretzky's Hacking Box", |
118 "Chromium 10k", | 148 "Chromium 10k", |
119 "Chrome 10k", | 149 "Chrome 10k", |
120 sync_pb::SyncEnums_DeviceType_TYPE_LINUX)); | 150 sync_pb::SyncEnums_DeviceType_TYPE_LINUX)); |
121 } | 151 } |
122 | 152 |
123 virtual std::string GetLocalSyncCacheGUID() const OVERRIDE { | 153 virtual std::string GetLocalSyncCacheGUID() const OVERRIDE { |
124 return "cache_guid"; | 154 return "cache_guid"; |
125 } | 155 } |
126 | 156 |
127 SessionsSyncManager* manager() { return manager_.get(); } | 157 SessionsSyncManager* manager() { return manager_.get(); } |
128 SessionSyncTestHelper* helper() { return &helper_; } | 158 SessionSyncTestHelper* helper() { return &helper_; } |
129 | 159 |
130 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data, | 160 void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data, |
131 syncer::SyncChangeList* output) { | 161 syncer::SyncChangeList* output) { |
| 162 test_processor_ = new TestSyncProcessorStub(output); |
132 syncer::SyncMergeResult result = manager_->MergeDataAndStartSyncing( | 163 syncer::SyncMergeResult result = manager_->MergeDataAndStartSyncing( |
133 syncer::SESSIONS, initial_data, | 164 syncer::SESSIONS, initial_data, |
134 scoped_ptr<syncer::SyncChangeProcessor>( | 165 scoped_ptr<syncer::SyncChangeProcessor>(test_processor_), |
135 new TestSyncProcessorStub(output)), | |
136 scoped_ptr<syncer::SyncErrorFactory>( | 166 scoped_ptr<syncer::SyncErrorFactory>( |
137 new syncer::SyncErrorFactoryMock())); | 167 new syncer::SyncErrorFactoryMock())); |
138 EXPECT_FALSE(result.error().IsSet()); | 168 EXPECT_FALSE(result.error().IsSet()); |
139 } | 169 } |
140 | 170 |
141 void InitWithNoSyncData() { | 171 void InitWithNoSyncData() { |
142 InitWithSyncDataTakeOutput(syncer::SyncDataList(), NULL); | 172 InitWithSyncDataTakeOutput(syncer::SyncDataList(), NULL); |
143 } | 173 } |
144 | 174 |
| 175 void TriggerProcessSyncChangesError() { |
| 176 test_processor_->FailProcessSyncChangesWith(syncer::SyncError( |
| 177 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, "Error", |
| 178 syncer::SESSIONS)); |
| 179 } |
| 180 |
145 syncer::SyncChangeList* FilterOutLocalHeaderChanges( | 181 syncer::SyncChangeList* FilterOutLocalHeaderChanges( |
146 syncer::SyncChangeList* list) { | 182 syncer::SyncChangeList* list) { |
147 syncer::SyncChangeList::iterator it = list->begin(); | 183 syncer::SyncChangeList::iterator it = list->begin(); |
148 bool found = false; | 184 bool found = false; |
149 while (it != list->end()) { | 185 while (it != list->end()) { |
150 if (it->sync_data().GetTag() == manager_->current_machine_tag()) { | 186 if (it->sync_data().GetTag() == manager_->current_machine_tag()) { |
151 EXPECT_TRUE(SyncChange::ACTION_ADD == it->change_type() || | 187 EXPECT_TRUE(SyncChange::ACTION_ADD == it->change_type() || |
152 SyncChange::ACTION_UPDATE == it->change_type()); | 188 SyncChange::ACTION_UPDATE == it->change_type()); |
153 it = list->erase(it); | 189 it = list->erase(it); |
154 found = true; | 190 found = true; |
155 } else { | 191 } else { |
156 ++it; | 192 ++it; |
157 } | 193 } |
158 } | 194 } |
159 EXPECT_TRUE(found); | 195 EXPECT_TRUE(found); |
160 return list; | 196 return list; |
161 } | 197 } |
162 | 198 |
163 private: | 199 private: |
164 scoped_ptr<SessionsSyncManager> manager_; | 200 scoped_ptr<SessionsSyncManager> manager_; |
165 SessionSyncTestHelper helper_; | 201 SessionSyncTestHelper helper_; |
| 202 TestSyncProcessorStub* test_processor_; |
166 }; | 203 }; |
167 | 204 |
168 TEST_F(SessionsSyncManagerTest, PopulateSessionHeader) { | 205 TEST_F(SessionsSyncManagerTest, PopulateSessionHeader) { |
169 sync_pb::SessionHeader header_s; | 206 sync_pb::SessionHeader header_s; |
170 header_s.set_client_name("Client 1"); | 207 header_s.set_client_name("Client 1"); |
171 header_s.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_WIN); | 208 header_s.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_WIN); |
172 | 209 |
173 SyncedSession session; | 210 SyncedSession session; |
174 base::Time time = base::Time::Now(); | 211 base::Time time = base::Time::Now(); |
175 SessionsSyncManager::PopulateSessionHeaderFromSpecifics( | 212 SessionsSyncManager::PopulateSessionHeaderFromSpecifics( |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 const sync_pb::SessionSpecifics& specifics2(data_2.GetSpecifics().session()); | 549 const sync_pb::SessionSpecifics& specifics2(data_2.GetSpecifics().session()); |
513 EXPECT_EQ(manager()->current_machine_tag(), specifics2.session_tag()); | 550 EXPECT_EQ(manager()->current_machine_tag(), specifics2.session_tag()); |
514 EXPECT_TRUE(specifics2.has_header()); | 551 EXPECT_TRUE(specifics2.has_header()); |
515 const sync_pb::SessionHeader& header_s2 = specifics2.header(); | 552 const sync_pb::SessionHeader& header_s2 = specifics2.header(); |
516 EXPECT_EQ(0, header_s2.window_size()); | 553 EXPECT_EQ(0, header_s2.window_size()); |
517 | 554 |
518 // Now take that header node and feed it in as input. | 555 // Now take that header node and feed it in as input. |
519 SyncData d(SyncData::CreateRemoteData(1, data.GetSpecifics(), base::Time())); | 556 SyncData d(SyncData::CreateRemoteData(1, data.GetSpecifics(), base::Time())); |
520 syncer::SyncDataList in(&d, &d + 1); | 557 syncer::SyncDataList in(&d, &d + 1); |
521 out.clear(); | 558 out.clear(); |
522 SessionsSyncManager manager2(profile(), this); | 559 SessionsSyncManager manager2(profile(), this, NewDummyRouter()); |
523 syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( | 560 syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( |
524 syncer::SESSIONS, in, | 561 syncer::SESSIONS, in, |
525 scoped_ptr<syncer::SyncChangeProcessor>( | 562 scoped_ptr<syncer::SyncChangeProcessor>( |
526 new TestSyncProcessorStub(&out)), | 563 new TestSyncProcessorStub(&out)), |
527 scoped_ptr<syncer::SyncErrorFactory>( | 564 scoped_ptr<syncer::SyncErrorFactory>( |
528 new syncer::SyncErrorFactoryMock())); | 565 new syncer::SyncErrorFactoryMock())); |
529 ASSERT_FALSE(result.error().IsSet()); | 566 ASSERT_FALSE(result.error().IsSet()); |
530 | 567 |
531 EXPECT_EQ(1U, out.size()); | 568 EXPECT_EQ(1U, out.size()); |
532 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[0].change_type()); | 569 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[0].change_type()); |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 manager()->local_tab_pool_.GetFreeTabNode(&changes); | 942 manager()->local_tab_pool_.GetFreeTabNode(&changes); |
906 | 943 |
907 // Update the tab_id of the node, so that it is considered a valid | 944 // Update the tab_id of the node, so that it is considered a valid |
908 // unassociated node otherwise it will be mistaken for a corrupted node and | 945 // unassociated node otherwise it will be mistaken for a corrupted node and |
909 // will be deleted before being added to the tab node pool. | 946 // will be deleted before being added to the tab node pool. |
910 sync_pb::EntitySpecifics entity(changes[0].sync_data().GetSpecifics()); | 947 sync_pb::EntitySpecifics entity(changes[0].sync_data().GetSpecifics()); |
911 entity.mutable_session()->mutable_tab()->set_tab_id(1); | 948 entity.mutable_session()->mutable_tab()->set_tab_id(1); |
912 SyncData d(SyncData::CreateRemoteData(1, entity, base::Time())); | 949 SyncData d(SyncData::CreateRemoteData(1, entity, base::Time())); |
913 syncer::SyncDataList in(&d, &d + 1); | 950 syncer::SyncDataList in(&d, &d + 1); |
914 changes.clear(); | 951 changes.clear(); |
915 SessionsSyncManager manager2(profile(), this); | 952 SessionsSyncManager manager2(profile(), this, NewDummyRouter()); |
916 syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( | 953 syncer::SyncMergeResult result = manager2.MergeDataAndStartSyncing( |
917 syncer::SESSIONS, in, | 954 syncer::SESSIONS, in, |
918 scoped_ptr<syncer::SyncChangeProcessor>( | 955 scoped_ptr<syncer::SyncChangeProcessor>( |
919 new TestSyncProcessorStub(&changes)), | 956 new TestSyncProcessorStub(&changes)), |
920 scoped_ptr<syncer::SyncErrorFactory>( | 957 scoped_ptr<syncer::SyncErrorFactory>( |
921 new syncer::SyncErrorFactoryMock())); | 958 new syncer::SyncErrorFactoryMock())); |
922 ASSERT_FALSE(result.error().IsSet()); | 959 ASSERT_FALSE(result.error().IsSet()); |
923 EXPECT_TRUE(FilterOutLocalHeaderChanges(&changes)->empty()); | 960 EXPECT_TRUE(FilterOutLocalHeaderChanges(&changes)->empty()); |
924 } | 961 } |
925 | 962 |
926 TEST_F(SessionsSyncManagerTest, MergeDeletesCorruptNode) { | 963 TEST_F(SessionsSyncManagerTest, MergeDeletesCorruptNode) { |
927 syncer::SyncChangeList changes; | 964 syncer::SyncChangeList changes; |
928 InitWithNoSyncData(); | 965 InitWithNoSyncData(); |
929 | 966 |
930 std::string local_tag = manager()->current_machine_tag(); | 967 std::string local_tag = manager()->current_machine_tag(); |
931 int tab_node_id = manager()->local_tab_pool_.GetFreeTabNode(&changes); | 968 int tab_node_id = manager()->local_tab_pool_.GetFreeTabNode(&changes); |
932 SyncData d(SyncData::CreateRemoteData( | 969 SyncData d(SyncData::CreateRemoteData( |
933 1, changes[0].sync_data().GetSpecifics(), base::Time())); | 970 1, changes[0].sync_data().GetSpecifics(), base::Time())); |
934 syncer::SyncDataList in(&d, &d + 1); | 971 syncer::SyncDataList in(&d, &d + 1); |
935 changes.clear(); | 972 changes.clear(); |
936 TearDown(); | 973 TearDown(); |
937 SetUp(); | 974 SetUp(); |
938 InitWithSyncDataTakeOutput(in, &changes); | 975 InitWithSyncDataTakeOutput(in, &changes); |
939 EXPECT_EQ(1U, FilterOutLocalHeaderChanges(&changes)->size()); | 976 EXPECT_EQ(1U, FilterOutLocalHeaderChanges(&changes)->size()); |
940 EXPECT_EQ(SyncChange::ACTION_DELETE, changes[0].change_type()); | 977 EXPECT_EQ(SyncChange::ACTION_DELETE, changes[0].change_type()); |
941 EXPECT_EQ(TabNodePool2::TabIdToTag(local_tag, tab_node_id), | 978 EXPECT_EQ(TabNodePool2::TabIdToTag(local_tag, tab_node_id), |
942 changes[0].sync_data().GetTag()); | 979 changes[0].sync_data().GetTag()); |
943 } | 980 } |
944 | 981 |
| 982 // Test that things work if a tab is initially ignored. |
945 TEST_F(SessionsSyncManagerTest, AssociateWindowsDontReloadTabs) { | 983 TEST_F(SessionsSyncManagerTest, AssociateWindowsDontReloadTabs) { |
946 syncer::SyncChangeList out; | 984 syncer::SyncChangeList out; |
947 // Go to a URL that is ignored by session syncing. | 985 // Go to a URL that is ignored by session syncing. |
948 AddTab(browser(), GURL("chrome://preferences/")); | 986 AddTab(browser(), GURL("chrome://preferences/")); |
949 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); | 987 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); |
950 ASSERT_EQ(2U, out.size()); | 988 ASSERT_EQ(2U, out.size()); // Header add and update. |
951 EXPECT_EQ( | 989 EXPECT_EQ( |
952 0, | 990 0, |
953 out[1].sync_data().GetSpecifics().session().header().window_size()); | 991 out[1].sync_data().GetSpecifics().session().header().window_size()); |
954 out.clear(); | 992 out.clear(); |
955 | 993 |
956 // Go to a sync-interesting URL. | 994 // Go to a sync-interesting URL. |
957 NavigateAndCommitActiveTab(GURL("http://foo2")); | 995 NavigateAndCommitActiveTab(GURL("http://foo2")); |
958 | 996 |
959 // Simulate a selective association (e.g in response to tab event) as | 997 EXPECT_EQ(3U, out.size()); // Tab add, update, and header update. |
960 // would occur in practice from ProcessSyncChanges. | |
961 content::WebContents* c = | |
962 browser()->tab_strip_model()->GetActiveWebContents(); | |
963 manager()->AssociateTab(SyncedTabDelegate::ImplFromWebContents(c), &out); | |
964 ASSERT_EQ(2U, out.size()); | |
965 | 998 |
966 EXPECT_TRUE(StartsWithASCII(out[0].sync_data().GetTag(), | 999 EXPECT_TRUE(StartsWithASCII(out[0].sync_data().GetTag(), |
967 manager()->current_machine_tag(), true)); | 1000 manager()->current_machine_tag(), true)); |
968 EXPECT_EQ(manager()->current_machine_tag(), | 1001 EXPECT_EQ(manager()->current_machine_tag(), |
969 out[0].sync_data().GetSpecifics().session().session_tag()); | 1002 out[0].sync_data().GetSpecifics().session().session_tag()); |
970 EXPECT_EQ(SyncChange::ACTION_ADD, out[0].change_type()); | 1003 EXPECT_EQ(SyncChange::ACTION_ADD, out[0].change_type()); |
971 | 1004 |
972 EXPECT_TRUE(StartsWithASCII(out[1].sync_data().GetTag(), | 1005 EXPECT_TRUE(StartsWithASCII(out[1].sync_data().GetTag(), |
973 manager()->current_machine_tag(), true)); | 1006 manager()->current_machine_tag(), true)); |
974 EXPECT_EQ(manager()->current_machine_tag(), | 1007 EXPECT_EQ(manager()->current_machine_tag(), |
975 out[1].sync_data().GetSpecifics().session().session_tag()); | 1008 out[1].sync_data().GetSpecifics().session().session_tag()); |
976 EXPECT_TRUE(out[1].sync_data().GetSpecifics().session().has_tab()); | 1009 EXPECT_TRUE(out[1].sync_data().GetSpecifics().session().has_tab()); |
977 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[1].change_type()); | 1010 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[1].change_type()); |
978 | 1011 |
979 out.clear(); | 1012 EXPECT_TRUE(out[2].IsValid()); |
980 manager()->AssociateWindows(SessionsSyncManager::DONT_RELOAD_TABS, | 1013 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[2].change_type()); |
981 &out); | 1014 const SyncData data(out[2].sync_data()); |
982 | |
983 EXPECT_EQ(1U, out.size()); | |
984 EXPECT_TRUE(out[0].IsValid()); | |
985 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[0].change_type()); | |
986 const SyncData data(out[0].sync_data()); | |
987 EXPECT_EQ(manager()->current_machine_tag(), data.GetTag()); | 1015 EXPECT_EQ(manager()->current_machine_tag(), data.GetTag()); |
988 const sync_pb::SessionSpecifics& specifics(data.GetSpecifics().session()); | 1016 const sync_pb::SessionSpecifics& specifics(data.GetSpecifics().session()); |
989 EXPECT_EQ(manager()->current_machine_tag(), specifics.session_tag()); | 1017 EXPECT_EQ(manager()->current_machine_tag(), specifics.session_tag()); |
990 EXPECT_TRUE(specifics.has_header()); | 1018 EXPECT_TRUE(specifics.has_header()); |
991 const sync_pb::SessionHeader& header_s = specifics.header(); | 1019 const sync_pb::SessionHeader& header_s = specifics.header(); |
992 EXPECT_EQ(1, header_s.window_size()); | 1020 EXPECT_EQ(1, header_s.window_size()); |
993 EXPECT_EQ(1, header_s.window(0).tab_size()); | 1021 EXPECT_EQ(1, header_s.window(0).tab_size()); |
994 } | 1022 } |
995 | 1023 |
| 1024 TEST_F(SessionsSyncManagerTest, OnLocalTabModified) { |
| 1025 syncer::SyncChangeList out; |
| 1026 // Init with no local data, relies on MergeLocalSessionNoTabs. |
| 1027 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); |
| 1028 ASSERT_FALSE(manager()->current_machine_tag().empty()); |
| 1029 ASSERT_EQ(2U, out.size()); |
| 1030 |
| 1031 // Copy the original header. |
| 1032 sync_pb::EntitySpecifics header(out[0].sync_data().GetSpecifics()); |
| 1033 out.clear(); |
| 1034 |
| 1035 const GURL foo1("http://foo/1"); |
| 1036 const GURL foo2("http://foo/2"); |
| 1037 const GURL bar1("http://bar/1"); |
| 1038 const GURL bar2("http://bar/2"); |
| 1039 AddTab(browser(), foo1); |
| 1040 NavigateAndCommitActiveTab(foo2); |
| 1041 AddTab(browser(), bar1); |
| 1042 NavigateAndCommitActiveTab(bar2); |
| 1043 |
| 1044 // One add, one update for each AddTab. |
| 1045 // One update for each NavigateAndCommit. |
| 1046 // = 6 total tab updates. |
| 1047 // One header update corresponding to each of those. |
| 1048 // = 6 total header updates. |
| 1049 // 12 total updates. |
| 1050 ASSERT_EQ(12U, out.size()); |
| 1051 |
| 1052 // Verify the tab node creations and updates to ensure the SyncProcessor |
| 1053 // sees the right operations. |
| 1054 for (int i = 0; i < 12; i++) { |
| 1055 SCOPED_TRACE(i); |
| 1056 EXPECT_TRUE(out[i].IsValid()); |
| 1057 const SyncData data(out[i].sync_data()); |
| 1058 EXPECT_TRUE(StartsWithASCII(data.GetTag(), |
| 1059 manager()->current_machine_tag(), true)); |
| 1060 const sync_pb::SessionSpecifics& specifics(data.GetSpecifics().session()); |
| 1061 EXPECT_EQ(manager()->current_machine_tag(), specifics.session_tag()); |
| 1062 if (i % 6 == 0) { |
| 1063 // First thing on an AddTab is a no-op header update for parented tab. |
| 1064 EXPECT_EQ(header.SerializeAsString(), |
| 1065 data.GetSpecifics().SerializeAsString()); |
| 1066 } else if (i % 6 == 1) { |
| 1067 // Next, the TabNodePool should create the tab node. |
| 1068 EXPECT_EQ(SyncChange::ACTION_ADD, out[i].change_type()); |
| 1069 } else if (i % 6 == 2) { |
| 1070 // Then we see the tab update to the URL. |
| 1071 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[i].change_type()); |
| 1072 ASSERT_TRUE(specifics.has_tab()); |
| 1073 } else if (i % 6 == 3) { |
| 1074 // The header needs to be updated to reflect the new window state. |
| 1075 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[i].change_type()); |
| 1076 EXPECT_TRUE(specifics.has_header()); |
| 1077 } else if (i % 6 == 4) { |
| 1078 // Now we move on to NavigateAndCommit. Update the tab. |
| 1079 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[i].change_type()); |
| 1080 ASSERT_TRUE(specifics.has_tab()); |
| 1081 } else if (i % 6 == 5) { |
| 1082 // The header needs to be updated to reflect the new window state. |
| 1083 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[i].change_type()); |
| 1084 ASSERT_TRUE(specifics.has_header()); |
| 1085 header = data.GetSpecifics(); |
| 1086 } |
| 1087 } |
| 1088 |
| 1089 // Verify the actual content to ensure sync sees the right data. |
| 1090 // When it's all said and done, the header should reflect two tabs. |
| 1091 const sync_pb::SessionHeader& session_header = header.session().header(); |
| 1092 ASSERT_EQ(1, session_header.window_size()); |
| 1093 EXPECT_EQ(2, session_header.window(0).tab_size()); |
| 1094 |
| 1095 // ASSERT_TRUEs above allow us to dive in freely here. |
| 1096 // Verify first tab. |
| 1097 const sync_pb::SessionTab& tab1_1 = |
| 1098 out[2].sync_data().GetSpecifics().session().tab(); |
| 1099 ASSERT_EQ(1, tab1_1.navigation_size()); |
| 1100 EXPECT_EQ(foo1.spec(), tab1_1.navigation(0).virtual_url()); |
| 1101 const sync_pb::SessionTab& tab1_2 = |
| 1102 out[4].sync_data().GetSpecifics().session().tab(); |
| 1103 ASSERT_EQ(2, tab1_2.navigation_size()); |
| 1104 EXPECT_EQ(foo1.spec(), tab1_2.navigation(0).virtual_url()); |
| 1105 EXPECT_EQ(foo2.spec(), tab1_2.navigation(1).virtual_url()); |
| 1106 |
| 1107 // Verify second tab. |
| 1108 const sync_pb::SessionTab& tab2_1 = |
| 1109 out[8].sync_data().GetSpecifics().session().tab(); |
| 1110 ASSERT_EQ(1, tab2_1.navigation_size()); |
| 1111 EXPECT_EQ(bar1.spec(), tab2_1.navigation(0).virtual_url()); |
| 1112 const sync_pb::SessionTab& tab2_2 = |
| 1113 out[10].sync_data().GetSpecifics().session().tab(); |
| 1114 ASSERT_EQ(2, tab2_2.navigation_size()); |
| 1115 EXPECT_EQ(bar1.spec(), tab2_2.navigation(0).virtual_url()); |
| 1116 EXPECT_EQ(bar2.spec(), tab2_2.navigation(1).virtual_url()); |
| 1117 } |
| 1118 |
996 // Ensure model association associates the pre-existing tabs. | 1119 // Ensure model association associates the pre-existing tabs. |
997 TEST_F(SessionsSyncManagerTest, MergeLocalSessionExistingTabs) { | 1120 TEST_F(SessionsSyncManagerTest, MergeLocalSessionExistingTabs) { |
998 AddTab(browser(), GURL("http://foo1")); | 1121 AddTab(browser(), GURL("http://foo1")); |
999 NavigateAndCommitActiveTab(GURL("http://foo2")); | 1122 NavigateAndCommitActiveTab(GURL("http://foo2")); // Adds back entry. |
1000 AddTab(browser(), GURL("http://bar1")); | 1123 AddTab(browser(), GURL("http://bar1")); |
1001 NavigateAndCommitActiveTab(GURL("http://bar2")); | 1124 NavigateAndCommitActiveTab(GURL("http://bar2")); // Adds back entry. |
1002 | 1125 |
1003 syncer::SyncChangeList out; | 1126 syncer::SyncChangeList out; |
1004 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); | 1127 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); |
1005 ASSERT_EQ(6U, out.size()); | 1128 ASSERT_EQ(6U, out.size()); |
1006 | 1129 |
1007 // Check that this machine's data is not included in the foreign windows. | 1130 // Check that this machine's data is not included in the foreign windows. |
1008 std::vector<const SyncedSession*> foreign_sessions; | 1131 std::vector<const SyncedSession*> foreign_sessions; |
1009 ASSERT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions)); | 1132 ASSERT_FALSE(manager()->GetAllForeignSessions(&foreign_sessions)); |
1010 | 1133 |
1011 // Verify the header. | 1134 // Verify the header. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 TEST_F(SessionsSyncManagerTest, CheckPrerenderedWebContentsSwap) { | 1193 TEST_F(SessionsSyncManagerTest, CheckPrerenderedWebContentsSwap) { |
1071 AddTab(browser(), GURL("http://foo1")); | 1194 AddTab(browser(), GURL("http://foo1")); |
1072 NavigateAndCommitActiveTab(GURL("http://foo2")); | 1195 NavigateAndCommitActiveTab(GURL("http://foo2")); |
1073 | 1196 |
1074 syncer::SyncChangeList out; | 1197 syncer::SyncChangeList out; |
1075 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); | 1198 InitWithSyncDataTakeOutput(syncer::SyncDataList(), &out); |
1076 ASSERT_EQ(4U, out.size()); // Header, tab ADD, tab UPDATE, header UPDATE. | 1199 ASSERT_EQ(4U, out.size()); // Header, tab ADD, tab UPDATE, header UPDATE. |
1077 | 1200 |
1078 // To simulate WebContents swap during prerendering, create new WebContents | 1201 // To simulate WebContents swap during prerendering, create new WebContents |
1079 // and swap with old WebContents. | 1202 // and swap with old WebContents. |
1080 content::WebContents* old_web_contents = | 1203 scoped_ptr<content::WebContents> old_web_contents; |
1081 browser()->tab_strip_model()->GetActiveWebContents(); | 1204 old_web_contents.reset(browser()->tab_strip_model()->GetActiveWebContents()); |
1082 | 1205 |
1083 // Create new WebContents, with the required tab helpers. | 1206 // Create new WebContents, with the required tab helpers. |
1084 WebContents* new_web_contents = WebContents::CreateWithSessionStorage( | 1207 WebContents* new_web_contents = WebContents::CreateWithSessionStorage( |
1085 WebContents::CreateParams(profile()), | 1208 WebContents::CreateParams(profile()), |
1086 old_web_contents->GetController().GetSessionStorageNamespaceMap()); | 1209 old_web_contents->GetController().GetSessionStorageNamespaceMap()); |
1087 SessionTabHelper::CreateForWebContents(new_web_contents); | 1210 SessionTabHelper::CreateForWebContents(new_web_contents); |
1088 TabContentsSyncedTabDelegate::CreateForWebContents(new_web_contents); | 1211 TabContentsSyncedTabDelegate::CreateForWebContents(new_web_contents); |
1089 new_web_contents->GetController() | 1212 new_web_contents->GetController() |
1090 .CopyStateFrom(old_web_contents->GetController()); | 1213 .CopyStateFrom(old_web_contents->GetController()); |
1091 | 1214 |
1092 // Swap the WebContents. | 1215 // Swap the WebContents. |
1093 int index = | 1216 int index = browser()->tab_strip_model()->GetIndexOfWebContents( |
1094 browser()->tab_strip_model()->GetIndexOfWebContents(old_web_contents); | 1217 old_web_contents.get()); |
1095 browser()->tab_strip_model()->ReplaceWebContentsAt(index, new_web_contents); | 1218 browser()->tab_strip_model()->ReplaceWebContentsAt(index, new_web_contents); |
1096 | 1219 |
1097 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | 1220 ASSERT_EQ(9U, out.size()); |
1098 ASSERT_EQ(7U, out.size()); | |
1099 EXPECT_EQ(SyncChange::ACTION_ADD, out[4].change_type()); | 1221 EXPECT_EQ(SyncChange::ACTION_ADD, out[4].change_type()); |
1100 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[5].change_type()); | 1222 EXPECT_EQ(SyncChange::ACTION_UPDATE, out[5].change_type()); |
1101 | 1223 |
1102 // Navigate away. | 1224 // Navigate away. |
1103 NavigateAndCommitActiveTab(GURL("http://bar2")); | 1225 NavigateAndCommitActiveTab(GURL("http://bar2")); |
1104 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | |
1105 | 1226 |
1106 // Delete old WebContents. This should not crash. | 1227 // Delete old WebContents. This should not crash. |
1107 delete old_web_contents; | 1228 old_web_contents.reset(); |
1108 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | |
1109 | 1229 |
1110 // Try more navigations and verify output size. This can also reveal | 1230 // Try more navigations and verify output size. This can also reveal |
1111 // bugs (leaks) on memcheck bots if the SessionSyncManager | 1231 // bugs (leaks) on memcheck bots if the SessionSyncManager |
1112 // didn't properly clean up the tab pool or session tracker. | 1232 // didn't properly clean up the tab pool or session tracker. |
1113 NavigateAndCommitActiveTab(GURL("http://bar3")); | 1233 NavigateAndCommitActiveTab(GURL("http://bar3")); |
1114 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | |
1115 | 1234 |
1116 AddTab(browser(), GURL("http://bar4")); | 1235 AddTab(browser(), GURL("http://bar4")); |
1117 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | |
1118 NavigateAndCommitActiveTab(GURL("http://bar5")); | 1236 NavigateAndCommitActiveTab(GURL("http://bar5")); |
1119 manager()->AssociateWindows(SessionsSyncManager::RELOAD_TABS, &out); | 1237 ASSERT_EQ(19U, out.size()); |
1120 ASSERT_EQ(20U, out.size()); | |
1121 } | 1238 } |
1122 | 1239 |
1123 namespace { | 1240 namespace { |
1124 class SessionNotificationObserver : public content::NotificationObserver { | 1241 class SessionNotificationObserver : public content::NotificationObserver { |
1125 public: | 1242 public: |
1126 SessionNotificationObserver() : notified_of_update_(false) { | 1243 SessionNotificationObserver() : notified_of_update_(false), |
| 1244 notified_of_refresh_(false) { |
1127 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, | 1245 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED, |
1128 content::NotificationService::AllSources()); | 1246 content::NotificationService::AllSources()); |
| 1247 registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL, |
| 1248 content::NotificationService::AllSources()); |
1129 } | 1249 } |
1130 virtual void Observe(int type, | 1250 virtual void Observe(int type, |
1131 const content::NotificationSource& source, | 1251 const content::NotificationSource& source, |
1132 const content::NotificationDetails& details) OVERRIDE { | 1252 const content::NotificationDetails& details) OVERRIDE { |
1133 switch (type) { | 1253 switch (type) { |
1134 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: | 1254 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED: |
1135 notified_of_update_ = true; | 1255 notified_of_update_ = true; |
1136 break; | 1256 break; |
| 1257 case chrome::NOTIFICATION_SYNC_REFRESH_LOCAL: |
| 1258 notified_of_refresh_ = true; |
| 1259 break; |
1137 default: | 1260 default: |
1138 NOTREACHED(); | 1261 NOTREACHED(); |
1139 break; | 1262 break; |
1140 } | 1263 } |
1141 } | 1264 } |
1142 bool notified_of_update() const { return notified_of_update_; } | 1265 bool notified_of_update() const { return notified_of_update_; } |
1143 void Reset() { notified_of_update_ = false; } | 1266 bool notified_of_refresh() const { return notified_of_refresh_; } |
| 1267 void Reset() { |
| 1268 notified_of_update_ = false; |
| 1269 notified_of_refresh_ = false; |
| 1270 } |
1144 private: | 1271 private: |
1145 content::NotificationRegistrar registrar_; | 1272 content::NotificationRegistrar registrar_; |
1146 bool notified_of_update_; | 1273 bool notified_of_update_; |
| 1274 bool notified_of_refresh_; |
1147 }; | 1275 }; |
1148 } // namespace | 1276 } // namespace |
1149 | 1277 |
1150 TEST_F(SessionsSyncManagerTest, NotifiedOfUpdates) { | 1278 TEST_F(SessionsSyncManagerTest, NotifiedOfUpdates) { |
1151 SessionNotificationObserver observer; | 1279 SessionNotificationObserver observer; |
| 1280 ASSERT_FALSE(observer.notified_of_update()); |
1152 InitWithNoSyncData(); | 1281 InitWithNoSyncData(); |
1153 | 1282 |
1154 SessionID::id_type n[] = {5}; | 1283 SessionID::id_type n[] = {5}; |
1155 std::vector<sync_pb::SessionSpecifics> tabs1; | 1284 std::vector<sync_pb::SessionSpecifics> tabs1; |
1156 std::vector<SessionID::id_type> tab_list(n, n + arraysize(n)); | 1285 std::vector<SessionID::id_type> tab_list(n, n + arraysize(n)); |
1157 sync_pb::SessionSpecifics meta(helper()->BuildForeignSession( | 1286 sync_pb::SessionSpecifics meta(helper()->BuildForeignSession( |
1158 "tag1", tab_list, &tabs1)); | 1287 "tag1", tab_list, &tabs1)); |
1159 | 1288 |
1160 syncer::SyncChangeList changes; | 1289 syncer::SyncChangeList changes; |
1161 changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_ADD)); | 1290 changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_ADD)); |
1162 manager()->ProcessSyncChanges(FROM_HERE, changes); | 1291 manager()->ProcessSyncChanges(FROM_HERE, changes); |
1163 EXPECT_TRUE(observer.notified_of_update()); | 1292 EXPECT_TRUE(observer.notified_of_update()); |
1164 | 1293 |
1165 changes.clear(); | 1294 changes.clear(); |
1166 observer.Reset(); | 1295 observer.Reset(); |
1167 AddTabsToChangeList(tabs1, SyncChange::ACTION_ADD, &changes); | 1296 AddTabsToChangeList(tabs1, SyncChange::ACTION_ADD, &changes); |
1168 manager()->ProcessSyncChanges(FROM_HERE, changes); | 1297 manager()->ProcessSyncChanges(FROM_HERE, changes); |
1169 EXPECT_TRUE(observer.notified_of_update()); | 1298 EXPECT_TRUE(observer.notified_of_update()); |
1170 | 1299 |
1171 changes.clear(); | 1300 changes.clear(); |
1172 observer.Reset(); | 1301 observer.Reset(); |
1173 changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_DELETE)); | 1302 changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_DELETE)); |
1174 manager()->ProcessSyncChanges(FROM_HERE, changes); | 1303 manager()->ProcessSyncChanges(FROM_HERE, changes); |
1175 EXPECT_TRUE(observer.notified_of_update()); | 1304 EXPECT_TRUE(observer.notified_of_update()); |
1176 } | 1305 } |
1177 | 1306 |
| 1307 #if defined(OS_ANDROID) || defined(OS_IOS) |
| 1308 // Tests that opening the other devices page triggers a session sync refresh. |
| 1309 // This page only exists on mobile platforms today; desktop has a |
| 1310 // search-enhanced NTP without other devices. |
| 1311 TEST_F(SessionsSyncManagerTest, NotifiedOfRefresh) { |
| 1312 SessionNotificationObserver observer; |
| 1313 ASSERT_FALSE(observer.notified_of_refresh()); |
| 1314 InitWithNoSyncData(); |
| 1315 AddTab(browser(), GURL("http://foo1")); |
| 1316 EXPECT_FALSE(observer.notified_of_refresh()); |
| 1317 NavigateAndCommitActiveTab(GURL("chrome://newtab/#open_tabs")); |
| 1318 EXPECT_TRUE(observer.notified_of_refresh()); |
| 1319 } |
| 1320 #endif // defined(OS_ANDROID) || defined(OS_IOS) |
| 1321 |
1178 } // namespace browser_sync | 1322 } // namespace browser_sync |
OLD | NEW |