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 <string> | 5 #include <string> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "chrome/browser/sessions/session_types.h" | 10 #include "chrome/browser/sessions/session_types.h" |
11 #include "chrome/browser/sync/glue/session_model_associator.h" | 11 #include "chrome/browser/sync/glue/session_model_associator.h" |
12 #include "chrome/browser/sync/glue/synced_tab_delegate.h" | 12 #include "chrome/browser/sync/glue/synced_tab_delegate.h" |
13 #include "chrome/browser/sync/profile_sync_service_mock.h" | 13 #include "chrome/browser/sync/profile_sync_service_mock.h" |
14 #include "chrome/common/chrome_notification_types.h" | 14 #include "chrome/common/chrome_notification_types.h" |
15 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
16 #include "chrome/test/base/profile_mock.h" | 16 #include "chrome/test/base/profile_mock.h" |
17 #include "content/public/browser/navigation_entry.h" | 17 #include "content/public/browser/navigation_entry.h" |
18 #include "content/public/browser/navigation_entry.h" | |
19 #include "content/public/browser/notification_details.h" | 18 #include "content/public/browser/notification_details.h" |
20 #include "content/public/browser/notification_service.h" | 19 #include "content/public/browser/notification_service.h" |
21 #include "content/public/common/page_transition_types.h" | 20 #include "content/public/common/page_transition_types.h" |
22 #include "content/test/test_browser_thread.h" | 21 #include "content/test/test_browser_thread.h" |
23 #include "sync/protocol/session_specifics.pb.h" | 22 #include "sync/protocol/session_specifics.pb.h" |
24 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 #include "sync/util/time.h" |
26 | 26 |
27 using content::BrowserThread; | 27 using content::BrowserThread; |
28 using testing::NiceMock; | 28 using testing::NiceMock; |
29 using testing::Return; | 29 using testing::Return; |
| 30 using testing::_; |
30 | 31 |
31 namespace browser_sync { | 32 namespace browser_sync { |
32 | 33 |
33 class SyncSessionModelAssociatorTest : public testing::Test { | 34 class SyncSessionModelAssociatorTest : public testing::Test { |
34 public: | 35 public: |
35 SyncSessionModelAssociatorTest() | 36 SyncSessionModelAssociatorTest() |
36 : ui_thread_(BrowserThread::UI, &message_loop_), | 37 : ui_thread_(BrowserThread::UI, &message_loop_), |
37 sync_service_(&profile_) {} | 38 sync_service_(&profile_), |
38 virtual void SetUp() OVERRIDE { | 39 model_associator_(&sync_service_, true) {} |
39 model_associator_.reset(new SessionModelAssociator(&sync_service_, true)); | 40 |
| 41 // Helper methods to avoid having to friend individual tests. |
| 42 bool GetFavicon(std::string page_url, std::string* favicon) { |
| 43 return model_associator_.GetSyncedFaviconForPageURL(page_url, favicon); |
40 } | 44 } |
41 virtual void TearDown() OVERRIDE { | 45 |
42 model_associator_.reset(); | 46 void LoadTabFavicon(const sync_pb::SessionTab& tab) { |
| 47 model_associator_.LoadForeignTabFavicon(tab); |
| 48 } |
| 49 |
| 50 size_t NumFavicons() { |
| 51 return model_associator_.NumFaviconsForTesting(); |
| 52 } |
| 53 |
| 54 void DecrementFavicon(std::string url) { |
| 55 model_associator_.DecrementAndCleanFaviconForURL(url); |
| 56 } |
| 57 |
| 58 void AssociateTabContents(const SyncedWindowDelegate& window, |
| 59 const SyncedTabDelegate& new_tab, |
| 60 SyncedSessionTab* prev_tab, |
| 61 sync_pb::SessionTab* sync_tab, |
| 62 GURL* new_url) { |
| 63 model_associator_.AssociateTabContents(window, |
| 64 new_tab, |
| 65 prev_tab, |
| 66 sync_tab, |
| 67 new_url); |
43 } | 68 } |
44 | 69 |
45 protected: | 70 protected: |
46 MessageLoopForUI message_loop_; | 71 MessageLoopForUI message_loop_; |
47 content::TestBrowserThread ui_thread_; | 72 content::TestBrowserThread ui_thread_; |
48 NiceMock<ProfileMock> profile_; | 73 NiceMock<ProfileMock> profile_; |
49 NiceMock<ProfileSyncServiceMock> sync_service_; | 74 NiceMock<ProfileSyncServiceMock> sync_service_; |
50 scoped_ptr<SessionModelAssociator> model_associator_; | 75 SessionModelAssociator model_associator_; |
51 }; | 76 }; |
52 | 77 |
53 TEST_F(SyncSessionModelAssociatorTest, SessionWindowHasNoTabsToSync) { | 78 TEST_F(SyncSessionModelAssociatorTest, SessionWindowHasNoTabsToSync) { |
54 SessionWindow win; | 79 SessionWindow win; |
55 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win)); | 80 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win)); |
56 scoped_ptr<SessionTab> tab(new SessionTab()); | 81 scoped_ptr<SessionTab> tab(new SessionTab()); |
57 win.tabs.push_back(tab.release()); | 82 win.tabs.push_back(tab.release()); |
58 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win)); | 83 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win)); |
59 TabNavigation nav(0, GURL("about:bubba"), | 84 TabNavigation nav(0, GURL("about:bubba"), |
60 content::Referrer(GURL("about:referrer"), | 85 content::Referrer(GURL("about:referrer"), |
61 WebKit::WebReferrerPolicyDefault), | 86 WebKit::WebReferrerPolicyDefault), |
62 string16(ASCIIToUTF16("title")), | 87 string16(ASCIIToUTF16("title")), |
63 std::string("state"), content::PageTransitionFromInt(0)); | 88 std::string("state"), content::PageTransitionFromInt(0)); |
64 win.tabs[0]->navigations.push_back(nav); | 89 win.tabs[0]->navigations.push_back(nav); |
65 ASSERT_FALSE(SessionWindowHasNoTabsToSync(win)); | 90 ASSERT_FALSE(SessionWindowHasNoTabsToSync(win)); |
66 } | 91 } |
67 | 92 |
68 TEST_F(SyncSessionModelAssociatorTest, ShouldSyncSessionTab) { | 93 TEST_F(SyncSessionModelAssociatorTest, ShouldSyncSessionTab) { |
69 SessionTab tab; | 94 SyncedSessionTab tab; |
70 ASSERT_FALSE(ShouldSyncSessionTab(tab)); | 95 ASSERT_FALSE(ShouldSyncSessionTab(tab)); |
71 TabNavigation nav(0, GURL(chrome::kChromeUINewTabURL), | 96 TabNavigation nav(0, GURL(chrome::kChromeUINewTabURL), |
72 content::Referrer(GURL("about:referrer"), | 97 content::Referrer(GURL("about:referrer"), |
73 WebKit::WebReferrerPolicyDefault), | 98 WebKit::WebReferrerPolicyDefault), |
74 string16(ASCIIToUTF16("title")), | 99 string16(ASCIIToUTF16("title")), |
75 std::string("state"), content::PageTransitionFromInt(0)); | 100 std::string("state"), content::PageTransitionFromInt(0)); |
76 tab.navigations.push_back(nav); | 101 tab.navigations.push_back(nav); |
77 // NewTab does not count as valid if it's the only navigation. | 102 // NewTab does not count as valid if it's the only navigation. |
78 ASSERT_FALSE(ShouldSyncSessionTab(tab)); | 103 ASSERT_FALSE(ShouldSyncSessionTab(tab)); |
79 TabNavigation nav2(0, GURL("about:bubba"), | 104 TabNavigation nav2(0, GURL("about:bubba"), |
80 content::Referrer(GURL("about:referrer"), | 105 content::Referrer(GURL("about:referrer"), |
81 WebKit::WebReferrerPolicyDefault), | 106 WebKit::WebReferrerPolicyDefault), |
82 string16(ASCIIToUTF16("title")), | 107 string16(ASCIIToUTF16("title")), |
83 std::string("state"), content::PageTransitionFromInt(0)); | 108 std::string("state"), content::PageTransitionFromInt(0)); |
84 tab.navigations.push_back(nav2); | 109 tab.navigations.push_back(nav2); |
85 // Once there's another navigation, the tab is valid. | 110 // Once there's another navigation, the tab is valid. |
86 ASSERT_TRUE(ShouldSyncSessionTab(tab)); | 111 ASSERT_TRUE(ShouldSyncSessionTab(tab)); |
87 } | 112 } |
88 | 113 |
89 TEST_F(SyncSessionModelAssociatorTest, | 114 TEST_F(SyncSessionModelAssociatorTest, |
90 ShouldSyncSessionTabIgnoresFragmentForNtp) { | 115 ShouldSyncSessionTabIgnoresFragmentForNtp) { |
91 SessionTab tab; | 116 SyncedSessionTab tab; |
92 ASSERT_FALSE(ShouldSyncSessionTab(tab)); | 117 ASSERT_FALSE(ShouldSyncSessionTab(tab)); |
93 TabNavigation nav(0, GURL(std::string(chrome::kChromeUINewTabURL) + | 118 TabNavigation nav(0, GURL(std::string(chrome::kChromeUINewTabURL) + |
94 "#bookmarks"), | 119 "#bookmarks"), |
95 content::Referrer(GURL("about:referrer"), | 120 content::Referrer(GURL("about:referrer"), |
96 WebKit::WebReferrerPolicyDefault), | 121 WebKit::WebReferrerPolicyDefault), |
97 string16(ASCIIToUTF16("title")), | 122 string16(ASCIIToUTF16("title")), |
98 std::string("state"), content::PageTransitionFromInt(0)); | 123 std::string("state"), content::PageTransitionFromInt(0)); |
99 tab.navigations.push_back(nav); | 124 tab.navigations.push_back(nav); |
100 // NewTab does not count as valid if it's the only navigation. | 125 // NewTab does not count as valid if it's the only navigation. |
101 ASSERT_FALSE(ShouldSyncSessionTab(tab)); | 126 ASSERT_FALSE(ShouldSyncSessionTab(tab)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 160 } |
136 | 161 |
137 TEST_F(SyncSessionModelAssociatorTest, PopulateSessionTab) { | 162 TEST_F(SyncSessionModelAssociatorTest, PopulateSessionTab) { |
138 sync_pb::SessionTab tab_s; | 163 sync_pb::SessionTab tab_s; |
139 tab_s.set_tab_id(5); | 164 tab_s.set_tab_id(5); |
140 tab_s.set_tab_visual_index(13); | 165 tab_s.set_tab_visual_index(13); |
141 tab_s.set_current_navigation_index(3); | 166 tab_s.set_current_navigation_index(3); |
142 tab_s.set_pinned(true); | 167 tab_s.set_pinned(true); |
143 tab_s.set_extension_app_id("app_id"); | 168 tab_s.set_extension_app_id("app_id"); |
144 sync_pb::TabNavigation* navigation = tab_s.add_navigation(); | 169 sync_pb::TabNavigation* navigation = tab_s.add_navigation(); |
145 navigation->set_index(12); | |
146 navigation->set_virtual_url("http://foo/1"); | 170 navigation->set_virtual_url("http://foo/1"); |
147 navigation->set_referrer("referrer"); | 171 navigation->set_referrer("referrer"); |
148 navigation->set_title("title"); | 172 navigation->set_title("title"); |
149 navigation->set_page_transition(sync_pb::TabNavigation_PageTransition_TYPED); | 173 navigation->set_page_transition(sync_pb::TabNavigation_PageTransition_TYPED); |
150 | 174 |
151 SessionTab tab; | 175 SyncedSessionTab tab; |
152 tab.tab_id.set_id(5); // Expected to be set by the SyncedSessionTracker. | 176 tab.tab_id.set_id(5); // Expected to be set by the SyncedSessionTracker. |
153 SessionModelAssociator::PopulateSessionTabFromSpecifics( | 177 SessionModelAssociator::PopulateSessionTabFromSpecifics( |
154 tab_s, base::Time(), &tab); | 178 tab_s, base::Time(), &tab); |
155 ASSERT_EQ(5, tab.tab_id.id()); | 179 ASSERT_EQ(5, tab.tab_id.id()); |
156 ASSERT_EQ(13, tab.tab_visual_index); | 180 ASSERT_EQ(13, tab.tab_visual_index); |
157 ASSERT_EQ(3, tab.current_navigation_index); | 181 ASSERT_EQ(3, tab.current_navigation_index); |
158 ASSERT_TRUE(tab.pinned); | 182 ASSERT_TRUE(tab.pinned); |
159 ASSERT_EQ("app_id", tab.extension_app_id); | 183 ASSERT_EQ("app_id", tab.extension_app_id); |
160 ASSERT_EQ(12, tab.navigations[0].index()); | |
161 ASSERT_EQ(GURL("referrer"), tab.navigations[0].referrer().url); | 184 ASSERT_EQ(GURL("referrer"), tab.navigations[0].referrer().url); |
162 ASSERT_EQ(string16(ASCIIToUTF16("title")), tab.navigations[0].title()); | 185 ASSERT_EQ(string16(ASCIIToUTF16("title")), tab.navigations[0].title()); |
163 ASSERT_EQ(content::PAGE_TRANSITION_TYPED, tab.navigations[0].transition()); | 186 ASSERT_EQ(content::PAGE_TRANSITION_TYPED, tab.navigations[0].transition()); |
164 ASSERT_EQ(GURL("http://foo/1"), tab.navigations[0].virtual_url()); | 187 ASSERT_EQ(GURL("http://foo/1"), tab.navigations[0].virtual_url()); |
165 } | 188 } |
166 | 189 |
167 TEST_F(SyncSessionModelAssociatorTest, TabNodePool) { | 190 TEST_F(SyncSessionModelAssociatorTest, TabNodePool) { |
168 SessionModelAssociator::TabNodePool pool(NULL); | 191 SessionModelAssociator::TabNodePool pool(NULL); |
169 pool.set_machine_tag("tag"); | 192 pool.set_machine_tag("tag"); |
170 ASSERT_TRUE(pool.empty()); | 193 ASSERT_TRUE(pool.empty()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 ASSERT_TRUE(pool.full()); | 230 ASSERT_TRUE(pool.full()); |
208 ASSERT_EQ(2U, pool.capacity()); | 231 ASSERT_EQ(2U, pool.capacity()); |
209 pool.clear(); | 232 pool.clear(); |
210 ASSERT_TRUE(pool.empty()); | 233 ASSERT_TRUE(pool.empty()); |
211 ASSERT_TRUE(pool.full()); | 234 ASSERT_TRUE(pool.full()); |
212 ASSERT_EQ(0U, pool.capacity()); | 235 ASSERT_EQ(0U, pool.capacity()); |
213 } | 236 } |
214 | 237 |
215 namespace { | 238 namespace { |
216 | 239 |
| 240 class SyncedWindowDelegateMock : public SyncedWindowDelegate { |
| 241 public: |
| 242 SyncedWindowDelegateMock() {} |
| 243 virtual ~SyncedWindowDelegateMock() {} |
| 244 MOCK_CONST_METHOD0(HasWindow, bool()); |
| 245 MOCK_CONST_METHOD0(GetSessionId, SessionID::id_type()); |
| 246 MOCK_CONST_METHOD0(GetTabCount, int()); |
| 247 MOCK_CONST_METHOD0(GetActiveIndex, int()); |
| 248 MOCK_CONST_METHOD0(IsApp, bool()); |
| 249 MOCK_CONST_METHOD0(IsTypeTabbed, bool()); |
| 250 MOCK_CONST_METHOD0(IsTypePopup, bool()); |
| 251 MOCK_CONST_METHOD1(IsTabPinned, bool(const SyncedTabDelegate* tab)); |
| 252 MOCK_CONST_METHOD1(GetTabAt, SyncedTabDelegate*(int index)); |
| 253 MOCK_CONST_METHOD1(GetTabIdAt, SessionID::id_type(int index)); |
| 254 }; |
| 255 |
217 class SyncedTabDelegateMock : public SyncedTabDelegate { | 256 class SyncedTabDelegateMock : public SyncedTabDelegate { |
218 public: | 257 public: |
219 SyncedTabDelegateMock() {} | 258 SyncedTabDelegateMock() {} |
220 ~SyncedTabDelegateMock() {} | 259 virtual ~SyncedTabDelegateMock() {} |
221 | 260 |
222 MOCK_CONST_METHOD0(GetWindowId, SessionID::id_type()); | 261 MOCK_CONST_METHOD0(GetWindowId, SessionID::id_type()); |
223 MOCK_CONST_METHOD0(GetSessionId, SessionID::id_type()); | 262 MOCK_CONST_METHOD0(GetSessionId, SessionID::id_type()); |
224 MOCK_CONST_METHOD0(IsBeingDestroyed, bool()); | 263 MOCK_CONST_METHOD0(IsBeingDestroyed, bool()); |
225 MOCK_CONST_METHOD0(profile, Profile*()); | 264 MOCK_CONST_METHOD0(profile, Profile*()); |
226 MOCK_CONST_METHOD0(HasExtensionAppId, bool()); | 265 MOCK_CONST_METHOD0(HasExtensionAppId, bool()); |
227 MOCK_CONST_METHOD0(GetExtensionAppId, const std::string&()); | 266 MOCK_CONST_METHOD0(GetExtensionAppId, const std::string&()); |
228 MOCK_CONST_METHOD0(GetCurrentEntryIndex, int()); | 267 MOCK_CONST_METHOD0(GetCurrentEntryIndex, int()); |
229 MOCK_CONST_METHOD0(GetEntryCount, int()); | 268 MOCK_CONST_METHOD0(GetEntryCount, int()); |
230 MOCK_CONST_METHOD0(GetPendingEntryIndex, int()); | 269 MOCK_CONST_METHOD0(GetPendingEntryIndex, int()); |
(...skipping 25 matching lines...) Expand all Loading... |
256 }; | 295 }; |
257 | 296 |
258 } // namespace. | 297 } // namespace. |
259 | 298 |
260 // Test that AttemptSessionsDataRefresh() triggers the NOTIFICATION_SYNC_REFRESH | 299 // Test that AttemptSessionsDataRefresh() triggers the NOTIFICATION_SYNC_REFRESH |
261 // notification. | 300 // notification. |
262 TEST_F(SyncSessionModelAssociatorTest, TriggerSessionRefresh) { | 301 TEST_F(SyncSessionModelAssociatorTest, TriggerSessionRefresh) { |
263 SyncRefreshListener refresh_listener; | 302 SyncRefreshListener refresh_listener; |
264 | 303 |
265 EXPECT_FALSE(refresh_listener.notified_of_refresh()); | 304 EXPECT_FALSE(refresh_listener.notified_of_refresh()); |
266 model_associator_->AttemptSessionsDataRefresh(); | 305 model_associator_.AttemptSessionsDataRefresh(); |
267 EXPECT_TRUE(refresh_listener.notified_of_refresh()); | 306 EXPECT_TRUE(refresh_listener.notified_of_refresh()); |
268 } | 307 } |
269 | 308 |
270 // Test that we exclude tabs with only chrome:// and file:// schemed navigations | 309 // Test that we exclude tabs with only chrome:// and file:// schemed navigations |
271 // from ShouldSyncTab(..). | 310 // from ShouldSyncTab(..). |
272 TEST_F(SyncSessionModelAssociatorTest, ValidTabs) { | 311 TEST_F(SyncSessionModelAssociatorTest, ValidTabs) { |
273 NiceMock<SyncedTabDelegateMock> tab_mock; | 312 NiceMock<SyncedTabDelegateMock> tab_mock; |
274 | 313 |
275 // A null entry shouldn't crash. | 314 // A null entry shouldn't crash. |
276 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); | 315 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); |
277 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( | 316 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
278 Return((content::NavigationEntry *)NULL)); | 317 Return((content::NavigationEntry *)NULL)); |
279 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1)); | 318 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1)); |
280 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); | 319 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
281 EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock)); | 320 EXPECT_FALSE(model_associator_.ShouldSyncTab(tab_mock)); |
282 | 321 |
283 // A chrome:// entry isn't valid. | 322 // A chrome:// entry isn't valid. |
284 scoped_ptr<content::NavigationEntry> entry( | 323 scoped_ptr<content::NavigationEntry> entry( |
285 content::NavigationEntry::Create()); | 324 content::NavigationEntry::Create()); |
286 entry->SetVirtualURL(GURL("chrome://preferences/")); | 325 entry->SetVirtualURL(GURL("chrome://preferences/")); |
287 testing::Mock::VerifyAndClearExpectations(&tab_mock); | 326 testing::Mock::VerifyAndClearExpectations(&tab_mock); |
288 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); | 327 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); |
289 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly(Return(entry.get())); | 328 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly(Return(entry.get())); |
290 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1)); | 329 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(1)); |
291 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); | 330 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
292 EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock)); | 331 EXPECT_FALSE(model_associator_.ShouldSyncTab(tab_mock)); |
293 | 332 |
294 // A file:// entry isn't valid, even in addition to another entry. | 333 // A file:// entry isn't valid, even in addition to another entry. |
295 scoped_ptr<content::NavigationEntry> entry2( | 334 scoped_ptr<content::NavigationEntry> entry2( |
296 content::NavigationEntry::Create()); | 335 content::NavigationEntry::Create()); |
297 entry2->SetVirtualURL(GURL("file://bla")); | 336 entry2->SetVirtualURL(GURL("file://bla")); |
298 testing::Mock::VerifyAndClearExpectations(&tab_mock); | 337 testing::Mock::VerifyAndClearExpectations(&tab_mock); |
299 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); | 338 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); |
300 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly(Return(entry.get())); | 339 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly(Return(entry.get())); |
301 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( | 340 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
302 Return(entry2.get())); | 341 Return(entry2.get())); |
303 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(2)); | 342 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(2)); |
304 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); | 343 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
305 EXPECT_FALSE(model_associator_->ShouldSyncTab(tab_mock)); | 344 EXPECT_FALSE(model_associator_.ShouldSyncTab(tab_mock)); |
306 | 345 |
307 // Add a valid scheme entry to tab, making the tab valid. | 346 // Add a valid scheme entry to tab, making the tab valid. |
308 scoped_ptr<content::NavigationEntry> entry3( | 347 scoped_ptr<content::NavigationEntry> entry3( |
309 content::NavigationEntry::Create()); | 348 content::NavigationEntry::Create()); |
310 entry3->SetVirtualURL(GURL("http://www.google.com")); | 349 entry3->SetVirtualURL(GURL("http://www.google.com")); |
311 testing::Mock::VerifyAndClearExpectations(&tab_mock); | 350 testing::Mock::VerifyAndClearExpectations(&tab_mock); |
312 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); | 351 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(0)); |
313 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( | 352 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
314 Return(entry.get())); | 353 Return(entry.get())); |
315 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( | 354 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
316 Return(entry2.get())); | 355 Return(entry2.get())); |
317 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( | 356 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
318 Return(entry3.get())); | 357 Return(entry3.get())); |
319 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); | 358 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); |
320 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); | 359 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
321 EXPECT_TRUE(model_associator_->ShouldSyncTab(tab_mock)); | 360 EXPECT_TRUE(model_associator_.ShouldSyncTab(tab_mock)); |
| 361 } |
| 362 |
| 363 // Create tab specifics with an empty favicon. Ensure it gets ignored and not |
| 364 // stored into the synced favicon lookups. |
| 365 TEST_F(SyncSessionModelAssociatorTest, LoadEmptyFavicon) { |
| 366 std::string favicon = ""; |
| 367 std::string favicon_url = "http://www.faviconurl.com/favicon.ico"; |
| 368 std::string page_url = "http://www.faviconurl.com/page.html"; |
| 369 sync_pb::SessionTab tab; |
| 370 tab.set_favicon(favicon); |
| 371 tab.set_favicon_source(favicon_url); |
| 372 tab.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); |
| 373 sync_pb::TabNavigation* navigation = tab.add_navigation(); |
| 374 navigation->set_virtual_url(page_url); |
| 375 tab.set_current_navigation_index(0); |
| 376 |
| 377 std::string synced_favicon; |
| 378 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 379 EXPECT_TRUE(synced_favicon.empty()); |
| 380 LoadTabFavicon(tab); |
| 381 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 382 EXPECT_TRUE(synced_favicon.empty()); |
| 383 } |
| 384 |
| 385 // Create tab specifics with a non-web favicon. Ensure it gets ignored and not |
| 386 // stored into the synced favicon lookups. |
| 387 TEST_F(SyncSessionModelAssociatorTest, LoadNonWebFavicon) { |
| 388 std::string favicon = "these are icon synced_favicon"; |
| 389 std::string favicon_url = "http://www.faviconurl.com/favicon.ico"; |
| 390 std::string page_url = "http://www.faviconurl.com/page.html"; |
| 391 sync_pb::SessionTab tab; |
| 392 tab.set_favicon(favicon); |
| 393 tab.set_favicon_source(favicon_url); |
| 394 // Set favicon type to an unsupported value (1 == WEB_FAVICON). |
| 395 tab.mutable_unknown_fields()->AddVarint(9, 2); |
| 396 sync_pb::TabNavigation* navigation = tab.add_navigation(); |
| 397 navigation->set_virtual_url(page_url); |
| 398 tab.set_current_navigation_index(0); |
| 399 |
| 400 std::string synced_favicon; |
| 401 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 402 EXPECT_TRUE(synced_favicon.empty()); |
| 403 LoadTabFavicon(tab); |
| 404 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 405 EXPECT_TRUE(synced_favicon.empty()); |
| 406 } |
| 407 |
| 408 // Create tab specifics with a valid favicon. Ensure it gets stored in the |
| 409 // synced favicon lookups and is accessible by the page url. |
| 410 TEST_F(SyncSessionModelAssociatorTest, LoadValidFavicon) { |
| 411 std::string favicon = "these are icon synced_favicon"; |
| 412 std::string favicon_url = "http://www.faviconurl.com/favicon.ico"; |
| 413 std::string page_url = "http://www.faviconurl.com/page.html"; |
| 414 sync_pb::SessionTab tab; |
| 415 tab.set_favicon(favicon); |
| 416 tab.set_favicon_source(favicon_url); |
| 417 tab.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); |
| 418 sync_pb::TabNavigation* navigation = tab.add_navigation(); |
| 419 navigation->set_virtual_url(page_url); |
| 420 tab.set_current_navigation_index(0); |
| 421 |
| 422 std::string synced_favicon; |
| 423 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 424 EXPECT_TRUE(synced_favicon.empty()); |
| 425 LoadTabFavicon(tab); |
| 426 EXPECT_TRUE(GetFavicon(page_url, &synced_favicon)); |
| 427 ASSERT_FALSE(synced_favicon.empty()); |
| 428 EXPECT_EQ(favicon, synced_favicon); |
| 429 } |
| 430 |
| 431 // Create tab specifics with a valid favicon, load it, then load tab specifics |
| 432 // with a new favicon for the same favicon source but different page. Ensure the |
| 433 // new favicon overwrites the old favicon for both page urls. |
| 434 TEST_F(SyncSessionModelAssociatorTest, UpdateValidFavicon) { |
| 435 std::string favicon_url = "http://www.faviconurl.com/favicon.ico"; |
| 436 |
| 437 std::string favicon = "these are icon synced_favicon"; |
| 438 std::string page_url = "http://www.faviconurl.com/page.html"; |
| 439 sync_pb::SessionTab tab; |
| 440 tab.set_favicon(favicon); |
| 441 tab.set_favicon_source(favicon_url); |
| 442 tab.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); |
| 443 sync_pb::TabNavigation* navigation = tab.add_navigation(); |
| 444 navigation->set_virtual_url(page_url); |
| 445 tab.set_current_navigation_index(0); |
| 446 |
| 447 std::string synced_favicon; |
| 448 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 449 EXPECT_TRUE(synced_favicon.empty()); |
| 450 LoadTabFavicon(tab); |
| 451 EXPECT_TRUE(GetFavicon(page_url, &synced_favicon)); |
| 452 ASSERT_FALSE(synced_favicon.empty()); |
| 453 EXPECT_EQ(favicon, synced_favicon); |
| 454 |
| 455 // Now have a new page with same favicon source but newer favicon data. |
| 456 std::string favicon2 = "these are new icon synced_favicon"; |
| 457 std::string page_url2 = "http://www.faviconurl.com/page2.html"; |
| 458 sync_pb::SessionTab tab2; |
| 459 tab2.set_favicon(favicon2); |
| 460 tab2.set_favicon_source(favicon_url); |
| 461 tab2.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); |
| 462 sync_pb::TabNavigation* navigation2 = tab2.add_navigation(); |
| 463 navigation2->set_virtual_url(page_url2); |
| 464 tab2.set_current_navigation_index(0); |
| 465 |
| 466 // Verify the favicons for both pages match the newest favicon. |
| 467 synced_favicon.clear(); |
| 468 EXPECT_FALSE(GetFavicon(page_url2, &synced_favicon)); |
| 469 EXPECT_TRUE(synced_favicon.empty()); |
| 470 LoadTabFavicon(tab2); |
| 471 EXPECT_TRUE(GetFavicon(page_url2, &synced_favicon)); |
| 472 ASSERT_FALSE(synced_favicon.empty()); |
| 473 EXPECT_EQ(favicon2, synced_favicon); |
| 474 EXPECT_NE(favicon, synced_favicon); |
| 475 synced_favicon.clear(); |
| 476 EXPECT_TRUE(GetFavicon(page_url, &synced_favicon)); |
| 477 ASSERT_FALSE(synced_favicon.empty()); |
| 478 EXPECT_EQ(favicon2, synced_favicon); |
| 479 EXPECT_NE(favicon, synced_favicon); |
| 480 } |
| 481 |
| 482 // Ensure that favicon cleanup cleans up favicons no longer being used and |
| 483 // doesn't touch those favicons still in use. |
| 484 TEST_F(SyncSessionModelAssociatorTest, FaviconCleanup) { |
| 485 EXPECT_EQ(NumFavicons(), 0U); |
| 486 |
| 487 std::string double_favicon = "these are icon synced_favicon"; |
| 488 std::string double_favicon_url = "http://www.faviconurl.com/favicon.ico"; |
| 489 std::string page_url = "http://www.faviconurl.com/page.html"; |
| 490 sync_pb::SessionTab tab; |
| 491 tab.set_favicon(double_favicon); |
| 492 tab.set_favicon_source(double_favicon_url); |
| 493 tab.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON); |
| 494 sync_pb::TabNavigation* navigation = tab.add_navigation(); |
| 495 navigation->set_virtual_url(page_url); |
| 496 tab.set_current_navigation_index(0); |
| 497 LoadTabFavicon(tab); |
| 498 EXPECT_EQ(1U, NumFavicons()); |
| 499 |
| 500 // Add another page using the first favicon. |
| 501 std::string page_url2 = "http://www.faviconurl.com/page2.html"; |
| 502 tab.mutable_navigation(0)->set_virtual_url(page_url2); |
| 503 LoadTabFavicon(tab); |
| 504 EXPECT_EQ(1U, NumFavicons()); |
| 505 |
| 506 // Add a favicon with a single user. |
| 507 std::string single_favicon = "different favicon synced_favicon"; |
| 508 std::string single_favicon_url = "http://www.single_favicon_page.com/x.ico"; |
| 509 std::string single_favicon_page = "http://www.single_favicon_page.com/x.html"; |
| 510 tab.set_favicon(single_favicon); |
| 511 tab.set_favicon_source(single_favicon_url); |
| 512 tab.mutable_navigation(0)->set_virtual_url(single_favicon_page); |
| 513 LoadTabFavicon(tab); |
| 514 EXPECT_EQ(2U, NumFavicons()); |
| 515 |
| 516 // Decrementing a favicon used by one page should remove it. |
| 517 std::string synced_favicon; |
| 518 EXPECT_TRUE(GetFavicon(single_favicon_page, &synced_favicon)); |
| 519 EXPECT_EQ(synced_favicon, single_favicon); |
| 520 DecrementFavicon(single_favicon_page); |
| 521 synced_favicon.clear(); |
| 522 EXPECT_FALSE(GetFavicon(single_favicon_page, &synced_favicon)); |
| 523 EXPECT_TRUE(synced_favicon.empty()); |
| 524 EXPECT_EQ(1U, NumFavicons()); |
| 525 |
| 526 // Decrementing a favicon used by two pages shouldn't remove it. |
| 527 synced_favicon.clear(); |
| 528 EXPECT_TRUE(GetFavicon(page_url, &synced_favicon)); |
| 529 EXPECT_EQ(synced_favicon, double_favicon); |
| 530 synced_favicon.clear(); |
| 531 EXPECT_TRUE(GetFavicon(page_url2, &synced_favicon)); |
| 532 EXPECT_EQ(synced_favicon, double_favicon); |
| 533 DecrementFavicon(page_url); |
| 534 EXPECT_EQ(1U, NumFavicons()); |
| 535 synced_favicon.clear(); |
| 536 EXPECT_TRUE(GetFavicon(page_url, &synced_favicon)); |
| 537 EXPECT_EQ(synced_favicon, double_favicon); |
| 538 synced_favicon.clear(); |
| 539 EXPECT_TRUE(GetFavicon(page_url2, &synced_favicon)); |
| 540 EXPECT_EQ(synced_favicon, double_favicon); |
| 541 EXPECT_EQ(1U, NumFavicons()); |
| 542 |
| 543 // Attempting to decrement a page that's already removed should do nothing. |
| 544 DecrementFavicon(single_favicon_page); |
| 545 EXPECT_EQ(1U, NumFavicons()); |
| 546 |
| 547 // Attempting to decrement an empty url should do nothing. |
| 548 DecrementFavicon(""); |
| 549 EXPECT_EQ(1U, NumFavicons()); |
| 550 |
| 551 // Decrementing the second and only remaining page should remove the favicon. |
| 552 // Both pages that referred to it should now fail to look up their favicon. |
| 553 DecrementFavicon(page_url2); |
| 554 synced_favicon.clear(); |
| 555 EXPECT_FALSE(GetFavicon(page_url, &synced_favicon)); |
| 556 EXPECT_TRUE(synced_favicon.empty()); |
| 557 EXPECT_EQ(0U, NumFavicons()); |
| 558 synced_favicon.clear(); |
| 559 EXPECT_FALSE(GetFavicon(page_url2, &synced_favicon)); |
| 560 EXPECT_TRUE(synced_favicon.empty()); |
| 561 EXPECT_EQ(0U, NumFavicons()); |
| 562 } |
| 563 |
| 564 // Ensure new tabs have all new timestamps set. |
| 565 TEST_F(SyncSessionModelAssociatorTest, AssociateNewTab) { |
| 566 NiceMock<SyncedWindowDelegateMock> window_mock; |
| 567 EXPECT_CALL(window_mock, IsTabPinned(_)).WillRepeatedly(Return(false)); |
| 568 |
| 569 // Create a tab with three valid entries. |
| 570 NiceMock<SyncedTabDelegateMock> tab_mock; |
| 571 EXPECT_CALL(tab_mock, GetSessionId()).WillRepeatedly(Return(0)); |
| 572 scoped_ptr<content::NavigationEntry> entry1( |
| 573 content::NavigationEntry::Create()); |
| 574 entry1->SetVirtualURL(GURL("http://www.google.com")); |
| 575 scoped_ptr<content::NavigationEntry> entry2( |
| 576 content::NavigationEntry::Create()); |
| 577 entry2->SetVirtualURL(GURL("http://www.noodle.com")); |
| 578 scoped_ptr<content::NavigationEntry> entry3( |
| 579 content::NavigationEntry::Create()); |
| 580 entry3->SetVirtualURL(GURL("http://www.doodle.com")); |
| 581 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(2)); |
| 582 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
| 583 Return(entry1.get())); |
| 584 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
| 585 Return(entry2.get())); |
| 586 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
| 587 Return(entry3.get())); |
| 588 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); |
| 589 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
| 590 |
| 591 // This tab is new, so prev_tab is the default SyncedSessionTab object. |
| 592 SyncedSessionTab prev_tab; |
| 593 prev_tab.tab_id.set_id(0); |
| 594 |
| 595 sync_pb::SessionTab sync_tab; |
| 596 GURL new_url; |
| 597 int64 now = TimeToProtoTime(base::Time::Now()); |
| 598 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 599 |
| 600 EXPECT_EQ(new_url, entry3->GetVirtualURL()); |
| 601 ASSERT_EQ(3, sync_tab.navigation_size()); |
| 602 EXPECT_EQ(entry1->GetVirtualURL().spec(), |
| 603 sync_tab.navigation(0).virtual_url()); |
| 604 EXPECT_EQ(entry2->GetVirtualURL().spec(), |
| 605 sync_tab.navigation(1).virtual_url()); |
| 606 EXPECT_EQ(entry3->GetVirtualURL().spec(), |
| 607 sync_tab.navigation(2).virtual_url()); |
| 608 EXPECT_EQ(2, sync_tab.current_navigation_index()); |
| 609 EXPECT_LE(now, sync_tab.navigation(0).timestamp()); |
| 610 EXPECT_LE(now, sync_tab.navigation(1).timestamp()); |
| 611 EXPECT_LE(now, sync_tab.navigation(2).timestamp()); |
| 612 } |
| 613 |
| 614 // Ensure we preserve old timestamps when the entries don't change. |
| 615 TEST_F(SyncSessionModelAssociatorTest, AssociateExistingTab) { |
| 616 NiceMock<SyncedWindowDelegateMock> window_mock; |
| 617 EXPECT_CALL(window_mock, IsTabPinned(_)).WillRepeatedly(Return(false)); |
| 618 |
| 619 // Create a tab with three valid entries. |
| 620 NiceMock<SyncedTabDelegateMock> tab_mock; |
| 621 EXPECT_CALL(tab_mock, GetSessionId()).WillRepeatedly(Return(0)); |
| 622 scoped_ptr<content::NavigationEntry> entry1( |
| 623 content::NavigationEntry::Create()); |
| 624 entry1->SetVirtualURL(GURL("http://www.google.com")); |
| 625 scoped_ptr<content::NavigationEntry> entry2( |
| 626 content::NavigationEntry::Create()); |
| 627 entry2->SetVirtualURL(GURL("http://www.noodle.com")); |
| 628 scoped_ptr<content::NavigationEntry> entry3( |
| 629 content::NavigationEntry::Create()); |
| 630 entry3->SetVirtualURL(GURL("http://www.doodle.com")); |
| 631 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(2)); |
| 632 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
| 633 Return(entry1.get())); |
| 634 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
| 635 Return(entry2.get())); |
| 636 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
| 637 Return(entry3.get())); |
| 638 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); |
| 639 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
| 640 |
| 641 // This tab is new, so prev_tab is the default SyncedSessionTab object. |
| 642 SyncedSessionTab prev_tab; |
| 643 prev_tab.tab_id.set_id(0); |
| 644 |
| 645 // The initial AssociateTabContents call builds the prev_tab. |
| 646 sync_pb::SessionTab sync_tab; |
| 647 GURL new_url; |
| 648 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 649 |
| 650 // Override the timestamps to arbitrary old values we can compare against. |
| 651 prev_tab.synced_tab_navigations[0].set_timestamp(ProtoTimeToTime(1)); |
| 652 prev_tab.synced_tab_navigations[1].set_timestamp(ProtoTimeToTime(2)); |
| 653 prev_tab.synced_tab_navigations[2].set_timestamp(ProtoTimeToTime(3)); |
| 654 |
| 655 // Now re-associate with the same data. |
| 656 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 657 |
| 658 EXPECT_EQ(new_url, entry3->GetVirtualURL()); |
| 659 ASSERT_EQ(3, sync_tab.navigation_size()); |
| 660 EXPECT_EQ(entry1->GetVirtualURL().spec(), |
| 661 sync_tab.navigation(0).virtual_url()); |
| 662 EXPECT_EQ(entry2->GetVirtualURL().spec(), |
| 663 sync_tab.navigation(1).virtual_url()); |
| 664 EXPECT_EQ(entry3->GetVirtualURL().spec(), |
| 665 sync_tab.navigation(2).virtual_url()); |
| 666 EXPECT_EQ(2, sync_tab.current_navigation_index()); |
| 667 EXPECT_EQ(1, sync_tab.navigation(0).timestamp()); |
| 668 EXPECT_EQ(2, sync_tab.navigation(1).timestamp()); |
| 669 EXPECT_EQ(3, sync_tab.navigation(2).timestamp()); |
| 670 EXPECT_EQ(3U, prev_tab.navigations.size()); |
| 671 EXPECT_EQ(3U, prev_tab.synced_tab_navigations.size()); |
| 672 } |
| 673 |
| 674 // Ensure we add a fresh timestamp for new entries appended to the end. |
| 675 TEST_F(SyncSessionModelAssociatorTest, AssociateAppendedTab) { |
| 676 NiceMock<SyncedWindowDelegateMock> window_mock; |
| 677 EXPECT_CALL(window_mock, IsTabPinned(_)).WillRepeatedly(Return(false)); |
| 678 |
| 679 // Create a tab with three valid entries. |
| 680 NiceMock<SyncedTabDelegateMock> tab_mock; |
| 681 EXPECT_CALL(tab_mock, GetSessionId()).WillRepeatedly(Return(0)); |
| 682 scoped_ptr<content::NavigationEntry> entry1( |
| 683 content::NavigationEntry::Create()); |
| 684 entry1->SetVirtualURL(GURL("http://www.google.com")); |
| 685 scoped_ptr<content::NavigationEntry> entry2( |
| 686 content::NavigationEntry::Create()); |
| 687 entry2->SetVirtualURL(GURL("http://www.noodle.com")); |
| 688 scoped_ptr<content::NavigationEntry> entry3( |
| 689 content::NavigationEntry::Create()); |
| 690 entry3->SetVirtualURL(GURL("http://www.doodle.com")); |
| 691 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(2)); |
| 692 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
| 693 Return(entry1.get())); |
| 694 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
| 695 Return(entry2.get())); |
| 696 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
| 697 Return(entry3.get())); |
| 698 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); |
| 699 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
| 700 |
| 701 // This tab is new, so prev_tab is the default SyncedSessionTab object. |
| 702 SyncedSessionTab prev_tab; |
| 703 prev_tab.tab_id.set_id(0); |
| 704 |
| 705 // The initial AssociateTabContents call builds the prev_tab. |
| 706 sync_pb::SessionTab sync_tab; |
| 707 GURL new_url; |
| 708 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 709 |
| 710 // Override the timestamps to arbitrary old values we can compare against. |
| 711 prev_tab.synced_tab_navigations[0].set_timestamp(ProtoTimeToTime(1)); |
| 712 prev_tab.synced_tab_navigations[1].set_timestamp(ProtoTimeToTime(2)); |
| 713 prev_tab.synced_tab_navigations[2].set_timestamp(ProtoTimeToTime(3)); |
| 714 |
| 715 // Add a new entry and change the current navigation index. |
| 716 scoped_ptr<content::NavigationEntry> entry4( |
| 717 content::NavigationEntry::Create()); |
| 718 entry4->SetVirtualURL(GURL("http://www.poodle.com")); |
| 719 EXPECT_CALL(tab_mock, GetEntryAtIndex(3)).WillRepeatedly( |
| 720 Return(entry4.get())); |
| 721 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(4)); |
| 722 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(3)); |
| 723 |
| 724 // The new entry should have a timestamp later than this. |
| 725 int64 now = TimeToProtoTime(base::Time::Now()); |
| 726 |
| 727 // Now re-associate with the new version. |
| 728 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 729 |
| 730 EXPECT_EQ(new_url, entry4->GetVirtualURL()); |
| 731 ASSERT_EQ(4, sync_tab.navigation_size()); |
| 732 EXPECT_EQ(entry1->GetVirtualURL().spec(), |
| 733 sync_tab.navigation(0).virtual_url()); |
| 734 EXPECT_EQ(entry2->GetVirtualURL().spec(), |
| 735 sync_tab.navigation(1).virtual_url()); |
| 736 EXPECT_EQ(entry3->GetVirtualURL().spec(), |
| 737 sync_tab.navigation(2).virtual_url()); |
| 738 EXPECT_EQ(entry4->GetVirtualURL().spec(), |
| 739 sync_tab.navigation(3).virtual_url()); |
| 740 EXPECT_EQ(3, sync_tab.current_navigation_index()); |
| 741 EXPECT_EQ(1, sync_tab.navigation(0).timestamp()); |
| 742 EXPECT_EQ(2, sync_tab.navigation(1).timestamp()); |
| 743 EXPECT_EQ(3, sync_tab.navigation(2).timestamp()); |
| 744 EXPECT_LE(now, sync_tab.navigation(3).timestamp()); |
| 745 EXPECT_EQ(4U, prev_tab.navigations.size()); |
| 746 EXPECT_EQ(4U, prev_tab.synced_tab_navigations.size()); |
| 747 } |
| 748 |
| 749 // We shouldn't get confused when old/new entries from the previous tab have |
| 750 // been pruned in the new tab. Timestamps for old entries we move back to in the |
| 751 // navigation stack should be refreshed. |
| 752 TEST_F(SyncSessionModelAssociatorTest, AssociatePrunedTab) { |
| 753 NiceMock<SyncedWindowDelegateMock> window_mock; |
| 754 EXPECT_CALL(window_mock, IsTabPinned(_)).WillRepeatedly(Return(false)); |
| 755 |
| 756 // Create a tab with four valid entries. |
| 757 NiceMock<SyncedTabDelegateMock> tab_mock; |
| 758 EXPECT_CALL(tab_mock, GetSessionId()).WillRepeatedly(Return(0)); |
| 759 scoped_ptr<content::NavigationEntry> entry1( |
| 760 content::NavigationEntry::Create()); |
| 761 entry1->SetVirtualURL(GURL("http://www.google.com")); |
| 762 scoped_ptr<content::NavigationEntry> entry2( |
| 763 content::NavigationEntry::Create()); |
| 764 entry2->SetVirtualURL(GURL("http://www.noodle.com")); |
| 765 scoped_ptr<content::NavigationEntry> entry3( |
| 766 content::NavigationEntry::Create()); |
| 767 entry3->SetVirtualURL(GURL("http://www.doodle.com")); |
| 768 scoped_ptr<content::NavigationEntry> entry4( |
| 769 content::NavigationEntry::Create()); |
| 770 entry4->SetVirtualURL(GURL("http://www.poodle.com")); |
| 771 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(3)); |
| 772 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
| 773 Return(entry1.get())); |
| 774 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
| 775 Return(entry2.get())); |
| 776 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
| 777 Return(entry3.get())); |
| 778 EXPECT_CALL(tab_mock, GetEntryAtIndex(3)).WillRepeatedly( |
| 779 Return(entry4.get())); |
| 780 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(4)); |
| 781 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
| 782 |
| 783 // This tab is new, so prev_tab is the default SyncedSessionTab object. |
| 784 SyncedSessionTab prev_tab; |
| 785 prev_tab.tab_id.set_id(0); |
| 786 |
| 787 // The initial AssociateTabContents call builds the prev_tab. |
| 788 sync_pb::SessionTab sync_tab; |
| 789 GURL new_url; |
| 790 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 791 |
| 792 // Override the timestamps to arbitrary old values we can compare against. |
| 793 prev_tab.synced_tab_navigations[0].set_timestamp(ProtoTimeToTime(1)); |
| 794 prev_tab.synced_tab_navigations[1].set_timestamp(ProtoTimeToTime(2)); |
| 795 prev_tab.synced_tab_navigations[2].set_timestamp(ProtoTimeToTime(3)); |
| 796 prev_tab.synced_tab_navigations[2].set_timestamp(ProtoTimeToTime(4)); |
| 797 |
| 798 // Reset new tab to have the oldest entry pruned, the current navigation |
| 799 // set to entry3, and a new entry added in place of entry4. |
| 800 testing::Mock::VerifyAndClearExpectations(&tab_mock); |
| 801 EXPECT_CALL(tab_mock, GetCurrentEntryIndex()).WillRepeatedly(Return(1)); |
| 802 EXPECT_CALL(tab_mock, GetEntryAtIndex(0)).WillRepeatedly( |
| 803 Return(entry2.get())); |
| 804 EXPECT_CALL(tab_mock, GetEntryAtIndex(1)).WillRepeatedly( |
| 805 Return(entry3.get())); |
| 806 scoped_ptr<content::NavigationEntry> entry5( |
| 807 content::NavigationEntry::Create()); |
| 808 entry5->SetVirtualURL(GURL("http://www.noogle.com")); |
| 809 EXPECT_CALL(tab_mock, GetEntryAtIndex(2)).WillRepeatedly( |
| 810 Return(entry5.get())); |
| 811 EXPECT_CALL(tab_mock, GetEntryCount()).WillRepeatedly(Return(3)); |
| 812 EXPECT_CALL(tab_mock, GetPendingEntryIndex()).WillRepeatedly(Return(-1)); |
| 813 |
| 814 // The new entry should have a timestamp later than this. |
| 815 int64 now = TimeToProtoTime(base::Time::Now()); |
| 816 |
| 817 // Now re-associate with the new version. |
| 818 AssociateTabContents(window_mock, tab_mock, &prev_tab, &sync_tab, &new_url); |
| 819 |
| 820 // Only entry2's timestamp should be preserved. The new entry should have a |
| 821 // new timestamp. |
| 822 EXPECT_EQ(new_url, entry3->GetVirtualURL()); |
| 823 ASSERT_EQ(3, sync_tab.navigation_size()); |
| 824 EXPECT_EQ(entry2->GetVirtualURL().spec(), |
| 825 sync_tab.navigation(0).virtual_url()); |
| 826 EXPECT_EQ(entry3->GetVirtualURL().spec(), |
| 827 sync_tab.navigation(1).virtual_url()); |
| 828 EXPECT_EQ(entry5->GetVirtualURL().spec(), |
| 829 sync_tab.navigation(2).virtual_url()); |
| 830 EXPECT_EQ(1, sync_tab.current_navigation_index()); |
| 831 EXPECT_EQ(2, sync_tab.navigation(0).timestamp()); |
| 832 EXPECT_LE(now, sync_tab.navigation(1).timestamp()); |
| 833 EXPECT_LE(now, sync_tab.navigation(2).timestamp()); |
| 834 EXPECT_EQ(3U, prev_tab.navigations.size()); |
| 835 EXPECT_EQ(3U, prev_tab.synced_tab_navigations.size()); |
322 } | 836 } |
323 | 837 |
324 } // namespace browser_sync | 838 } // namespace browser_sync |
OLD | NEW |