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