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/session_service.h"
16 #include "chrome/browser/sessions/session_service_factory.h"
17 #include "chrome/browser/sessions/tab_restore_service_factory.h"
18 #include "chrome/browser/sync/profile_sync_service_mock.h"
19 #include "chrome/browser/sync/sessions/sessions_sync_manager.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_tabstrip.h"
22 #include "chrome/browser/ui/sync/browser_synced_window_delegates_getter.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/test/base/browser_with_test_window_test.h"
27 #include "chrome/test/base/menu_model_test.h"
28 #include "chrome/test/base/testing_profile.h"
29 #include "components/sessions/core/persistent_tab_restore_service.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 make_scoped_ptr(new ChromeTabRestoreServiceClient(
149 Profile::FromBrowserContext(browser_context
))),
153 sync_driver::OpenTabsUIDelegate
* GetOpenTabsDelegate() {
154 return manager_
.get();
157 void RegisterRecentTabs(RecentTabsBuilderTestHelper
* helper
) {
158 helper
->ExportToSessionsSyncManager(manager_
.get());
162 TestingProfile testing_profile_
;
163 testing::NiceMock
<ProfileSyncServiceMock
> sync_service_
;
165 scoped_ptr
<browser_sync::SessionsSyncManager
> manager_
;
166 scoped_ptr
<sync_driver::LocalDeviceInfoProviderMock
> local_device_
;
169 // Test disabled "Recently closed" header with no foreign tabs.
170 TEST_F(RecentTabsSubMenuModelTest
, NoTabs
) {
171 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
174 // Menu index Menu items
175 // ---------------------------------------------
178 // 2 Recently closed header (disabled)
180 // 4 No tabs from other Devices
182 int num_items
= model
.GetItemCount();
183 EXPECT_EQ(5, num_items
);
184 EXPECT_FALSE(model
.IsEnabledAt(2));
185 EXPECT_FALSE(model
.IsEnabledAt(4));
186 EXPECT_EQ(0, model
.enable_count());
188 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
189 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
190 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
191 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
192 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
195 base::string16 title
;
196 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
197 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
198 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
199 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
200 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
203 // Test enabled "Recently closed" header with no foreign tabs.
204 TEST_F(RecentTabsSubMenuModelTest
, RecentlyClosedTabsFromCurrentSession
) {
205 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
206 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
208 // Add 2 tabs and close them.
209 AddTab(browser(), GURL("http://foo/1"));
210 AddTab(browser(), GURL("http://foo/2"));
211 browser()->tab_strip_model()->CloseAllTabs();
213 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
215 // Menu index Menu items
216 // --------------------------------------
219 // 2 Recently closed header
220 // 3 <tab for http://foo/2>
221 // 4 <tab for http://foo/1>
223 // 6 No tabs from other Devices
224 int num_items
= model
.GetItemCount();
225 EXPECT_EQ(7, num_items
);
226 EXPECT_TRUE(model
.IsEnabledAt(0));
227 model
.ActivatedAt(0);
228 EXPECT_TRUE(model
.IsEnabledAt(1));
229 EXPECT_FALSE(model
.IsEnabledAt(2));
230 EXPECT_TRUE(model
.IsEnabledAt(3));
231 EXPECT_TRUE(model
.IsEnabledAt(4));
232 model
.ActivatedAt(3);
233 model
.ActivatedAt(4);
234 EXPECT_FALSE(model
.IsEnabledAt(6));
235 EXPECT_EQ(3, model
.enable_count());
236 EXPECT_EQ(3, model
.execute_count());
238 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
239 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
240 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
241 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
242 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
243 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
244 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
247 base::string16 title
;
248 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
249 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
250 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
251 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
252 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
253 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
254 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
257 // TODO(sail): enable this test when dynamic model is enabled in
258 // RecentTabsSubMenuModel.
259 #if defined(OS_MACOSX)
260 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
261 DISABLED_RecentlyClosedTabsAndWindowsFromLastSession
263 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
264 RecentlyClosedTabsAndWindowsFromLastSession
266 TEST_F(RecentTabsSubMenuModelTest
,
267 MAYBE_RecentlyClosedTabsAndWindowsFromLastSession
) {
268 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
269 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
271 // Add 2 tabs and close them.
272 AddTab(browser(), GURL("http://wnd/tab0"));
273 AddTab(browser(), GURL("http://wnd/tab1"));
274 browser()->tab_strip_model()->CloseAllTabs();
276 // Create a SessionService for the profile (profile owns the service) and add
277 // a window with a tab to this session.
278 SessionService
* session_service
= new SessionService(profile());
279 SessionServiceFactory::SetForTestProfile(profile(),
280 make_scoped_ptr(session_service
));
283 session_service
->SetWindowType(window_id
,
284 Browser::TYPE_TABBED
,
285 SessionService::TYPE_NORMAL
);
286 session_service
->SetTabWindow(window_id
, tab_id
);
287 session_service
->SetTabIndexInWindow(window_id
, tab_id
, 0);
288 session_service
->SetSelectedTabInWindow(window_id
, 0);
289 session_service
->UpdateTabNavigation(
291 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
292 "http://wnd1/tab0", "title"));
293 // Set this, otherwise previous session won't be loaded.
294 profile()->set_last_session_exited_cleanly(false);
295 // Move this session to the last so that TabRestoreService will load it as the
297 SessionServiceFactory::GetForProfile(profile())->
298 MoveCurrentSessionToLastSession();
300 // Create a new TabRestoreService so that it'll load the recently closed tabs
301 // and windows afresh.
302 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
303 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
304 // Let the shutdown of previous TabRestoreService run.
305 content::RunAllBlockingPoolTasksUntilIdle();
307 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
308 TestRecentTabsMenuModelDelegate
delegate(&model
);
309 EXPECT_FALSE(delegate
.got_changes());
311 // Expected menu before tabs/windows from last session are loaded:
312 // Menu index Menu items
313 // ----------------------------------------------------------------
316 // 2 Recently closed header
318 // 4 No tabs from other Devices
320 int num_items
= model
.GetItemCount();
321 EXPECT_EQ(5, num_items
);
322 EXPECT_TRUE(model
.IsEnabledAt(0));
323 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
324 EXPECT_FALSE(model
.IsEnabledAt(2));
325 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(3));
326 EXPECT_FALSE(model
.IsEnabledAt(4));
327 EXPECT_EQ(1, model
.enable_count());
329 // Wait for tabs from last session to be loaded.
330 WaitForLoadFromLastSession();
332 // Expected menu after tabs/windows from last session are loaded:
333 // Menu index Menu items
334 // --------------------------------------------------------------
337 // 2 Recently closed header
338 // 3 <window for the tab http://wnd1/tab0>
339 // 4 <tab for http://wnd0/tab1>
340 // 5 <tab for http://wnd0/tab0>
342 // 7 No tabs from other Devices
344 EXPECT_TRUE(delegate
.got_changes());
346 num_items
= model
.GetItemCount();
347 EXPECT_EQ(8, num_items
);
349 EXPECT_TRUE(model
.IsEnabledAt(0));
350 model
.ActivatedAt(0);
351 EXPECT_TRUE(model
.IsEnabledAt(1));
352 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
353 EXPECT_FALSE(model
.IsEnabledAt(2));
354 EXPECT_TRUE(model
.IsEnabledAt(3));
355 EXPECT_TRUE(model
.IsEnabledAt(4));
356 EXPECT_TRUE(model
.IsEnabledAt(5));
357 model
.ActivatedAt(3);
358 model
.ActivatedAt(4);
359 model
.ActivatedAt(5);
360 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(6));
361 EXPECT_FALSE(model
.IsEnabledAt(7));
362 EXPECT_EQ(5, model
.enable_count());
363 EXPECT_EQ(4, model
.execute_count());
365 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
366 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
367 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
368 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
369 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
370 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
371 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
372 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
375 base::string16 title
;
376 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
377 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
378 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
379 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
380 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
381 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
382 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
383 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
386 // Test disabled "Recently closed" header with multiple sessions, multiple
387 // windows, and multiple enabled tabs from other devices.
388 TEST_F(RecentTabsSubMenuModelTest
, OtherDevices
) {
389 // Tabs are populated in decreasing timestamp.
390 base::Time timestamp
= base::Time::Now();
391 const base::TimeDelta time_delta
= base::TimeDelta::FromMinutes(10);
393 RecentTabsBuilderTestHelper recent_tabs_builder
;
395 // Create 1st session : 1 window, 3 tabs
396 recent_tabs_builder
.AddSession();
397 recent_tabs_builder
.AddWindow(0);
398 for (int i
= 0; i
< 3; ++i
) {
399 timestamp
-= time_delta
;
400 recent_tabs_builder
.AddTabWithInfo(0, 0, timestamp
, base::string16());
403 // Create 2nd session : 2 windows, 1 tab in 1st window, 2 tabs in 2nd window
404 recent_tabs_builder
.AddSession();
405 recent_tabs_builder
.AddWindow(1);
406 recent_tabs_builder
.AddWindow(1);
407 timestamp
-= time_delta
;
408 recent_tabs_builder
.AddTabWithInfo(1, 0, timestamp
, base::string16());
409 timestamp
-= time_delta
;
410 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
411 timestamp
-= time_delta
;
412 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
414 RegisterRecentTabs(&recent_tabs_builder
);
416 // Verify that data is populated correctly in RecentTabsSubMenuModel.
418 // - first inserted tab is most recent and hence is top
419 // Menu index Menu items
420 // -----------------------------------------------------
423 // 2 Recently closed header (disabled)
425 // 4 <section header for 1st session>
426 // 5-7 <3 tabs of the only window of session 0>
428 // 9 <section header for 2nd session>
429 // 10 <the only tab of window 0 of session 1>
430 // 11-12 <2 tabs of window 1 of session 2>
432 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
433 int num_items
= model
.GetItemCount();
434 EXPECT_EQ(13, num_items
);
435 model
.ActivatedAt(0);
436 EXPECT_TRUE(model
.IsEnabledAt(0));
437 model
.ActivatedAt(1);
438 EXPECT_TRUE(model
.IsEnabledAt(1));
439 model
.ActivatedAt(2);
440 EXPECT_FALSE(model
.IsEnabledAt(2));
441 model
.ActivatedAt(3);
442 EXPECT_TRUE(model
.IsEnabledAt(3));
443 model
.ActivatedAt(5);
444 EXPECT_TRUE(model
.IsEnabledAt(5));
445 model
.ActivatedAt(6);
446 EXPECT_TRUE(model
.IsEnabledAt(6));
447 model
.ActivatedAt(7);
448 EXPECT_TRUE(model
.IsEnabledAt(7));
449 model
.ActivatedAt(10);
450 EXPECT_TRUE(model
.IsEnabledAt(10));
451 model
.ActivatedAt(11);
452 EXPECT_TRUE(model
.IsEnabledAt(11));
453 model
.ActivatedAt(12);
454 EXPECT_TRUE(model
.IsEnabledAt(12));
456 EXPECT_EQ(7, model
.enable_count());
457 EXPECT_EQ(10, model
.execute_count());
459 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
460 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
461 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
462 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
463 EXPECT_TRUE(model
.GetLabelFontListAt(4) != nullptr);
464 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
465 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
466 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
467 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(8));
468 EXPECT_TRUE(model
.GetLabelFontListAt(9) != nullptr);
469 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(10));
470 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(11));
471 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(12));
474 base::string16 title
;
475 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
476 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
477 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
478 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
479 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
480 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
481 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
482 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
483 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(8, &url
, &title
));
484 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(9, &url
, &title
));
485 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(10, &url
, &title
));
486 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(11, &url
, &title
));
487 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(12, &url
, &title
));
490 TEST_F(RecentTabsSubMenuModelTest
, MaxSessionsAndRecency
) {
491 // Create 4 sessions : each session has 1 window with 1 tab each.
492 RecentTabsBuilderTestHelper recent_tabs_builder
;
493 for (int s
= 0; s
< 4; ++s
) {
494 recent_tabs_builder
.AddSession();
495 recent_tabs_builder
.AddWindow(s
);
496 recent_tabs_builder
.AddTab(s
, 0);
498 RegisterRecentTabs(&recent_tabs_builder
);
500 // Verify that data is populated correctly in RecentTabsSubMenuModel.
502 // - max sessions is 3, so only 3 most-recent sessions will show.
503 // Menu index Menu items
504 // ----------------------------------------------------------
507 // 2 Recently closed header (disabled)
509 // 4 <section header for 1st session>
510 // 5 <the only tab of the only window of session 3>
512 // 7 <section header for 2nd session>
513 // 8 <the only tab of the only window of session 2>
515 // 10 <section header for 3rd session>
516 // 11 <the only tab of the only window of session 1>
518 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
519 int num_items
= model
.GetItemCount();
520 EXPECT_EQ(12, num_items
);
522 std::vector
<base::string16
> tab_titles
=
523 recent_tabs_builder
.GetTabTitlesSortedByRecency();
524 EXPECT_EQ(tab_titles
[0], model
.GetLabelAt(5));
525 EXPECT_EQ(tab_titles
[1], model
.GetLabelAt(8));
526 EXPECT_EQ(tab_titles
[2], model
.GetLabelAt(11));
529 TEST_F(RecentTabsSubMenuModelTest
, MaxTabsPerSessionAndRecency
) {
530 // Create a session: 2 windows with 5 tabs each.
531 RecentTabsBuilderTestHelper recent_tabs_builder
;
532 recent_tabs_builder
.AddSession();
533 for (int w
= 0; w
< 2; ++w
) {
534 recent_tabs_builder
.AddWindow(0);
535 for (int t
= 0; t
< 5; ++t
)
536 recent_tabs_builder
.AddTab(0, w
);
538 RegisterRecentTabs(&recent_tabs_builder
);
540 // Verify that data is populated correctly in RecentTabsSubMenuModel.
542 // - max tabs per session is 4, so only 4 most-recent tabs will show,
543 // independent of which window they came from.
544 // Menu index Menu items
545 // ---------------------------------------------
548 // 2 Recently closed header (disabled)
550 // 4 <section header for session>
551 // 5-8 <4 most-recent tabs of session>
553 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
554 int num_items
= model
.GetItemCount();
555 EXPECT_EQ(9, num_items
);
557 std::vector
<base::string16
> tab_titles
=
558 recent_tabs_builder
.GetTabTitlesSortedByRecency();
559 for (int i
= 0; i
< 4; ++i
)
560 EXPECT_EQ(tab_titles
[i
], model
.GetLabelAt(i
+ 5));
563 TEST_F(RecentTabsSubMenuModelTest
, MaxWidth
) {
564 // Create 1 session with 1 window and 1 tab.
565 RecentTabsBuilderTestHelper recent_tabs_builder
;
566 recent_tabs_builder
.AddSession();
567 recent_tabs_builder
.AddWindow(0);
568 recent_tabs_builder
.AddTab(0, 0);
569 RegisterRecentTabs(&recent_tabs_builder
);
571 // Menu index Menu items
572 // ----------------------------------------------------------
575 // 2 Recently closed header (disabled)
577 // 4 <section header for 1st session>
578 // 5 <the only tab of the only window of session 1>
580 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
581 EXPECT_EQ(6, model
.GetItemCount());
582 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
583 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
584 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(4));
585 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(5));
588 TEST_F(RecentTabsSubMenuModelTest
, MaxWidthNoDevices
) {
590 // Menu index Menu items
591 // --------------------------------------------
594 // 2 Recently closed heaer (disabled)
596 // 4 No tabs from other Devices
598 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
599 EXPECT_EQ(5, model
.GetItemCount());
600 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
601 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
602 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(4));