1 // Copyright 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 "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
10 #include "base/command_line.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/sessions/chrome_tab_restore_service_client.h"
15 #include "chrome/browser/sessions/persistent_tab_restore_service.h"
16 #include "chrome/browser/sessions/session_service.h"
17 #include "chrome/browser/sessions/session_service_factory.h"
18 #include "chrome/browser/sessions/tab_restore_service_factory.h"
19 #include "chrome/browser/sync/profile_sync_service_mock.h"
20 #include "chrome/browser/sync/sessions/sessions_sync_manager.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_tabstrip.h"
23 #include "chrome/browser/ui/sync/browser_synced_window_delegates_getter.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/test/base/browser_with_test_window_test.h"
28 #include "chrome/test/base/menu_model_test.h"
29 #include "chrome/test/base/testing_profile.h"
30 #include "components/sessions/serialized_navigation_entry_test_helper.h"
31 #include "components/sessions/session_types.h"
32 #include "components/sync_driver/glue/synced_session.h"
33 #include "components/sync_driver/local_device_info_provider_mock.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/test/test_utils.h"
36 #include "grit/generated_resources.h"
37 #include "sync/api/fake_sync_change_processor.h"
38 #include "sync/api/sync_error_factory_mock.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/gtest/include/gtest/gtest.h"
44 // This copies parts of MenuModelTest::Delegate and combines them with the
45 // RecentTabsSubMenuModel since RecentTabsSubMenuModel is a
46 // SimpleMenuModel::Delegate and not just derived from SimpleMenuModel.
47 class TestRecentTabsSubMenuModel
: public RecentTabsSubMenuModel
{
49 TestRecentTabsSubMenuModel(ui::AcceleratorProvider
* provider
,
51 sync_driver::OpenTabsUIDelegate
* delegate
)
52 : RecentTabsSubMenuModel(provider
, browser
, delegate
),
56 // Testing overrides to ui::SimpleMenuModel::Delegate:
57 bool IsCommandIdEnabled(int command_id
) const override
{
58 bool val
= RecentTabsSubMenuModel::IsCommandIdEnabled(command_id
);
64 void ExecuteCommand(int command_id
, int event_flags
) override
{
68 int execute_count() const { return execute_count_
; }
69 int enable_count() const { return enable_count_
; }
73 int mutable enable_count_
; // Mutable because IsCommandIdEnabledAt is const.
75 DISALLOW_COPY_AND_ASSIGN(TestRecentTabsSubMenuModel
);
78 class TestRecentTabsMenuModelDelegate
: public ui::MenuModelDelegate
{
80 explicit TestRecentTabsMenuModelDelegate(ui::MenuModel
* model
)
83 model_
->SetMenuModelDelegate(this);
86 ~TestRecentTabsMenuModelDelegate() override
{
87 model_
->SetMenuModelDelegate(NULL
);
90 // ui::MenuModelDelegate implementation:
92 void OnIconChanged(int index
) override
{}
94 void OnMenuStructureChanged() override
{ got_changes_
= true; }
96 bool got_changes() const { return got_changes_
; }
99 ui::MenuModel
* model_
;
102 DISALLOW_COPY_AND_ASSIGN(TestRecentTabsMenuModelDelegate
);
105 class DummyRouter
: public browser_sync::LocalSessionEventRouter
{
107 ~DummyRouter() override
{}
109 browser_sync::LocalSessionEventHandler
* handler
) override
{}
110 void Stop() override
{}
115 class RecentTabsSubMenuModelTest
116 : public BrowserWithTestWindowTest
{
118 RecentTabsSubMenuModelTest()
119 : sync_service_(&testing_profile_
),
120 local_device_(new sync_driver::LocalDeviceInfoProviderMock(
121 "RecentTabsSubMenuModelTest",
125 sync_pb::SyncEnums_DeviceType_TYPE_LINUX
,
127 manager_
.reset(new browser_sync::SessionsSyncManager(
128 &testing_profile_
, local_device_
.get(),
129 scoped_ptr
<browser_sync::LocalSessionEventRouter
>(new DummyRouter()),
130 scoped_ptr
<browser_sync::SyncedWindowDelegatesGetter
>(
131 new browser_sync::BrowserSyncedWindowDelegatesGetter())));
132 manager_
->MergeDataAndStartSyncing(
134 syncer::SyncDataList(),
135 scoped_ptr
<syncer::SyncChangeProcessor
>(
136 new syncer::FakeSyncChangeProcessor
),
137 scoped_ptr
<syncer::SyncErrorFactory
>(
138 new syncer::SyncErrorFactoryMock
));
141 void WaitForLoadFromLastSession() {
142 content::RunAllBlockingPoolTasksUntilIdle();
145 static scoped_ptr
<KeyedService
> GetTabRestoreService(
146 content::BrowserContext
* browser_context
) {
147 return make_scoped_ptr(new PersistentTabRestoreService(
148 Profile::FromBrowserContext(browser_context
),
149 make_scoped_ptr(new ChromeTabRestoreServiceClient(
150 Profile::FromBrowserContext(browser_context
))),
154 sync_driver::OpenTabsUIDelegate
* GetOpenTabsDelegate() {
155 return manager_
.get();
158 void RegisterRecentTabs(RecentTabsBuilderTestHelper
* helper
) {
159 helper
->ExportToSessionsSyncManager(manager_
.get());
163 TestingProfile testing_profile_
;
164 testing::NiceMock
<ProfileSyncServiceMock
> sync_service_
;
166 scoped_ptr
<browser_sync::SessionsSyncManager
> manager_
;
167 scoped_ptr
<sync_driver::LocalDeviceInfoProviderMock
> local_device_
;
170 // Test disabled "Recently closed" header with no foreign tabs.
171 TEST_F(RecentTabsSubMenuModelTest
, NoTabs
) {
172 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
175 // Menu index Menu items
176 // ---------------------------------------------
179 // 2 Recently closed header (disabled)
181 // 4 No tabs from other Devices
183 int num_items
= model
.GetItemCount();
184 EXPECT_EQ(5, num_items
);
185 EXPECT_FALSE(model
.IsEnabledAt(2));
186 EXPECT_FALSE(model
.IsEnabledAt(4));
187 EXPECT_EQ(0, model
.enable_count());
189 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
190 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
191 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
192 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
193 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
196 base::string16 title
;
197 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
198 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
199 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
200 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
201 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
204 // Test enabled "Recently closed" header with no foreign tabs.
205 TEST_F(RecentTabsSubMenuModelTest
, RecentlyClosedTabsFromCurrentSession
) {
206 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
207 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
209 // Add 2 tabs and close them.
210 AddTab(browser(), GURL("http://foo/1"));
211 AddTab(browser(), GURL("http://foo/2"));
212 browser()->tab_strip_model()->CloseAllTabs();
214 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
216 // Menu index Menu items
217 // --------------------------------------
220 // 2 Recently closed header
221 // 3 <tab for http://foo/2>
222 // 4 <tab for http://foo/1>
224 // 6 No tabs from other Devices
225 int num_items
= model
.GetItemCount();
226 EXPECT_EQ(7, num_items
);
227 EXPECT_TRUE(model
.IsEnabledAt(0));
228 model
.ActivatedAt(0);
229 EXPECT_TRUE(model
.IsEnabledAt(1));
230 EXPECT_FALSE(model
.IsEnabledAt(2));
231 EXPECT_TRUE(model
.IsEnabledAt(3));
232 EXPECT_TRUE(model
.IsEnabledAt(4));
233 model
.ActivatedAt(3);
234 model
.ActivatedAt(4);
235 EXPECT_FALSE(model
.IsEnabledAt(6));
236 EXPECT_EQ(3, model
.enable_count());
237 EXPECT_EQ(3, model
.execute_count());
239 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
240 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
241 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
242 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
243 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
244 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
245 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
248 base::string16 title
;
249 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
250 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
251 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
252 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
253 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
254 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
255 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
258 // TODO(sail): enable this test when dynamic model is enabled in
259 // RecentTabsSubMenuModel.
260 #if defined(OS_MACOSX)
261 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
262 DISABLED_RecentlyClosedTabsAndWindowsFromLastSession
264 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
265 RecentlyClosedTabsAndWindowsFromLastSession
267 TEST_F(RecentTabsSubMenuModelTest
,
268 MAYBE_RecentlyClosedTabsAndWindowsFromLastSession
) {
269 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
270 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
272 // Add 2 tabs and close them.
273 AddTab(browser(), GURL("http://wnd/tab0"));
274 AddTab(browser(), GURL("http://wnd/tab1"));
275 browser()->tab_strip_model()->CloseAllTabs();
277 // Create a SessionService for the profile (profile owns the service) and add
278 // a window with a tab to this session.
279 SessionService
* session_service
= new SessionService(profile());
280 SessionServiceFactory::SetForTestProfile(profile(),
281 make_scoped_ptr(session_service
));
284 session_service
->SetWindowType(window_id
,
285 Browser::TYPE_TABBED
,
286 SessionService::TYPE_NORMAL
);
287 session_service
->SetTabWindow(window_id
, tab_id
);
288 session_service
->SetTabIndexInWindow(window_id
, tab_id
, 0);
289 session_service
->SetSelectedTabInWindow(window_id
, 0);
290 session_service
->UpdateTabNavigation(
292 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
293 "http://wnd1/tab0", "title"));
294 // Set this, otherwise previous session won't be loaded.
295 profile()->set_last_session_exited_cleanly(false);
296 // Move this session to the last so that TabRestoreService will load it as the
298 SessionServiceFactory::GetForProfile(profile())->
299 MoveCurrentSessionToLastSession();
301 // Create a new TabRestoreService so that it'll load the recently closed tabs
302 // and windows afresh.
303 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
304 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
305 // Let the shutdown of previous TabRestoreService run.
306 content::RunAllBlockingPoolTasksUntilIdle();
308 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
309 TestRecentTabsMenuModelDelegate
delegate(&model
);
310 EXPECT_FALSE(delegate
.got_changes());
312 // Expected menu before tabs/windows from last session are loaded:
313 // Menu index Menu items
314 // ----------------------------------------------------------------
317 // 2 Recently closed header
319 // 4 No tabs from other Devices
321 int num_items
= model
.GetItemCount();
322 EXPECT_EQ(5, num_items
);
323 EXPECT_TRUE(model
.IsEnabledAt(0));
324 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
325 EXPECT_FALSE(model
.IsEnabledAt(2));
326 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(3));
327 EXPECT_FALSE(model
.IsEnabledAt(4));
328 EXPECT_EQ(1, model
.enable_count());
330 // Wait for tabs from last session to be loaded.
331 WaitForLoadFromLastSession();
333 // Expected menu after tabs/windows from last session are loaded:
334 // Menu index Menu items
335 // --------------------------------------------------------------
338 // 2 Recently closed header
339 // 3 <window for the tab http://wnd1/tab0>
340 // 4 <tab for http://wnd0/tab1>
341 // 5 <tab for http://wnd0/tab0>
343 // 7 No tabs from other Devices
345 EXPECT_TRUE(delegate
.got_changes());
347 num_items
= model
.GetItemCount();
348 EXPECT_EQ(8, num_items
);
350 EXPECT_TRUE(model
.IsEnabledAt(0));
351 model
.ActivatedAt(0);
352 EXPECT_TRUE(model
.IsEnabledAt(1));
353 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
354 EXPECT_FALSE(model
.IsEnabledAt(2));
355 EXPECT_TRUE(model
.IsEnabledAt(3));
356 EXPECT_TRUE(model
.IsEnabledAt(4));
357 EXPECT_TRUE(model
.IsEnabledAt(5));
358 model
.ActivatedAt(3);
359 model
.ActivatedAt(4);
360 model
.ActivatedAt(5);
361 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(6));
362 EXPECT_FALSE(model
.IsEnabledAt(7));
363 EXPECT_EQ(5, model
.enable_count());
364 EXPECT_EQ(4, model
.execute_count());
366 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
367 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
368 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
369 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
370 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
371 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
372 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
373 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
376 base::string16 title
;
377 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
378 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
379 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
380 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
381 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
382 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
383 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
384 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
387 // Test disabled "Recently closed" header with multiple sessions, multiple
388 // windows, and multiple enabled tabs from other devices.
389 TEST_F(RecentTabsSubMenuModelTest
, OtherDevices
) {
390 // Tabs are populated in decreasing timestamp.
391 base::Time timestamp
= base::Time::Now();
392 const base::TimeDelta time_delta
= base::TimeDelta::FromMinutes(10);
394 RecentTabsBuilderTestHelper recent_tabs_builder
;
396 // Create 1st session : 1 window, 3 tabs
397 recent_tabs_builder
.AddSession();
398 recent_tabs_builder
.AddWindow(0);
399 for (int i
= 0; i
< 3; ++i
) {
400 timestamp
-= time_delta
;
401 recent_tabs_builder
.AddTabWithInfo(0, 0, timestamp
, base::string16());
404 // Create 2nd session : 2 windows, 1 tab in 1st window, 2 tabs in 2nd window
405 recent_tabs_builder
.AddSession();
406 recent_tabs_builder
.AddWindow(1);
407 recent_tabs_builder
.AddWindow(1);
408 timestamp
-= time_delta
;
409 recent_tabs_builder
.AddTabWithInfo(1, 0, timestamp
, base::string16());
410 timestamp
-= time_delta
;
411 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
412 timestamp
-= time_delta
;
413 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
415 RegisterRecentTabs(&recent_tabs_builder
);
417 // Verify that data is populated correctly in RecentTabsSubMenuModel.
419 // - first inserted tab is most recent and hence is top
420 // Menu index Menu items
421 // -----------------------------------------------------
424 // 2 Recently closed header (disabled)
426 // 4 <section header for 1st session>
427 // 5-7 <3 tabs of the only window of session 0>
429 // 9 <section header for 2nd session>
430 // 10 <the only tab of window 0 of session 1>
431 // 11-12 <2 tabs of window 1 of session 2>
433 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
434 int num_items
= model
.GetItemCount();
435 EXPECT_EQ(13, num_items
);
436 model
.ActivatedAt(0);
437 EXPECT_TRUE(model
.IsEnabledAt(0));
438 model
.ActivatedAt(1);
439 EXPECT_TRUE(model
.IsEnabledAt(1));
440 model
.ActivatedAt(2);
441 EXPECT_FALSE(model
.IsEnabledAt(2));
442 model
.ActivatedAt(3);
443 EXPECT_TRUE(model
.IsEnabledAt(3));
444 model
.ActivatedAt(5);
445 EXPECT_TRUE(model
.IsEnabledAt(5));
446 model
.ActivatedAt(6);
447 EXPECT_TRUE(model
.IsEnabledAt(6));
448 model
.ActivatedAt(7);
449 EXPECT_TRUE(model
.IsEnabledAt(7));
450 model
.ActivatedAt(10);
451 EXPECT_TRUE(model
.IsEnabledAt(10));
452 model
.ActivatedAt(11);
453 EXPECT_TRUE(model
.IsEnabledAt(11));
454 model
.ActivatedAt(12);
455 EXPECT_TRUE(model
.IsEnabledAt(12));
457 EXPECT_EQ(7, model
.enable_count());
458 EXPECT_EQ(10, model
.execute_count());
460 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
461 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
462 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
463 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
464 EXPECT_TRUE(model
.GetLabelFontListAt(4) != nullptr);
465 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
466 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
467 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
468 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(8));
469 EXPECT_TRUE(model
.GetLabelFontListAt(9) != nullptr);
470 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(10));
471 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(11));
472 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(12));
475 base::string16 title
;
476 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
477 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
478 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
479 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
480 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
481 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
482 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
483 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
484 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(8, &url
, &title
));
485 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(9, &url
, &title
));
486 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(10, &url
, &title
));
487 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(11, &url
, &title
));
488 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(12, &url
, &title
));
491 TEST_F(RecentTabsSubMenuModelTest
, MaxSessionsAndRecency
) {
492 // Create 4 sessions : each session has 1 window with 1 tab each.
493 RecentTabsBuilderTestHelper recent_tabs_builder
;
494 for (int s
= 0; s
< 4; ++s
) {
495 recent_tabs_builder
.AddSession();
496 recent_tabs_builder
.AddWindow(s
);
497 recent_tabs_builder
.AddTab(s
, 0);
499 RegisterRecentTabs(&recent_tabs_builder
);
501 // Verify that data is populated correctly in RecentTabsSubMenuModel.
503 // - max sessions is 3, so only 3 most-recent sessions will show.
504 // Menu index Menu items
505 // ----------------------------------------------------------
508 // 2 Recently closed header (disabled)
510 // 4 <section header for 1st session>
511 // 5 <the only tab of the only window of session 3>
513 // 7 <section header for 2nd session>
514 // 8 <the only tab of the only window of session 2>
516 // 10 <section header for 3rd session>
517 // 11 <the only tab of the only window of session 1>
519 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
520 int num_items
= model
.GetItemCount();
521 EXPECT_EQ(12, num_items
);
523 std::vector
<base::string16
> tab_titles
=
524 recent_tabs_builder
.GetTabTitlesSortedByRecency();
525 EXPECT_EQ(tab_titles
[0], model
.GetLabelAt(5));
526 EXPECT_EQ(tab_titles
[1], model
.GetLabelAt(8));
527 EXPECT_EQ(tab_titles
[2], model
.GetLabelAt(11));
530 TEST_F(RecentTabsSubMenuModelTest
, MaxTabsPerSessionAndRecency
) {
531 // Create a session: 2 windows with 5 tabs each.
532 RecentTabsBuilderTestHelper recent_tabs_builder
;
533 recent_tabs_builder
.AddSession();
534 for (int w
= 0; w
< 2; ++w
) {
535 recent_tabs_builder
.AddWindow(0);
536 for (int t
= 0; t
< 5; ++t
)
537 recent_tabs_builder
.AddTab(0, w
);
539 RegisterRecentTabs(&recent_tabs_builder
);
541 // Verify that data is populated correctly in RecentTabsSubMenuModel.
543 // - max tabs per session is 4, so only 4 most-recent tabs will show,
544 // independent of which window they came from.
545 // Menu index Menu items
546 // ---------------------------------------------
549 // 2 Recently closed header (disabled)
551 // 4 <section header for session>
552 // 5-8 <4 most-recent tabs of session>
554 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
555 int num_items
= model
.GetItemCount();
556 EXPECT_EQ(9, num_items
);
558 std::vector
<base::string16
> tab_titles
=
559 recent_tabs_builder
.GetTabTitlesSortedByRecency();
560 for (int i
= 0; i
< 4; ++i
)
561 EXPECT_EQ(tab_titles
[i
], model
.GetLabelAt(i
+ 5));
564 TEST_F(RecentTabsSubMenuModelTest
, MaxWidth
) {
565 // Create 1 session with 1 window and 1 tab.
566 RecentTabsBuilderTestHelper recent_tabs_builder
;
567 recent_tabs_builder
.AddSession();
568 recent_tabs_builder
.AddWindow(0);
569 recent_tabs_builder
.AddTab(0, 0);
570 RegisterRecentTabs(&recent_tabs_builder
);
572 // Menu index Menu items
573 // ----------------------------------------------------------
576 // 2 Recently closed header (disabled)
578 // 4 <section header for 1st session>
579 // 5 <the only tab of the only window of session 1>
581 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
582 EXPECT_EQ(6, model
.GetItemCount());
583 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
584 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
585 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(4));
586 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(5));
589 TEST_F(RecentTabsSubMenuModelTest
, MaxWidthNoDevices
) {
591 // Menu index Menu items
592 // --------------------------------------------
595 // 2 Recently closed heaer (disabled)
597 // 4 No tabs from other Devices
599 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
600 EXPECT_EQ(5, model
.GetItemCount());
601 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
602 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
603 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(4));