Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: chrome/browser/sync/glue/session_model_associator_unittest.cc

Issue 10125002: [Sync] Add per-navigation timestamps/unique ids to tab sync. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: nit Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698