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
3 // found in the LICENSE file.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/sessions/session_types.h"
12 #include "chrome/browser/sync/glue/session_model_associator.h"
13 #include "chrome/browser/sync/glue/synced_tab_delegate.h"
14 #include "chrome/browser/sync/profile_sync_service_mock.h"
15 #include "chrome/common/url_constants.h"
16 #include "chrome/test/base/profile_mock.h"
17 #include "components/sessions/serialized_navigation_entry_test_helper.h"
18 #include "content/public/browser/navigation_entry.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/common/page_transition_types.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "sync/protocol/session_specifics.pb.h"
24 #include "sync/util/time.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
29 using content::BrowserThread
;
30 using sessions::SerializedNavigationEntry
;
31 using sessions::SerializedNavigationEntryTestHelper
;
32 using testing::NiceMock
;
33 using testing::Return
;
34 using testing::StrictMock
;
37 namespace browser_sync
{
39 class SyncSessionModelAssociatorTest
: public testing::Test
{
41 SyncSessionModelAssociatorTest()
42 : ui_thread_(BrowserThread::UI
, &message_loop_
),
43 sync_service_(&profile_
),
44 model_associator_(&sync_service_
, true) {}
46 void LoadTabFavicon(const sync_pb::SessionTab
& tab
) {
47 model_associator_
.LoadForeignTabFavicon(tab
);
48 message_loop_
.RunUntilIdle();
51 static GURL
GetCurrentVirtualURL(const SyncedTabDelegate
& tab_delegate
) {
52 return SessionModelAssociator::GetCurrentVirtualURL(tab_delegate
);
55 static void SetSessionTabFromDelegate(
56 const SyncedTabDelegate
& tab_delegate
,
58 SessionTab
* session_tab
) {
59 SessionModelAssociator::SetSessionTabFromDelegate(
65 bool FaviconEquals(const GURL page_url
,
66 std::string expected_bytes
) {
67 FaviconCache
* cache
= model_associator_
.GetFaviconCache();
69 scoped_refptr
<base::RefCountedMemory
> favicon
;
70 if (!cache
->GetSyncedFaviconForPageURL(gurl
, &favicon
))
71 return expected_bytes
.empty();
72 if (favicon
->size() != expected_bytes
.size())
74 for (size_t i
= 0; i
< favicon
->size(); ++i
) {
75 if (expected_bytes
[i
] != *(favicon
->front() + i
))
82 base::MessageLoopForUI message_loop_
;
83 content::TestBrowserThread ui_thread_
;
84 NiceMock
<ProfileMock
> profile_
;
85 NiceMock
<ProfileSyncServiceMock
> sync_service_
;
88 SessionModelAssociator model_associator_
;
93 TEST_F(SyncSessionModelAssociatorTest
, SessionWindowHasNoTabsToSync
) {
95 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win
));
96 scoped_ptr
<SessionTab
> tab(new SessionTab());
97 win
.tabs
.push_back(tab
.release());
98 ASSERT_TRUE(SessionWindowHasNoTabsToSync(win
));
99 SerializedNavigationEntry nav
=
100 SerializedNavigationEntryTestHelper::CreateNavigation("about:bubba",
102 win
.tabs
[0]->navigations
.push_back(nav
);
103 ASSERT_FALSE(SessionWindowHasNoTabsToSync(win
));
106 TEST_F(SyncSessionModelAssociatorTest
, ShouldSyncSessionTab
) {
108 ASSERT_FALSE(ShouldSyncSessionTab(tab
));
109 SerializedNavigationEntry nav
=
110 SerializedNavigationEntryTestHelper::CreateNavigation(
111 chrome::kChromeUINewTabURL
, "title");
112 tab
.navigations
.push_back(nav
);
113 // NewTab does not count as valid if it's the only navigation.
114 ASSERT_FALSE(ShouldSyncSessionTab(tab
));
115 SerializedNavigationEntry nav2
=
116 SerializedNavigationEntryTestHelper::CreateNavigation("about:bubba",
118 tab
.navigations
.push_back(nav2
);
119 // Once there's another navigation, the tab is valid.
120 ASSERT_TRUE(ShouldSyncSessionTab(tab
));
123 TEST_F(SyncSessionModelAssociatorTest
,
124 ShouldSyncSessionTabIgnoresFragmentForNtp
) {
126 ASSERT_FALSE(ShouldSyncSessionTab(tab
));
127 SerializedNavigationEntry nav
=
128 SerializedNavigationEntryTestHelper::CreateNavigation(
129 std::string(chrome::kChromeUINewTabURL
) + "#bookmarks", "title");
130 tab
.navigations
.push_back(nav
);
131 // NewTab does not count as valid if it's the only navigation.
132 ASSERT_FALSE(ShouldSyncSessionTab(tab
));
137 TEST_F(SyncSessionModelAssociatorTest
, PopulateSessionHeader
) {
138 sync_pb::SessionHeader header_s
;
139 header_s
.set_client_name("Client 1");
140 header_s
.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_WIN
);
142 SyncedSession session
;
143 base::Time time
= base::Time::Now();
144 SessionModelAssociator::PopulateSessionHeaderFromSpecifics(
145 header_s
, time
, &session
);
146 ASSERT_EQ("Client 1", session
.session_name
);
147 ASSERT_EQ(SyncedSession::TYPE_WIN
, session
.device_type
);
148 ASSERT_EQ(time
, session
.modified_time
);
151 TEST_F(SyncSessionModelAssociatorTest
, PopulateSessionWindow
) {
152 sync_pb::SessionWindow window_s
;
154 window_s
.set_browser_type(sync_pb::SessionWindow_BrowserType_TYPE_TABBED
);
155 window_s
.set_selected_tab_index(1);
157 std::string tag
= "tag";
158 SyncedSessionTracker tracker
;
159 SyncedSession
* session
= tracker
.GetSession(tag
);
160 tracker
.PutWindowInSession(tag
, 0);
161 SessionModelAssociator::PopulateSessionWindowFromSpecifics(
162 tag
, window_s
, base::Time(), session
->windows
[0], &tracker
);
163 ASSERT_EQ(1U, session
->windows
[0]->tabs
.size());
164 ASSERT_EQ(1, session
->windows
[0]->selected_tab_index
);
165 ASSERT_EQ(1, session
->windows
[0]->type
);
166 ASSERT_EQ(1U, tracker
.num_synced_sessions());
167 ASSERT_EQ(1U, tracker
.num_synced_tabs(std::string("tag")));
172 class SyncedTabDelegateMock
: public SyncedTabDelegate
{
174 SyncedTabDelegateMock() {}
175 virtual ~SyncedTabDelegateMock() {}
177 MOCK_CONST_METHOD0(GetWindowId
, SessionID::id_type());
178 MOCK_CONST_METHOD0(GetSessionId
, SessionID::id_type());
179 MOCK_CONST_METHOD0(IsBeingDestroyed
, bool());
180 MOCK_CONST_METHOD0(profile
, Profile
*());
181 MOCK_CONST_METHOD0(GetExtensionAppId
, std::string());
182 MOCK_CONST_METHOD0(GetCurrentEntryIndex
, int());
183 MOCK_CONST_METHOD0(GetEntryCount
, int());
184 MOCK_CONST_METHOD0(GetPendingEntryIndex
, int());
185 MOCK_CONST_METHOD0(GetPendingEntry
, content::NavigationEntry
*());
186 MOCK_CONST_METHOD1(GetEntryAtIndex
, content::NavigationEntry
*(int i
));
187 MOCK_CONST_METHOD0(GetActiveEntry
, content::NavigationEntry
*());
188 MOCK_CONST_METHOD0(ProfileIsManaged
, bool());
189 MOCK_CONST_METHOD0(GetBlockedNavigations
,
190 const std::vector
<const content::NavigationEntry
*>*());
191 MOCK_CONST_METHOD0(IsPinned
, bool());
192 MOCK_CONST_METHOD0(HasWebContents
, bool());
193 MOCK_CONST_METHOD0(GetWebContents
, content::WebContents
*());
194 MOCK_CONST_METHOD0(GetSyncId
, int());
195 MOCK_METHOD1(SetSyncId
, void(int));
198 class SyncRefreshListener
: public content::NotificationObserver
{
200 SyncRefreshListener() : notified_of_refresh_(false) {
201 registrar_
.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL
,
202 content::NotificationService::AllSources());
205 virtual void Observe(int type
,
206 const content::NotificationSource
& source
,
207 const content::NotificationDetails
& details
) OVERRIDE
{
208 if (type
== chrome::NOTIFICATION_SYNC_REFRESH_LOCAL
) {
209 notified_of_refresh_
= true;
213 bool notified_of_refresh() const { return notified_of_refresh_
; }
216 bool notified_of_refresh_
;
217 content::NotificationRegistrar registrar_
;
220 // Test that AttemptSessionsDataRefresh() triggers the
221 // NOTIFICATION_SYNC_REFRESH_LOCAL notification.
222 TEST_F(SyncSessionModelAssociatorTest
, TriggerSessionRefresh
) {
223 SyncRefreshListener refresh_listener
;
225 EXPECT_FALSE(refresh_listener
.notified_of_refresh());
226 model_associator_
.AttemptSessionsDataRefresh();
227 EXPECT_TRUE(refresh_listener
.notified_of_refresh());
230 // Test that we exclude tabs with only chrome:// and file:// schemed navigations
231 // from ShouldSyncTab(..).
232 TEST_F(SyncSessionModelAssociatorTest
, ValidTabs
) {
233 NiceMock
<SyncedTabDelegateMock
> tab_mock
;
235 // A null entry shouldn't crash.
236 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(0));
237 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(
238 Return((content::NavigationEntry
*)NULL
));
239 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(1));
240 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
241 EXPECT_FALSE(model_associator_
.ShouldSyncTab(tab_mock
));
243 // A chrome:// entry isn't valid.
244 scoped_ptr
<content::NavigationEntry
> entry(
245 content::NavigationEntry::Create());
246 entry
->SetVirtualURL(GURL("chrome://preferences/"));
247 testing::Mock::VerifyAndClearExpectations(&tab_mock
);
248 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(0));
249 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(Return(entry
.get()));
250 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(1));
251 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
252 EXPECT_FALSE(model_associator_
.ShouldSyncTab(tab_mock
));
254 // A file:// entry isn't valid, even in addition to another entry.
255 scoped_ptr
<content::NavigationEntry
> entry2(
256 content::NavigationEntry::Create());
257 entry2
->SetVirtualURL(GURL("file://bla"));
258 testing::Mock::VerifyAndClearExpectations(&tab_mock
);
259 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(0));
260 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(Return(entry
.get()));
261 EXPECT_CALL(tab_mock
, GetEntryAtIndex(1)).WillRepeatedly(
262 Return(entry2
.get()));
263 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(2));
264 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
265 EXPECT_FALSE(model_associator_
.ShouldSyncTab(tab_mock
));
267 // Add a valid scheme entry to tab, making the tab valid.
268 scoped_ptr
<content::NavigationEntry
> entry3(
269 content::NavigationEntry::Create());
270 entry3
->SetVirtualURL(GURL("http://www.google.com"));
271 testing::Mock::VerifyAndClearExpectations(&tab_mock
);
272 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(0));
273 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(
274 Return(entry
.get()));
275 EXPECT_CALL(tab_mock
, GetEntryAtIndex(1)).WillRepeatedly(
276 Return(entry2
.get()));
277 EXPECT_CALL(tab_mock
, GetEntryAtIndex(2)).WillRepeatedly(
278 Return(entry3
.get()));
279 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(3));
280 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
281 EXPECT_TRUE(model_associator_
.ShouldSyncTab(tab_mock
));
284 // TODO(akalin): We should really use a fake for SyncedTabDelegate.
286 // Make sure GetCurrentVirtualURL() returns the virtual URL of the pending
287 // entry if the current entry is pending.
288 TEST_F(SyncSessionModelAssociatorTest
, GetCurrentVirtualURLPending
) {
289 StrictMock
<SyncedTabDelegateMock
> tab_mock
;
290 scoped_ptr
<content::NavigationEntry
> entry(
291 content::NavigationEntry::Create());
292 entry
->SetVirtualURL(GURL("http://www.google.com"));
293 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillOnce(Return(0));
294 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillOnce(Return(0));
295 EXPECT_CALL(tab_mock
, GetPendingEntry()).WillOnce(Return(entry
.get()));
296 EXPECT_EQ(entry
->GetVirtualURL(), GetCurrentVirtualURL(tab_mock
));
299 // Make sure GetCurrentVirtualURL() returns the virtual URL of the current
300 // entry if the current entry is non-pending.
301 TEST_F(SyncSessionModelAssociatorTest
, GetCurrentVirtualURLNonPending
) {
302 StrictMock
<SyncedTabDelegateMock
> tab_mock
;
303 scoped_ptr
<content::NavigationEntry
> entry(
304 content::NavigationEntry::Create());
305 entry
->SetVirtualURL(GURL("http://www.google.com"));
306 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillOnce(Return(0));
307 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillOnce(Return(-1));
308 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillOnce(Return(entry
.get()));
309 EXPECT_EQ(entry
->GetVirtualURL(), GetCurrentVirtualURL(tab_mock
));
312 const base::Time kTime1
= base::Time::FromInternalValue(100);
313 const base::Time kTime2
= base::Time::FromInternalValue(105);
314 const base::Time kTime3
= base::Time::FromInternalValue(110);
315 const base::Time kTime4
= base::Time::FromInternalValue(120);
316 const base::Time kTime5
= base::Time::FromInternalValue(130);
318 // Populate the mock tab delegate with some data and navigation
319 // entries and make sure that setting a SessionTab from it preserves
320 // those entries (and clobbers any existing data).
321 TEST_F(SyncSessionModelAssociatorTest
, SetSessionTabFromDelegate
) {
322 // Create a tab with three valid entries.
323 NiceMock
<SyncedTabDelegateMock
> tab_mock
;
324 EXPECT_CALL(tab_mock
, GetSessionId()).WillRepeatedly(Return(0));
325 scoped_ptr
<content::NavigationEntry
> entry1(
326 content::NavigationEntry::Create());
327 entry1
->SetVirtualURL(GURL("http://www.google.com"));
328 entry1
->SetTimestamp(kTime1
);
329 entry1
->SetHttpStatusCode(200);
330 scoped_ptr
<content::NavigationEntry
> entry2(
331 content::NavigationEntry::Create());
332 entry2
->SetVirtualURL(GURL("http://www.noodle.com"));
333 entry2
->SetTimestamp(kTime2
);
334 entry2
->SetHttpStatusCode(201);
335 scoped_ptr
<content::NavigationEntry
> entry3(
336 content::NavigationEntry::Create());
337 entry3
->SetVirtualURL(GURL("http://www.doodle.com"));
338 entry3
->SetTimestamp(kTime3
);
339 entry3
->SetHttpStatusCode(202);
340 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(2));
341 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(
342 Return(entry1
.get()));
343 EXPECT_CALL(tab_mock
, GetEntryAtIndex(1)).WillRepeatedly(
344 Return(entry2
.get()));
345 EXPECT_CALL(tab_mock
, GetEntryAtIndex(2)).WillRepeatedly(
346 Return(entry3
.get()));
347 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(3));
348 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
349 EXPECT_CALL(tab_mock
, ProfileIsManaged()).WillRepeatedly(Return(false));
351 SessionTab session_tab
;
352 session_tab
.window_id
.set_id(1);
353 session_tab
.tab_id
.set_id(1);
354 session_tab
.tab_visual_index
= 1;
355 session_tab
.current_navigation_index
= 1;
356 session_tab
.pinned
= true;
357 session_tab
.extension_app_id
= "app id";
358 session_tab
.user_agent_override
= "override";
359 session_tab
.timestamp
= kTime5
;
360 session_tab
.navigations
.push_back(
361 SerializedNavigationEntryTestHelper::CreateNavigation(
362 "http://www.example.com", "Example"));
363 session_tab
.session_storage_persistent_id
= "persistent id";
364 SetSessionTabFromDelegate(tab_mock
, kTime4
, &session_tab
);
366 EXPECT_EQ(0, session_tab
.window_id
.id());
367 EXPECT_EQ(0, session_tab
.tab_id
.id());
368 EXPECT_EQ(0, session_tab
.tab_visual_index
);
369 EXPECT_EQ(2, session_tab
.current_navigation_index
);
370 EXPECT_FALSE(session_tab
.pinned
);
371 EXPECT_TRUE(session_tab
.extension_app_id
.empty());
372 EXPECT_TRUE(session_tab
.user_agent_override
.empty());
373 EXPECT_EQ(kTime4
, session_tab
.timestamp
);
374 ASSERT_EQ(3u, session_tab
.navigations
.size());
375 EXPECT_EQ(entry1
->GetVirtualURL(),
376 session_tab
.navigations
[0].virtual_url());
377 EXPECT_EQ(entry2
->GetVirtualURL(),
378 session_tab
.navigations
[1].virtual_url());
379 EXPECT_EQ(entry3
->GetVirtualURL(),
380 session_tab
.navigations
[2].virtual_url());
381 EXPECT_EQ(kTime1
, session_tab
.navigations
[0].timestamp());
382 EXPECT_EQ(kTime2
, session_tab
.navigations
[1].timestamp());
383 EXPECT_EQ(kTime3
, session_tab
.navigations
[2].timestamp());
384 EXPECT_EQ(200, session_tab
.navigations
[0].http_status_code());
385 EXPECT_EQ(201, session_tab
.navigations
[1].http_status_code());
386 EXPECT_EQ(202, session_tab
.navigations
[2].http_status_code());
387 EXPECT_EQ(SerializedNavigationEntry::STATE_INVALID
,
388 session_tab
.navigations
[0].blocked_state());
389 EXPECT_EQ(SerializedNavigationEntry::STATE_INVALID
,
390 session_tab
.navigations
[1].blocked_state());
391 EXPECT_EQ(SerializedNavigationEntry::STATE_INVALID
,
392 session_tab
.navigations
[2].blocked_state());
393 EXPECT_TRUE(session_tab
.session_storage_persistent_id
.empty());
396 // Tests that for managed users blocked navigations are recorded and marked as
397 // such, while regular navigations are marked as allowed.
398 TEST_F(SyncSessionModelAssociatorTest
, BlockedNavigations
) {
399 NiceMock
<SyncedTabDelegateMock
> tab_mock
;
400 EXPECT_CALL(tab_mock
, GetSessionId()).WillRepeatedly(Return(0));
401 scoped_ptr
<content::NavigationEntry
> entry1(
402 content::NavigationEntry::Create());
403 entry1
->SetVirtualURL(GURL("http://www.google.com"));
404 entry1
->SetTimestamp(kTime1
);
405 EXPECT_CALL(tab_mock
, GetCurrentEntryIndex()).WillRepeatedly(Return(0));
406 EXPECT_CALL(tab_mock
, GetEntryAtIndex(0)).WillRepeatedly(
407 Return(entry1
.get()));
408 EXPECT_CALL(tab_mock
, GetEntryCount()).WillRepeatedly(Return(1));
409 EXPECT_CALL(tab_mock
, GetPendingEntryIndex()).WillRepeatedly(Return(-1));
411 content::NavigationEntry
* entry2
= content::NavigationEntry::Create();
412 entry2
->SetVirtualURL(GURL("http://blocked.com/foo"));
413 entry2
->SetTimestamp(kTime2
);
414 content::NavigationEntry
* entry3
= content::NavigationEntry::Create();
415 entry3
->SetVirtualURL(GURL("http://evil.com"));
416 entry3
->SetTimestamp(kTime3
);
417 ScopedVector
<const content::NavigationEntry
> blocked_navigations
;
418 blocked_navigations
.push_back(entry2
);
419 blocked_navigations
.push_back(entry3
);
421 EXPECT_CALL(tab_mock
, ProfileIsManaged()).WillRepeatedly(Return(true));
422 EXPECT_CALL(tab_mock
, GetBlockedNavigations()).WillRepeatedly(
423 Return(&blocked_navigations
.get()));
425 SessionTab session_tab
;
426 session_tab
.window_id
.set_id(1);
427 session_tab
.tab_id
.set_id(1);
428 session_tab
.tab_visual_index
= 1;
429 session_tab
.current_navigation_index
= 1;
430 session_tab
.pinned
= true;
431 session_tab
.extension_app_id
= "app id";
432 session_tab
.user_agent_override
= "override";
433 session_tab
.timestamp
= kTime5
;
434 session_tab
.navigations
.push_back(
435 SerializedNavigationEntryTestHelper::CreateNavigation(
436 "http://www.example.com", "Example"));
437 session_tab
.session_storage_persistent_id
= "persistent id";
438 SetSessionTabFromDelegate(tab_mock
, kTime4
, &session_tab
);
440 EXPECT_EQ(0, session_tab
.window_id
.id());
441 EXPECT_EQ(0, session_tab
.tab_id
.id());
442 EXPECT_EQ(0, session_tab
.tab_visual_index
);
443 EXPECT_EQ(0, session_tab
.current_navigation_index
);
444 EXPECT_FALSE(session_tab
.pinned
);
445 EXPECT_TRUE(session_tab
.extension_app_id
.empty());
446 EXPECT_TRUE(session_tab
.user_agent_override
.empty());
447 EXPECT_EQ(kTime4
, session_tab
.timestamp
);
448 ASSERT_EQ(3u, session_tab
.navigations
.size());
449 EXPECT_EQ(entry1
->GetVirtualURL(),
450 session_tab
.navigations
[0].virtual_url());
451 EXPECT_EQ(entry2
->GetVirtualURL(),
452 session_tab
.navigations
[1].virtual_url());
453 EXPECT_EQ(entry3
->GetVirtualURL(),
454 session_tab
.navigations
[2].virtual_url());
455 EXPECT_EQ(kTime1
, session_tab
.navigations
[0].timestamp());
456 EXPECT_EQ(kTime2
, session_tab
.navigations
[1].timestamp());
457 EXPECT_EQ(kTime3
, session_tab
.navigations
[2].timestamp());
458 EXPECT_EQ(SerializedNavigationEntry::STATE_ALLOWED
,
459 session_tab
.navigations
[0].blocked_state());
460 EXPECT_EQ(SerializedNavigationEntry::STATE_BLOCKED
,
461 session_tab
.navigations
[1].blocked_state());
462 EXPECT_EQ(SerializedNavigationEntry::STATE_BLOCKED
,
463 session_tab
.navigations
[2].blocked_state());
464 EXPECT_TRUE(session_tab
.session_storage_persistent_id
.empty());
467 // Create tab specifics with an empty favicon. Ensure it gets ignored and not
468 // stored into the synced favicon lookups.
469 TEST_F(SyncSessionModelAssociatorTest
, LoadEmptyFavicon
) {
471 std::string favicon_url
= "http://www.faviconurl.com/favicon.ico";
472 std::string page_url
= "http://www.faviconurl.com/page.html";
473 sync_pb::SessionTab tab
;
474 tab
.set_favicon(favicon
);
475 tab
.set_favicon_source(favicon_url
);
476 tab
.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON
);
477 sync_pb::TabNavigation
* navigation
= tab
.add_navigation();
478 navigation
->set_virtual_url(page_url
);
479 tab
.set_current_navigation_index(0);
481 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
483 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
486 // Create tab specifics with a non-web favicon. Ensure it gets ignored and not
487 // stored into the synced favicon lookups.
488 TEST_F(SyncSessionModelAssociatorTest
, LoadNonWebFavicon
) {
489 std::string favicon
= "icon bytes";
490 std::string favicon_url
= "http://www.faviconurl.com/favicon.ico";
491 std::string page_url
= "http://www.faviconurl.com/page.html";
492 sync_pb::SessionTab tab
;
493 tab
.set_favicon(favicon
);
494 tab
.set_favicon_source(favicon_url
);
495 // Set favicon type to an unsupported value (1 == WEB_FAVICON).
496 tab
.mutable_unknown_fields()->AddVarint(9, 2);
497 sync_pb::TabNavigation
* navigation
= tab
.add_navigation();
498 navigation
->set_virtual_url(page_url
);
499 tab
.set_current_navigation_index(0);
501 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
503 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
506 // Create tab specifics with a valid favicon. Ensure it gets stored in the
507 // synced favicon lookups and is accessible by the page url.
508 TEST_F(SyncSessionModelAssociatorTest
, LoadValidFavicon
) {
509 std::string favicon
= "icon bytes";
510 std::string favicon_url
= "http://www.faviconurl.com/favicon.ico";
511 std::string page_url
= "http://www.faviconurl.com/page.html";
512 sync_pb::SessionTab tab
;
513 tab
.set_favicon(favicon
);
514 tab
.set_favicon_source(favicon_url
);
515 tab
.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON
);
516 sync_pb::TabNavigation
* navigation
= tab
.add_navigation();
517 navigation
->set_virtual_url(page_url
);
518 tab
.set_current_navigation_index(0);
520 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
522 EXPECT_TRUE(FaviconEquals(GURL(page_url
), favicon
));
525 // Create tab specifics with a valid favicon, load it, then load tab specifics
526 // with a new favicon for the same favicon source but different page. Ensure the
527 // old favicon remains.
528 TEST_F(SyncSessionModelAssociatorTest
, UpdateValidFavicon
) {
529 std::string favicon_url
= "http://www.faviconurl.com/favicon.ico";
531 std::string favicon
= "icon bytes";
532 std::string page_url
= "http://www.faviconurl.com/page.html";
533 sync_pb::SessionTab tab
;
534 tab
.set_favicon(favicon
);
535 tab
.set_favicon_source(favicon_url
);
536 tab
.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON
);
537 sync_pb::TabNavigation
* navigation
= tab
.add_navigation();
538 navigation
->set_virtual_url(page_url
);
539 tab
.set_current_navigation_index(0);
541 EXPECT_TRUE(FaviconEquals(GURL(page_url
), std::string()));
543 EXPECT_TRUE(FaviconEquals(GURL(page_url
), favicon
));
545 // Now have a new page with same favicon source but newer favicon data.
546 std::string favicon2
= "icon bytes 2";
547 std::string page_url2
= "http://www.faviconurl.com/page2.html";
548 sync_pb::SessionTab tab2
;
549 tab2
.set_favicon(favicon2
);
550 tab2
.set_favicon_source(favicon_url
);
551 tab2
.set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON
);
552 sync_pb::TabNavigation
* navigation2
= tab2
.add_navigation();
553 navigation2
->set_virtual_url(page_url2
);
554 tab2
.set_current_navigation_index(0);
556 // The new page should be mapped to the old favicon data.
557 EXPECT_TRUE(FaviconEquals(GURL(page_url2
), std::string()));
558 LoadTabFavicon(tab2
);
559 EXPECT_TRUE(FaviconEquals(GURL(page_url
), favicon
));
560 EXPECT_TRUE(FaviconEquals(GURL(page_url2
), favicon
));
565 } // namespace browser_sync