Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / sync / profile_sync_service_session_unittest.cc
blob9b6adbdc303d5133a1ddc4140637cec2379f7305
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.
5 #include <map>
6 #include <string>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11 #include "base/compiler_specific.h"
12 #include "base/location.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop.h"
15 #include "base/scoped_temp_dir.h"
16 #include "base/stl_util.h"
17 #include "base/time.h"
18 #include "chrome/browser/sessions/session_types_test_helper.h"
19 #include "chrome/browser/signin/signin_manager.h"
20 #include "chrome/browser/signin/signin_manager_factory.h"
21 #include "chrome/browser/signin/token_service_factory.h"
22 #include "chrome/browser/sync/abstract_profile_sync_service_test.h"
23 #include "chrome/browser/sync/glue/session_change_processor.h"
24 #include "chrome/browser/sync/glue/session_data_type_controller.h"
25 #include "chrome/browser/sync/glue/session_model_associator.h"
26 #include "chrome/browser/sync/glue/sync_backend_host.h"
27 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
28 #include "chrome/browser/sync/profile_sync_service_factory.h"
29 #include "chrome/browser/sync/profile_sync_test_util.h"
30 #include "chrome/browser/sync/test_profile_sync_service.h"
31 #include "chrome/common/chrome_notification_types.h"
32 #include "chrome/test/base/browser_with_test_window_test.h"
33 #include "chrome/test/base/testing_profile.h"
34 #include "content/public/browser/navigation_entry.h"
35 #include "content/public/browser/notification_observer.h"
36 #include "content/public/browser/notification_registrar.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/test/test_browser_thread.h"
39 #include "google_apis/gaia/gaia_constants.h"
40 #include "googleurl/src/gurl.h"
41 #include "sync/internal_api/public/base/model_type.h"
42 #include "sync/internal_api/public/change_record.h"
43 #include "sync/internal_api/public/read_node.h"
44 #include "sync/internal_api/public/read_transaction.h"
45 #include "sync/internal_api/public/test/test_user_share.h"
46 #include "sync/internal_api/public/write_node.h"
47 #include "sync/internal_api/public/write_transaction.h"
48 #include "sync/protocol/session_specifics.pb.h"
49 #include "sync/protocol/sync.pb.h"
50 #include "testing/gmock/include/gmock/gmock.h"
51 #include "testing/gtest/include/gtest/gtest.h"
52 #include "ui/base/ui_base_types.h"
54 using browser_sync::SessionChangeProcessor;
55 using browser_sync::SessionDataTypeController;
56 using browser_sync::SessionModelAssociator;
57 using browser_sync::SyncBackendHost;
58 using content::BrowserThread;
59 using syncer::ChangeRecord;
60 using testing::_;
61 using testing::Return;
62 using syncer::TestIdFactory;
64 namespace browser_sync {
66 namespace {
68 void BuildSessionSpecifics(const std::string& tag,
69 sync_pb::SessionSpecifics* meta) {
70 meta->set_session_tag(tag);
71 sync_pb::SessionHeader* header = meta->mutable_header();
72 header->set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
73 header->set_client_name("name");
76 void AddWindowSpecifics(int window_id,
77 const std::vector<int>& tab_list,
78 sync_pb::SessionSpecifics* meta) {
79 sync_pb::SessionHeader* header = meta->mutable_header();
80 sync_pb::SessionWindow* window = header->add_window();
81 window->set_window_id(window_id);
82 window->set_selected_tab_index(0);
83 window->set_browser_type(sync_pb::SessionWindow_BrowserType_TYPE_TABBED);
84 for (std::vector<int>::const_iterator iter = tab_list.begin();
85 iter != tab_list.end(); ++iter) {
86 window->add_tab(*iter);
90 void BuildTabSpecifics(const std::string& tag, int window_id, int tab_id,
91 sync_pb::SessionSpecifics* tab_base) {
92 tab_base->set_session_tag(tag);
93 sync_pb::SessionTab* tab = tab_base->mutable_tab();
94 tab->set_tab_id(tab_id);
95 tab->set_tab_visual_index(1);
96 tab->set_current_navigation_index(0);
97 tab->set_pinned(true);
98 tab->set_extension_app_id("app_id");
99 sync_pb::TabNavigation* navigation = tab->add_navigation();
100 navigation->set_virtual_url("http://foo/1");
101 navigation->set_referrer("referrer");
102 navigation->set_title("title");
103 navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED);
106 // Verifies number of windows, number of tabs, and basic fields.
107 void VerifySyncedSession(
108 const std::string& tag,
109 const std::vector<std::vector<SessionID::id_type> >& windows,
110 const SyncedSession& session) {
111 ASSERT_EQ(tag, session.session_tag);
112 ASSERT_EQ(SyncedSession::TYPE_LINUX, session.device_type);
113 ASSERT_EQ("name", session.session_name);
114 ASSERT_EQ(windows.size(), session.windows.size());
116 // We assume the window id's are in increasing order.
117 int i = 0;
118 for (std::vector<std::vector<int> >::const_iterator win_iter =
119 windows.begin();
120 win_iter != windows.end(); ++win_iter, ++i) {
121 SessionWindow* win_ptr;
122 SyncedSession::SyncedWindowMap::const_iterator map_iter =
123 session.windows.find(i);
124 if (map_iter != session.windows.end())
125 win_ptr = map_iter->second;
126 else
127 FAIL();
128 ASSERT_EQ(win_iter->size(), win_ptr->tabs.size());
129 ASSERT_EQ(0, win_ptr->selected_tab_index);
130 ASSERT_EQ(1, win_ptr->type);
131 int j = 0;
132 for (std::vector<int>::const_iterator tab_iter = (*win_iter).begin();
133 tab_iter != (*win_iter).end(); ++tab_iter, ++j) {
134 SessionTab* tab = win_ptr->tabs[j];
135 ASSERT_EQ(*tab_iter, tab->tab_id.id());
136 ASSERT_EQ(1U, tab->navigations.size());
137 ASSERT_EQ(1, tab->tab_visual_index);
138 ASSERT_EQ(0, tab->current_navigation_index);
139 ASSERT_TRUE(tab->pinned);
140 ASSERT_EQ("app_id", tab->extension_app_id);
141 ASSERT_EQ(1U, tab->navigations.size());
142 ASSERT_EQ(tab->navigations[0].virtual_url(), GURL("http://foo/1"));
143 ASSERT_EQ(SessionTypesTestHelper::GetReferrer(tab->navigations[0]).url,
144 GURL("referrer"));
145 ASSERT_EQ(tab->navigations[0].title(), string16(ASCIIToUTF16("title")));
146 ASSERT_EQ(SessionTypesTestHelper::GetTransitionType(tab->navigations[0]),
147 content::PAGE_TRANSITION_TYPED);
152 } // namespace
154 class ProfileSyncServiceSessionTest
155 : public BrowserWithTestWindowTest,
156 public content::NotificationObserver {
157 public:
158 ProfileSyncServiceSessionTest()
159 : io_thread_(BrowserThread::IO),
160 window_bounds_(0, 1, 2, 3),
161 notified_of_update_(false),
162 notified_of_refresh_(false) {}
163 ProfileSyncService* sync_service() { return sync_service_.get(); }
165 protected:
166 virtual TestingProfile* CreateProfile() OVERRIDE {
167 TestingProfile* profile = new TestingProfile();
168 // Don't want the profile to create a real ProfileSyncService.
169 ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(profile,
170 NULL);
171 return profile;
174 virtual void SetUp() {
175 // BrowserWithTestWindowTest implementation.
176 BrowserWithTestWindowTest::SetUp();
177 io_thread_.StartIOThread();
178 profile()->CreateRequestContext();
179 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
180 registrar_.Add(this, chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
181 content::NotificationService::AllSources());
182 registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
183 content::NotificationService::AllSources());
186 void Observe(int type,
187 const content::NotificationSource& source,
188 const content::NotificationDetails& details) {
189 switch (type) {
190 case chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED:
191 notified_of_update_ = true;
192 break;
193 case chrome::NOTIFICATION_SYNC_REFRESH_LOCAL:
194 notified_of_refresh_ = true;
195 break;
196 default:
197 NOTREACHED();
198 break;
202 virtual void TearDown() {
203 sync_service_->Shutdown();
204 sync_service_.reset();
205 profile()->ResetRequestContext();
207 // We need to destroy the profile before shutting down the threads, because
208 // some of the ref counted objects in the profile depend on their
209 // destruction on the io thread.
210 DestroyBrowserAndProfile();
211 set_profile(NULL);
213 // Pump messages posted by the sync core thread (which may end up
214 // posting on the IO thread).
215 MessageLoop::current()->RunAllPending();
216 io_thread_.Stop();
217 MessageLoop::current()->RunAllPending();
218 BrowserWithTestWindowTest::TearDown();
221 bool StartSyncService(const base::Closure& callback,
222 bool will_fail_association) {
223 if (sync_service_.get())
224 return false;
225 SigninManager* signin = SigninManagerFactory::GetForProfile(profile());
226 signin->SetAuthenticatedUsername("test_user");
227 ProfileSyncComponentsFactoryMock* factory =
228 new ProfileSyncComponentsFactoryMock();
229 sync_service_.reset(new TestProfileSyncService(
230 factory,
231 profile(),
232 signin,
233 ProfileSyncService::AUTO_START,
234 false,
235 callback));
237 // Register the session data type.
238 SessionDataTypeController *dtc = new SessionDataTypeController(factory,
239 profile(),
240 sync_service_.get());
241 sync_service_->RegisterDataTypeController(dtc);
243 model_associator_ =
244 new SessionModelAssociator(sync_service_.get(),
245 true /* setup_for_test */);
246 change_processor_ = new SessionChangeProcessor(
247 dtc, model_associator_,
248 true /* setup_for_test */);
249 EXPECT_CALL(*factory, CreateSessionSyncComponents(_, _)).
250 WillOnce(Return(ProfileSyncComponentsFactory::SyncComponents(
251 model_associator_, change_processor_)));
252 EXPECT_CALL(*factory, CreateDataTypeManager(_, _, _, _)).
253 WillOnce(ReturnNewDataTypeManager());
255 TokenServiceFactory::GetForProfile(profile())->IssueAuthTokenForTest(
256 GaiaConstants::kSyncService, "token");
257 sync_service_->Initialize();
258 MessageLoop::current()->Run();
259 return true;
262 content::TestBrowserThread io_thread_;
263 // Path used in testing.
264 ScopedTempDir temp_dir_;
265 SessionModelAssociator* model_associator_;
266 SessionChangeProcessor* change_processor_;
267 SessionID window_id_;
268 scoped_ptr<TestProfileSyncService> sync_service_;
269 const gfx::Rect window_bounds_;
270 bool notified_of_update_;
271 bool notified_of_refresh_;
272 content::NotificationRegistrar registrar_;
275 class CreateRootHelper {
276 public:
277 explicit CreateRootHelper(ProfileSyncServiceSessionTest* test)
278 : ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
279 base::Bind(&CreateRootHelper::CreateRootCallback,
280 base::Unretained(this), test))),
281 success_(false) {
284 virtual ~CreateRootHelper() {}
286 const base::Closure& callback() const { return callback_; }
287 bool success() { return success_; }
289 private:
290 void CreateRootCallback(ProfileSyncServiceSessionTest* test) {
291 success_ = syncer::TestUserShare::CreateRoot(
292 syncer::SESSIONS, test->sync_service()->GetUserShare());
295 base::Closure callback_;
296 bool success_;
299 // Test that we can write this machine's session to a node and retrieve it.
300 TEST_F(ProfileSyncServiceSessionTest, WriteSessionToNode) {
301 CreateRootHelper create_root(this);
302 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
303 ASSERT_TRUE(create_root.success());
305 // Check that the DataTypeController associated the models.
306 bool has_nodes;
307 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
308 ASSERT_TRUE(has_nodes);
309 std::string machine_tag = model_associator_->GetCurrentMachineTag();
310 int64 sync_id = model_associator_->GetSyncIdFromSessionTag(machine_tag);
311 ASSERT_NE(syncer::kInvalidId, sync_id);
313 // Check that we can get the correct session specifics back from the node.
314 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
315 syncer::ReadNode node(&trans);
316 ASSERT_EQ(syncer::BaseNode::INIT_OK,
317 node.InitByClientTagLookup(syncer::SESSIONS, machine_tag));
318 const sync_pb::SessionSpecifics& specifics(node.GetSessionSpecifics());
319 ASSERT_EQ(machine_tag, specifics.session_tag());
320 ASSERT_TRUE(specifics.has_header());
321 const sync_pb::SessionHeader& header_s = specifics.header();
322 ASSERT_TRUE(header_s.has_device_type());
323 ASSERT_EQ("TestSessionName", header_s.client_name());
324 ASSERT_EQ(0, header_s.window_size());
327 // Test that we can fill this machine's session, write it to a node,
328 // and then retrieve it.
329 // Disabled because this test fails occasionally: http://crbug.com/81104
330 TEST_F(ProfileSyncServiceSessionTest, DISABLED_WriteFilledSessionToNode) {
331 CreateRootHelper create_root(this);
332 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
333 ASSERT_TRUE(create_root.success());
335 // Check that the DataTypeController associated the models.
336 bool has_nodes;
337 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
338 ASSERT_TRUE(has_nodes);
339 AddTab(browser(), GURL("http://foo/1"));
340 NavigateAndCommitActiveTab(GURL("http://foo/2"));
341 AddTab(browser(), GURL("http://bar/1"));
342 NavigateAndCommitActiveTab(GURL("http://bar/2"));
344 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
345 ASSERT_TRUE(has_nodes);
346 std::string machine_tag = model_associator_->GetCurrentMachineTag();
347 int64 sync_id = model_associator_->GetSyncIdFromSessionTag(machine_tag);
348 ASSERT_NE(syncer::kInvalidId, sync_id);
350 // Check that this machine's data is not included in the foreign windows.
351 std::vector<const SyncedSession*> foreign_sessions;
352 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
353 ASSERT_EQ(foreign_sessions.size(), 0U);
355 // Get the tabs for this machine from the node and check that they were
356 // filled.
357 SessionModelAssociator::TabLinksMap tab_map = model_associator_->tab_map_;
358 ASSERT_EQ(2U, tab_map.size());
359 // Tabs are ordered by sessionid in tab_map, so should be able to traverse
360 // the tree based on order of tabs created
361 SessionModelAssociator::TabLinksMap::iterator iter = tab_map.begin();
362 ASSERT_EQ(2, iter->second->tab()->GetEntryCount());
363 ASSERT_EQ(GURL("http://foo/1"), iter->second->tab()->
364 GetEntryAtIndex(0)->GetVirtualURL());
365 ASSERT_EQ(GURL("http://foo/2"), iter->second->tab()->
366 GetEntryAtIndex(1)->GetVirtualURL());
367 iter++;
368 ASSERT_EQ(2, iter->second->tab()->GetEntryCount());
369 ASSERT_EQ(GURL("http://bar/1"), iter->second->tab()->
370 GetEntryAtIndex(0)->GetVirtualURL());
371 ASSERT_EQ(GURL("http://bar/2"), iter->second->tab()->
372 GetEntryAtIndex(1)->GetVirtualURL());
375 // Test that we fail on a failed model association.
376 TEST_F(ProfileSyncServiceSessionTest, FailModelAssociation) {
377 ASSERT_TRUE(StartSyncService(base::Closure(), true));
378 ASSERT_TRUE(sync_service_->HasUnrecoverableError());
381 // Write a foreign session to a node, and then retrieve it.
382 TEST_F(ProfileSyncServiceSessionTest, WriteForeignSessionToNode) {
383 CreateRootHelper create_root(this);
384 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
385 ASSERT_TRUE(create_root.success());
387 // Check that the DataTypeController associated the models.
388 bool has_nodes;
389 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
390 ASSERT_TRUE(has_nodes);
392 // Fill an instance of session specifics with a foreign session's data.
393 std::string tag = "tag1";
394 sync_pb::SessionSpecifics meta;
395 BuildSessionSpecifics(tag, &meta);
396 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
397 std::vector<SessionID::id_type> tab_list1(
398 tab_nums1, tab_nums1 + arraysize(tab_nums1));
399 AddWindowSpecifics(0, tab_list1, &meta);
400 std::vector<sync_pb::SessionSpecifics> tabs1;
401 tabs1.resize(tab_list1.size());
402 for (size_t i = 0; i < tab_list1.size(); ++i) {
403 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
406 // Update associator with the session's meta node containing one window.
407 model_associator_->AssociateForeignSpecifics(meta, base::Time());
408 // Add tabs for the window.
409 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
410 iter != tabs1.end(); ++iter) {
411 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
414 // Check that the foreign session was associated and retrieve the data.
415 std::vector<const SyncedSession*> foreign_sessions;
416 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
417 ASSERT_EQ(1U, foreign_sessions.size());
418 std::vector<std::vector<SessionID::id_type> > session_reference;
419 session_reference.push_back(tab_list1);
420 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
423 // Write a foreign session with one window to a node. Sync, then add a window.
424 // Sync, then add a third window. Close the two windows.
425 TEST_F(ProfileSyncServiceSessionTest, WriteForeignSessionToNodeThreeWindows) {
426 CreateRootHelper create_root(this);
427 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
428 ASSERT_TRUE(create_root.success());
430 // Build a foreign session with one window and four tabs.
431 std::string tag = "tag1";
432 sync_pb::SessionSpecifics meta;
433 BuildSessionSpecifics(tag, &meta);
434 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
435 std::vector<SessionID::id_type> tab_list1(
436 tab_nums1, tab_nums1 + arraysize(tab_nums1));
437 AddWindowSpecifics(0, tab_list1, &meta);
438 std::vector<sync_pb::SessionSpecifics> tabs1;
439 tabs1.resize(tab_list1.size());
440 for (size_t i = 0; i < tab_list1.size(); ++i) {
441 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
443 // Update associator with the session's meta node containing one window.
444 model_associator_->AssociateForeignSpecifics(meta, base::Time());
445 // Add tabs for first window.
446 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
447 iter != tabs1.end(); ++iter) {
448 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
451 // Verify first window
452 std::vector<const SyncedSession*> foreign_sessions;
453 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
454 std::vector<std::vector<SessionID::id_type> > session_reference;
455 session_reference.push_back(tab_list1);
456 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
458 // Add a second window.
459 SessionID::id_type tab_nums2[] = {7, 15, 18, 20};
460 std::vector<SessionID::id_type> tab_list2(
461 tab_nums2, tab_nums2 + arraysize(tab_nums2));
462 AddWindowSpecifics(1, tab_list2, &meta);
463 std::vector<sync_pb::SessionSpecifics> tabs2;
464 tabs2.resize(tab_list2.size());
465 for (size_t i = 0; i < tab_list2.size(); ++i) {
466 BuildTabSpecifics(tag, 0, tab_list2[i], &tabs2[i]);
468 // Update associator with the session's meta node containing two windows.
469 model_associator_->AssociateForeignSpecifics(meta, base::Time());
470 // Add tabs for second window.
471 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs2.begin();
472 iter != tabs2.end(); ++iter) {
473 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
476 // Verify the two windows.
477 foreign_sessions.clear();
478 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
479 ASSERT_EQ(1U, foreign_sessions.size());
480 session_reference.push_back(tab_list2);
481 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
483 // Add a third window.
484 SessionID::id_type tab_nums3[] = {8, 16, 19, 21};
485 std::vector<SessionID::id_type> tab_list3(
486 tab_nums3, tab_nums3 + arraysize(tab_nums3));
487 AddWindowSpecifics(2, tab_list3, &meta);
488 std::vector<sync_pb::SessionSpecifics> tabs3;
489 tabs3.resize(tab_list3.size());
490 for (size_t i = 0; i < tab_list3.size(); ++i) {
491 BuildTabSpecifics(tag, 0, tab_list3[i], &tabs3[i]);
493 // Update associator with the session's meta node containing three windows.
494 model_associator_->AssociateForeignSpecifics(meta, base::Time());
495 // Add tabs for third window.
496 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs3.begin();
497 iter != tabs3.end(); ++iter) {
498 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
501 // Verify the three windows
502 foreign_sessions.clear();
503 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
504 ASSERT_EQ(1U, foreign_sessions.size());
505 session_reference.push_back(tab_list3);
506 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
508 // Close third window (by clearing and then not adding it back).
509 meta.mutable_header()->clear_window();
510 AddWindowSpecifics(0, tab_list1, &meta);
511 AddWindowSpecifics(1, tab_list2, &meta);
512 // Update associator with just the meta node, now containing only two windows.
513 model_associator_->AssociateForeignSpecifics(meta, base::Time());
515 // Verify first two windows are still there.
516 foreign_sessions.clear();
517 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
518 ASSERT_EQ(1U, foreign_sessions.size());
519 session_reference.pop_back(); // Pop off the data for the third window.
520 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
522 // Close second window (by clearing and then not adding it back).
523 meta.mutable_header()->clear_window();
524 AddWindowSpecifics(0, tab_list1, &meta);
525 // Update associator with just the meta node, now containing only one windows.
526 model_associator_->AssociateForeignSpecifics(meta, base::Time());
528 // Verify first window is still there.
529 foreign_sessions.clear();
530 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
531 ASSERT_EQ(1U, foreign_sessions.size());
532 session_reference.pop_back(); // Pop off the data for the second window.
533 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
536 // Write a foreign session to a node, with the tabs arriving first, and then
537 // retrieve it.
538 TEST_F(ProfileSyncServiceSessionTest, WriteForeignSessionToNodeTabsFirst) {
539 CreateRootHelper create_root(this);
540 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
541 ASSERT_TRUE(create_root.success());
543 // Fill an instance of session specifics with a foreign session's data.
544 std::string tag = "tag1";
545 sync_pb::SessionSpecifics meta;
546 BuildSessionSpecifics(tag, &meta);
547 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
548 std::vector<SessionID::id_type> tab_list1(
549 tab_nums1, tab_nums1 + arraysize(tab_nums1));
550 AddWindowSpecifics(0, tab_list1, &meta);
551 std::vector<sync_pb::SessionSpecifics> tabs1;
552 tabs1.resize(tab_list1.size());
553 for (size_t i = 0; i < tab_list1.size(); ++i) {
554 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
557 // Add tabs for first window.
558 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
559 iter != tabs1.end(); ++iter) {
560 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
562 // Update associator with the session's meta node containing one window.
563 model_associator_->AssociateForeignSpecifics(meta, base::Time());
565 // Check that the foreign session was associated and retrieve the data.
566 std::vector<const SyncedSession*> foreign_sessions;
567 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
568 ASSERT_EQ(1U, foreign_sessions.size());
569 std::vector<std::vector<SessionID::id_type> > session_reference;
570 session_reference.push_back(tab_list1);
571 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
574 // Write a foreign session to a node with some tabs that never arrive.
575 TEST_F(ProfileSyncServiceSessionTest, WriteForeignSessionToNodeMissingTabs) {
576 CreateRootHelper create_root(this);
577 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
578 ASSERT_TRUE(create_root.success());
580 // Fill an instance of session specifics with a foreign session's data.
581 std::string tag = "tag1";
582 sync_pb::SessionSpecifics meta;
583 BuildSessionSpecifics(tag, &meta);
584 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
585 std::vector<SessionID::id_type> tab_list1(
586 tab_nums1, tab_nums1 + arraysize(tab_nums1));
587 AddWindowSpecifics(0, tab_list1, &meta);
588 std::vector<sync_pb::SessionSpecifics> tabs1;
589 tabs1.resize(tab_list1.size()); // First window has all the tabs
590 for (size_t i = 0; i < tab_list1.size(); ++i) {
591 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
593 // Add a second window, but this time only create two tab nodes, despite the
594 // window expecting four tabs.
595 SessionID::id_type tab_nums2[] = {7, 15, 18, 20};
596 std::vector<SessionID::id_type> tab_list2(
597 tab_nums2, tab_nums2 + arraysize(tab_nums2));
598 AddWindowSpecifics(1, tab_list2, &meta);
599 std::vector<sync_pb::SessionSpecifics> tabs2;
600 tabs2.resize(2);
601 for (size_t i = 0; i < 2; ++i) {
602 BuildTabSpecifics(tag, 0, tab_list2[i], &tabs2[i]);
605 // Update associator with the session's meta node containing two windows.
606 model_associator_->AssociateForeignSpecifics(meta, base::Time());
607 // Add tabs for first window.
608 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
609 iter != tabs1.end(); ++iter) {
610 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
612 // Add tabs for second window.
613 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs2.begin();
614 iter != tabs2.end(); ++iter) {
615 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
618 // Check that the foreign session was associated and retrieve the data.
619 std::vector<const SyncedSession*> foreign_sessions;
620 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
621 ASSERT_EQ(1U, foreign_sessions.size());
622 ASSERT_EQ(2U, foreign_sessions[0]->windows.size());
623 ASSERT_EQ(4U, foreign_sessions[0]->windows.find(0)->second->tabs.size());
624 ASSERT_EQ(4U, foreign_sessions[0]->windows.find(1)->second->tabs.size());
626 // Close the second window.
627 meta.mutable_header()->clear_window();
628 AddWindowSpecifics(0, tab_list1, &meta);
630 // Update associator with the session's meta node containing one window.
631 model_associator_->AssociateForeignSpecifics(meta, base::Time());
633 // Check that the foreign session was associated and retrieve the data.
634 foreign_sessions.clear();
635 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
636 ASSERT_EQ(1U, foreign_sessions.size());
637 ASSERT_EQ(1U, foreign_sessions[0]->windows.size());
638 std::vector<std::vector<SessionID::id_type> > session_reference;
639 session_reference.push_back(tab_list1);
640 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
643 // Test the DataTypeController on update.
644 TEST_F(ProfileSyncServiceSessionTest, UpdatedSyncNodeActionUpdate) {
645 CreateRootHelper create_root(this);
646 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
647 ASSERT_TRUE(create_root.success());
648 int64 node_id = model_associator_->GetSyncIdFromSessionTag(
649 model_associator_->GetCurrentMachineTag());
650 ASSERT_FALSE(notified_of_update_);
652 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
653 change_processor_->ApplyChangesFromSyncModel(
654 &trans, 0,
655 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
656 node_id, ChangeRecord::ACTION_UPDATE));
658 ASSERT_TRUE(notified_of_update_);
661 // Test the DataTypeController on add.
662 TEST_F(ProfileSyncServiceSessionTest, UpdatedSyncNodeActionAdd) {
663 CreateRootHelper create_root(this);
664 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
665 ASSERT_TRUE(create_root.success());
667 int64 node_id = model_associator_->GetSyncIdFromSessionTag(
668 model_associator_->GetCurrentMachineTag());
669 ASSERT_FALSE(notified_of_update_);
671 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
672 change_processor_->ApplyChangesFromSyncModel(
673 &trans, 0,
674 ProfileSyncServiceTestHelper::MakeSingletonChangeRecordList(
675 node_id, ChangeRecord::ACTION_ADD));
677 ASSERT_TRUE(notified_of_update_);
680 // Test the DataTypeController on delete.
681 TEST_F(ProfileSyncServiceSessionTest, UpdatedSyncNodeActionDelete) {
682 CreateRootHelper create_root(this);
683 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
684 ASSERT_TRUE(create_root.success());
686 int64 node_id = model_associator_->GetSyncIdFromSessionTag(
687 model_associator_->GetCurrentMachineTag());
688 sync_pb::EntitySpecifics deleted_specifics;
689 deleted_specifics.mutable_session()->set_session_tag("tag");
690 ASSERT_FALSE(notified_of_update_);
692 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
693 change_processor_->ApplyChangesFromSyncModel(
694 &trans, 0,
695 ProfileSyncServiceTestHelper::MakeSingletonDeletionChangeRecordList(
696 node_id, deleted_specifics));
698 ASSERT_TRUE(notified_of_update_);
700 // Test the TabNodePool when it starts off empty.
701 TEST_F(ProfileSyncServiceSessionTest, TabNodePoolEmpty) {
702 CreateRootHelper create_root(this);
703 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
704 ASSERT_TRUE(create_root.success());
706 std::vector<int64> node_ids;
707 ASSERT_EQ(0U, model_associator_->tab_pool_.capacity());
708 ASSERT_TRUE(model_associator_->tab_pool_.empty());
709 ASSERT_TRUE(model_associator_->tab_pool_.full());
710 const size_t num_ids = 10;
711 for (size_t i = 0; i < num_ids; ++i) {
712 int64 id = model_associator_->tab_pool_.GetFreeTabNode();
713 ASSERT_GT(id, -1);
714 node_ids.push_back(id);
716 ASSERT_EQ(num_ids, model_associator_->tab_pool_.capacity());
717 ASSERT_TRUE(model_associator_->tab_pool_.empty());
718 ASSERT_FALSE(model_associator_->tab_pool_.full());
719 for (size_t i = 0; i < num_ids; ++i) {
720 model_associator_->tab_pool_.FreeTabNode(node_ids[i]);
722 ASSERT_EQ(num_ids, model_associator_->tab_pool_.capacity());
723 ASSERT_FALSE(model_associator_->tab_pool_.empty());
724 ASSERT_TRUE(model_associator_->tab_pool_.full());
727 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
728 // Test the TabNodePool when it starts off with nodes
729 TEST_F(ProfileSyncServiceSessionTest, DISABLED_TabNodePoolNonEmpty) {
730 CreateRootHelper create_root(this);
731 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
732 ASSERT_TRUE(create_root.success());
734 const size_t num_starting_nodes = 3;
735 for (size_t i = 0; i < num_starting_nodes; ++i) {
736 model_associator_->tab_pool_.AddTabNode(i);
739 std::vector<int64> node_ids;
740 ASSERT_EQ(num_starting_nodes, model_associator_->tab_pool_.capacity());
741 ASSERT_FALSE(model_associator_->tab_pool_.empty());
742 ASSERT_TRUE(model_associator_->tab_pool_.full());
743 const size_t num_ids = 10;
744 for (size_t i = 0; i < num_ids; ++i) {
745 int64 id = model_associator_->tab_pool_.GetFreeTabNode();
746 ASSERT_GT(id, -1);
747 node_ids.push_back(id);
749 ASSERT_EQ(num_ids, model_associator_->tab_pool_.capacity());
750 ASSERT_TRUE(model_associator_->tab_pool_.empty());
751 ASSERT_FALSE(model_associator_->tab_pool_.full());
752 for (size_t i = 0; i < num_ids; ++i) {
753 model_associator_->tab_pool_.FreeTabNode(node_ids[i]);
755 ASSERT_EQ(num_ids, model_associator_->tab_pool_.capacity());
756 ASSERT_FALSE(model_associator_->tab_pool_.empty());
757 ASSERT_TRUE(model_associator_->tab_pool_.full());
760 // Write a foreign session to a node, and then delete it.
761 TEST_F(ProfileSyncServiceSessionTest, DeleteForeignSession) {
762 CreateRootHelper create_root(this);
763 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
764 ASSERT_TRUE(create_root.success());
766 // Check that the DataTypeController associated the models.
767 bool has_nodes;
768 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
769 ASSERT_TRUE(has_nodes);
771 // A foreign session's tag.
772 std::string tag = "tag1";
774 // Should do nothing if the foreign session doesn't exist.
775 std::vector<const SyncedSession*> foreign_sessions;
776 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
777 model_associator_->DeleteForeignSession(tag);
778 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
780 // Fill an instance of session specifics with a foreign session's data.
781 sync_pb::SessionSpecifics meta;
782 BuildSessionSpecifics(tag, &meta);
783 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
784 std::vector<SessionID::id_type> tab_list1(
785 tab_nums1, tab_nums1 + arraysize(tab_nums1));
786 AddWindowSpecifics(0, tab_list1, &meta);
787 std::vector<sync_pb::SessionSpecifics> tabs1;
788 tabs1.resize(tab_list1.size());
789 for (size_t i = 0; i < tab_list1.size(); ++i) {
790 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
793 // Update associator with the session's meta node containing one window.
794 model_associator_->AssociateForeignSpecifics(meta, base::Time());
795 // Add tabs for the window.
796 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
797 iter != tabs1.end(); ++iter) {
798 model_associator_->AssociateForeignSpecifics(*iter, base::Time());
801 // Check that the foreign session was associated and retrieve the data.
802 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
803 ASSERT_EQ(1U, foreign_sessions.size());
804 std::vector<std::vector<SessionID::id_type> > session_reference;
805 session_reference.push_back(tab_list1);
806 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
808 // Now delete the foreign session.
809 model_associator_->DeleteForeignSession(tag);
810 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
813 // Associate both a non-stale foreign session and a stale foreign session.
814 // Ensure only the stale session gets deleted.
815 TEST_F(ProfileSyncServiceSessionTest, DeleteStaleSessions) {
816 CreateRootHelper create_root(this);
817 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
818 ASSERT_TRUE(create_root.success());
820 // Fill two instances of session specifics with a foreign session's data.
821 std::string tag = "tag1";
822 sync_pb::SessionSpecifics meta;
823 BuildSessionSpecifics(tag, &meta);
824 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
825 std::vector<SessionID::id_type> tab_list1(
826 tab_nums1, tab_nums1 + arraysize(tab_nums1));
827 AddWindowSpecifics(0, tab_list1, &meta);
828 std::vector<sync_pb::SessionSpecifics> tabs1;
829 tabs1.resize(tab_list1.size());
830 for (size_t i = 0; i < tab_list1.size(); ++i) {
831 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
833 std::string tag2 = "tag2";
834 sync_pb::SessionSpecifics meta2;
835 BuildSessionSpecifics(tag2, &meta2);
836 SessionID::id_type tab_nums2[] = {8, 15, 18, 20};
837 std::vector<SessionID::id_type> tab_list2(
838 tab_nums2, tab_nums2 + arraysize(tab_nums2));
839 AddWindowSpecifics(0, tab_list2, &meta2);
840 std::vector<sync_pb::SessionSpecifics> tabs2;
841 tabs2.resize(tab_list2.size());
842 for (size_t i = 0; i < tab_list2.size(); ++i) {
843 BuildTabSpecifics(tag2, 0, tab_list2[i], &tabs2[i]);
846 // Set the modification time for tag1 to be 21 days ago, tag2 to 5 days ago.
847 base::Time tag1_time = base::Time::Now() - base::TimeDelta::FromDays(21);
848 base::Time tag2_time = base::Time::Now() - base::TimeDelta::FromDays(5);
850 // Associate specifics.
851 model_associator_->AssociateForeignSpecifics(meta, tag1_time);
852 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
853 iter != tabs1.end(); ++iter) {
854 model_associator_->AssociateForeignSpecifics(*iter, tag1_time);
856 model_associator_->AssociateForeignSpecifics(meta2, tag2_time);
857 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs2.begin();
858 iter != tabs2.end(); ++iter) {
859 model_associator_->AssociateForeignSpecifics(*iter, tag2_time);
862 // Check that the foreign session was associated and retrieve the data.
863 std::vector<const SyncedSession*> foreign_sessions;
864 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
865 ASSERT_EQ(2U, foreign_sessions.size());
867 // Now delete the stale session and verify the non-stale one is still there.
868 model_associator_->DeleteStaleSessions();
869 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
870 ASSERT_EQ(1U, foreign_sessions.size());
871 std::vector<std::vector<SessionID::id_type> > session_reference;
872 session_reference.push_back(tab_list2);
873 VerifySyncedSession(tag2, session_reference, *(foreign_sessions[0]));
876 // Write a stale foreign session to a node. Then update one of its tabs so
877 // the session is no longer stale. Ensure it doesn't get deleted.
878 TEST_F(ProfileSyncServiceSessionTest, StaleSessionRefresh) {
879 CreateRootHelper create_root(this);
880 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
881 ASSERT_TRUE(create_root.success());
883 std::string tag = "tag1";
884 sync_pb::SessionSpecifics meta;
885 BuildSessionSpecifics(tag, &meta);
886 SessionID::id_type tab_nums1[] = {5, 10, 13, 17};
887 std::vector<SessionID::id_type> tab_list1(
888 tab_nums1, tab_nums1 + arraysize(tab_nums1));
889 AddWindowSpecifics(0, tab_list1, &meta);
890 std::vector<sync_pb::SessionSpecifics> tabs1;
891 tabs1.resize(tab_list1.size());
892 for (size_t i = 0; i < tab_list1.size(); ++i) {
893 BuildTabSpecifics(tag, 0, tab_list1[i], &tabs1[i]);
896 // Associate.
897 base::Time stale_time = base::Time::Now() - base::TimeDelta::FromDays(21);
898 model_associator_->AssociateForeignSpecifics(meta, stale_time);
899 for (std::vector<sync_pb::SessionSpecifics>::iterator iter = tabs1.begin();
900 iter != tabs1.end(); ++iter) {
901 model_associator_->AssociateForeignSpecifics(*iter, stale_time);
904 // Associate one of the tabs with a non-stale time.
905 model_associator_->AssociateForeignSpecifics(tabs1[0], base::Time::Now());
907 // Check that the foreign session was associated and retrieve the data.
908 std::vector<const SyncedSession*> foreign_sessions;
909 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
910 ASSERT_EQ(1U, foreign_sessions.size());
912 // Verify the now non-stale session does not get deleted.
913 model_associator_->DeleteStaleSessions();
914 ASSERT_TRUE(model_associator_->GetAllForeignSessions(&foreign_sessions));
915 ASSERT_EQ(1U, foreign_sessions.size());
916 std::vector<std::vector<SessionID::id_type> > session_reference;
917 session_reference.push_back(tab_list1);
918 VerifySyncedSession(tag, session_reference, *(foreign_sessions[0]));
921 // Test that tabs with nothing but "chrome://*" and "file://*" navigations are
922 // not be synced.
923 // This test is crashing occasionally: http://crbug.com/116097
924 TEST_F(ProfileSyncServiceSessionTest, DISABLED_ValidTabs) {
925 CreateRootHelper create_root(this);
926 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
927 ASSERT_TRUE(create_root.success());
929 AddTab(browser(), GURL("chrome://bla1/"));
930 NavigateAndCommitActiveTab(GURL("chrome://bla2"));
931 AddTab(browser(), GURL("file://bla3/"));
932 AddTab(browser(), GURL("bla://bla"));
933 // Note: chrome://newtab has special handling which crashes in unit tests.
935 // Get the tabs for this machine. Only the bla:// url should be synced.
936 SessionModelAssociator::TabLinksMap tab_map = model_associator_->tab_map_;
937 ASSERT_EQ(1U, tab_map.size());
938 SessionModelAssociator::TabLinksMap::iterator iter = tab_map.begin();
939 ASSERT_EQ(1, iter->second->tab()->GetEntryCount());
940 ASSERT_EQ(GURL("bla://bla"), iter->second->tab()->
941 GetEntryAtIndex(0)->GetVirtualURL());
944 // Verify that AttemptSessionsDataRefresh triggers the
945 // NOTIFICATION_SYNC_REFRESH_LOCAL notification.
946 // TODO(zea): Once we can have unit tests that are able to open to the NTP,
947 // test that the NTP/#opentabs URL triggers a refresh as well (but only when
948 // it is the active tab).
949 TEST_F(ProfileSyncServiceSessionTest, SessionsRefresh) {
950 CreateRootHelper create_root(this);
951 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
952 ASSERT_TRUE(create_root.success());
954 // Empty, so returns false.
955 std::vector<const SyncedSession*> foreign_sessions;
956 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
957 ASSERT_FALSE(notified_of_refresh_);
958 model_associator_->AttemptSessionsDataRefresh();
959 ASSERT_TRUE(notified_of_refresh_);
961 // Nothing should have changed since we don't have unapplied data.
962 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
965 // Ensure model association associates the pre-existing tabs.
966 // TODO(jhorwich): Fix the test so that it doesn't crash (crbug.com/121487)
967 TEST_F(ProfileSyncServiceSessionTest, DISABLED_ExistingTabs) {
968 AddTab(browser(), GURL("http://foo1"));
969 NavigateAndCommitActiveTab(GURL("http://foo2"));
970 AddTab(browser(), GURL("http://bar1"));
971 NavigateAndCommitActiveTab(GURL("http://bar2"));
973 CreateRootHelper create_root(this);
974 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
975 ASSERT_TRUE(create_root.success());
976 bool has_nodes;
977 ASSERT_TRUE(model_associator_->SyncModelHasUserCreatedNodes(&has_nodes));
978 ASSERT_TRUE(has_nodes);
980 std::string machine_tag = model_associator_->GetCurrentMachineTag();
981 int64 sync_id = model_associator_->GetSyncIdFromSessionTag(machine_tag);
982 ASSERT_NE(syncer::kInvalidId, sync_id);
984 // Check that this machine's data is not included in the foreign windows.
985 std::vector<const SyncedSession*> foreign_sessions;
986 ASSERT_FALSE(model_associator_->GetAllForeignSessions(&foreign_sessions));
987 ASSERT_EQ(foreign_sessions.size(), 0U);
989 // Get the tabs for this machine from the node and check that they were
990 // filled.
991 SessionModelAssociator::TabLinksMap tab_map = model_associator_->tab_map_;
992 ASSERT_EQ(2U, tab_map.size());
993 // Tabs are ordered by sessionid in tab_map, so should be able to traverse
994 // the tree based on order of tabs created
995 SessionModelAssociator::TabLinksMap::iterator iter = tab_map.begin();
996 ASSERT_EQ(2, iter->second->tab()->GetEntryCount());
997 ASSERT_EQ(GURL("http://foo1"), iter->second->tab()->
998 GetEntryAtIndex(0)->GetVirtualURL());
999 ASSERT_EQ(GURL("http://foo2"), iter->second->tab()->
1000 GetEntryAtIndex(1)->GetVirtualURL());
1001 iter++;
1002 ASSERT_EQ(2, iter->second->tab()->GetEntryCount());
1003 ASSERT_EQ(GURL("http://bar1"), iter->second->tab()->
1004 GetEntryAtIndex(0)->GetVirtualURL());
1005 ASSERT_EQ(GURL("http://bar2"), iter->second->tab()->
1006 GetEntryAtIndex(1)->GetVirtualURL());
1009 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
1010 TEST_F(ProfileSyncServiceSessionTest, DISABLED_MissingHeaderAndTab) {
1011 AddTab(browser(), GURL("http://foo1"));
1012 NavigateAndCommitActiveTab(GURL("http://foo2"));
1013 AddTab(browser(), GURL("http://bar1"));
1014 NavigateAndCommitActiveTab(GURL("http://bar2"));
1015 CreateRootHelper create_root(this);
1016 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1017 syncer::SyncError error;
1018 std::string local_tag = model_associator_->GetCurrentMachineTag();
1020 error = model_associator_->DisassociateModels();
1021 ASSERT_FALSE(error.IsSet());
1023 // Create a sync node with the local tag but neither header nor tab field.
1024 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1025 syncer::ReadNode root(&trans);
1026 root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS));
1027 syncer::WriteNode extra_header(&trans);
1028 syncer::WriteNode::InitUniqueByCreationResult result =
1029 extra_header.InitUniqueByCreation(syncer::SESSIONS, root, "new_tag");
1030 ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
1031 sync_pb::SessionSpecifics specifics;
1032 specifics.set_session_tag(local_tag);
1033 extra_header.SetSessionSpecifics(specifics);
1036 error = model_associator_->AssociateModels(NULL, NULL);
1037 ASSERT_FALSE(error.IsSet());
1040 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
1041 TEST_F(ProfileSyncServiceSessionTest, DISABLED_MultipleHeaders) {
1042 AddTab(browser(), GURL("http://foo1"));
1043 NavigateAndCommitActiveTab(GURL("http://foo2"));
1044 AddTab(browser(), GURL("http://bar1"));
1045 NavigateAndCommitActiveTab(GURL("http://bar2"));
1046 CreateRootHelper create_root(this);
1047 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1048 syncer::SyncError error;
1049 std::string local_tag = model_associator_->GetCurrentMachineTag();
1051 error = model_associator_->DisassociateModels();
1052 ASSERT_FALSE(error.IsSet());
1054 // Create another sync node with a header field and the local tag.
1055 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1056 syncer::ReadNode root(&trans);
1057 root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS));
1058 syncer::WriteNode extra_header(&trans);
1059 syncer::WriteNode::InitUniqueByCreationResult result =
1060 extra_header.InitUniqueByCreation(syncer::SESSIONS,
1061 root, local_tag + "_");
1062 ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
1063 sync_pb::SessionSpecifics specifics;
1064 specifics.set_session_tag(local_tag);
1065 specifics.mutable_header();
1066 extra_header.SetSessionSpecifics(specifics);
1068 error = model_associator_->AssociateModels(NULL, NULL);
1069 ASSERT_FALSE(error.IsSet());
1072 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
1073 TEST_F(ProfileSyncServiceSessionTest, DISABLED_CorruptedForeign) {
1074 AddTab(browser(), GURL("http://foo1"));
1075 NavigateAndCommitActiveTab(GURL("http://foo2"));
1076 AddTab(browser(), GURL("http://bar1"));
1077 NavigateAndCommitActiveTab(GURL("http://bar2"));
1078 CreateRootHelper create_root(this);
1079 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1080 syncer::SyncError error;
1082 error = model_associator_->DisassociateModels();
1083 ASSERT_FALSE(error.IsSet());
1085 // Create another sync node with neither header nor tab field and a foreign
1086 // tag.
1087 std::string foreign_tag = "foreign_tag";
1088 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1089 syncer::ReadNode root(&trans);
1090 root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS));
1091 syncer::WriteNode extra_header(&trans);
1092 syncer::WriteNode::InitUniqueByCreationResult result =
1093 extra_header.InitUniqueByCreation(syncer::SESSIONS,
1094 root, foreign_tag);
1095 ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
1096 sync_pb::SessionSpecifics specifics;
1097 specifics.set_session_tag(foreign_tag);
1098 extra_header.SetSessionSpecifics(specifics);
1100 error = model_associator_->AssociateModels(NULL, NULL);
1101 ASSERT_FALSE(error.IsSet());
1104 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
1105 TEST_F(ProfileSyncServiceSessionTest, DISABLED_MissingLocalTabNode) {
1106 AddTab(browser(), GURL("http://foo1"));
1107 NavigateAndCommitActiveTab(GURL("http://foo2"));
1108 AddTab(browser(), GURL("http://bar1"));
1109 NavigateAndCommitActiveTab(GURL("http://bar2"));
1110 CreateRootHelper create_root(this);
1111 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1112 std::string local_tag = model_associator_->GetCurrentMachineTag();
1113 syncer::SyncError error;
1115 error = model_associator_->DisassociateModels();
1116 ASSERT_FALSE(error.IsSet());
1118 // Delete the first sync tab node.
1119 std::string tab_tag = SessionModelAssociator::TabIdToTag(local_tag, 0);
1121 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1122 syncer::ReadNode root(&trans);
1123 root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS));
1124 syncer::WriteNode tab_node(&trans);
1125 ASSERT_TRUE(tab_node.InitByClientTagLookup(syncer::SESSIONS, tab_tag));
1126 tab_node.Remove();
1128 error = model_associator_->AssociateModels(NULL, NULL);
1129 ASSERT_FALSE(error.IsSet());
1131 // Add some more tabs to ensure we don't conflict with the pre-existing tab
1132 // node.
1133 AddTab(browser(), GURL("http://baz1"));
1134 AddTab(browser(), GURL("http://baz2"));
1137 TEST_F(ProfileSyncServiceSessionTest, Favicons) {
1138 CreateRootHelper create_root(this);
1139 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1140 ASSERT_TRUE(create_root.success());
1142 // Build a foreign session with one window and one tab.
1143 std::string tag = "tag1";
1144 sync_pb::SessionSpecifics meta;
1145 BuildSessionSpecifics(tag, &meta);
1146 std::vector<SessionID::id_type> tab_list;
1147 tab_list.push_back(5);
1148 AddWindowSpecifics(0, tab_list, &meta);
1149 sync_pb::SessionSpecifics tab;
1150 BuildTabSpecifics(tag, 0, tab_list[0], &tab);
1151 std::string url = tab.tab().navigation(0).virtual_url();
1152 std::string favicon;
1154 // Update associator.
1155 model_associator_->AssociateForeignSpecifics(meta, base::Time());
1156 model_associator_->AssociateForeignSpecifics(tab, base::Time());
1157 ASSERT_FALSE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
1159 // Now add a favicon.
1160 tab.mutable_tab()->set_favicon_source("http://favicon_source.com/png.ico");
1161 tab.mutable_tab()->set_favicon_type(sync_pb::SessionTab::TYPE_WEB_FAVICON);
1162 tab.mutable_tab()->set_favicon("data");
1163 model_associator_->AssociateForeignSpecifics(tab, base::Time());
1164 ASSERT_TRUE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
1165 ASSERT_EQ("data", favicon);
1167 // Simulate navigating away. The associator should delete the favicon.
1168 tab.mutable_tab()->clear_navigation();
1169 tab.mutable_tab()->add_navigation()->set_virtual_url("http://new_url.com");
1170 tab.mutable_tab()->clear_favicon_source();
1171 tab.mutable_tab()->clear_favicon_type();
1172 tab.mutable_tab()->clear_favicon();
1173 model_associator_->AssociateForeignSpecifics(tab, base::Time());
1174 ASSERT_FALSE(model_associator_->GetSyncedFaviconForPageURL(url, &favicon));
1177 // TODO(jhorwich): Re-enable when crbug.com/121487 addressed
1178 TEST_F(ProfileSyncServiceSessionTest, DISABLED_CorruptedLocalHeader) {
1179 AddTab(browser(), GURL("http://foo1"));
1180 NavigateAndCommitActiveTab(GURL("http://foo2"));
1181 AddTab(browser(), GURL("http://bar1"));
1182 NavigateAndCommitActiveTab(GURL("http://bar2"));
1183 CreateRootHelper create_root(this);
1184 ASSERT_TRUE(StartSyncService(create_root.callback(), false));
1185 std::string local_tag = model_associator_->GetCurrentMachineTag();
1186 syncer::SyncError error;
1188 error = model_associator_->DisassociateModels();
1189 ASSERT_FALSE(error.IsSet());
1191 // Load the header node and clear it.
1192 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
1193 syncer::WriteNode header(&trans);
1194 ASSERT_EQ(syncer::BaseNode::INIT_OK,
1195 header.InitByClientTagLookup(syncer::SESSIONS, local_tag));
1196 sync_pb::SessionSpecifics specifics;
1197 header.SetSessionSpecifics(specifics);
1199 // Ensure we associate properly despite the pre-existing node with our local
1200 // tag.
1201 error = model_associator_->AssociateModels(NULL, NULL);
1202 ASSERT_FALSE(error.IsSet());
1205 } // namespace browser_sync