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/persistent_tab_restore_service.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/serialized_navigation_entry_test_helper.h"
30 #include "components/sessions/session_types.h"
31 #include "components/sync_driver/glue/synced_session.h"
32 #include "components/sync_driver/local_device_info_provider_mock.h"
33 #include "content/public/browser/browser_thread.h"
34 #include "content/public/test/test_utils.h"
35 #include "grit/generated_resources.h"
36 #include "sync/api/fake_sync_change_processor.h"
37 #include "sync/api/sync_error_factory_mock.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
43 // This copies parts of MenuModelTest::Delegate and combines them with the
44 // RecentTabsSubMenuModel since RecentTabsSubMenuModel is a
45 // SimpleMenuModel::Delegate and not just derived from SimpleMenuModel.
46 class TestRecentTabsSubMenuModel
: public RecentTabsSubMenuModel
{
48 TestRecentTabsSubMenuModel(ui::AcceleratorProvider
* provider
,
50 sync_driver::OpenTabsUIDelegate
* delegate
)
51 : RecentTabsSubMenuModel(provider
, browser
, delegate
),
55 // Testing overrides to ui::SimpleMenuModel::Delegate:
56 bool IsCommandIdEnabled(int command_id
) const override
{
57 bool val
= RecentTabsSubMenuModel::IsCommandIdEnabled(command_id
);
63 void ExecuteCommand(int command_id
, int event_flags
) override
{
67 int execute_count() const { return execute_count_
; }
68 int enable_count() const { return enable_count_
; }
72 int mutable enable_count_
; // Mutable because IsCommandIdEnabledAt is const.
74 DISALLOW_COPY_AND_ASSIGN(TestRecentTabsSubMenuModel
);
77 class TestRecentTabsMenuModelDelegate
: public ui::MenuModelDelegate
{
79 explicit TestRecentTabsMenuModelDelegate(ui::MenuModel
* model
)
82 model_
->SetMenuModelDelegate(this);
85 ~TestRecentTabsMenuModelDelegate() override
{
86 model_
->SetMenuModelDelegate(NULL
);
89 // ui::MenuModelDelegate implementation:
91 void OnIconChanged(int index
) override
{}
93 void OnMenuStructureChanged() override
{ got_changes_
= true; }
95 bool got_changes() const { return got_changes_
; }
98 ui::MenuModel
* model_
;
101 DISALLOW_COPY_AND_ASSIGN(TestRecentTabsMenuModelDelegate
);
104 class DummyRouter
: public browser_sync::LocalSessionEventRouter
{
106 ~DummyRouter() override
{}
108 browser_sync::LocalSessionEventHandler
* handler
) override
{}
109 void Stop() override
{}
114 class RecentTabsSubMenuModelTest
115 : public BrowserWithTestWindowTest
{
117 RecentTabsSubMenuModelTest()
118 : sync_service_(&testing_profile_
),
119 local_device_(new sync_driver::LocalDeviceInfoProviderMock(
120 "RecentTabsSubMenuModelTest",
124 sync_pb::SyncEnums_DeviceType_TYPE_LINUX
,
126 manager_
.reset(new browser_sync::SessionsSyncManager(
127 &testing_profile_
, local_device_
.get(),
128 scoped_ptr
<browser_sync::LocalSessionEventRouter
>(new DummyRouter()),
129 scoped_ptr
<browser_sync::SyncedWindowDelegatesGetter
>(
130 new browser_sync::BrowserSyncedWindowDelegatesGetter())));
131 manager_
->MergeDataAndStartSyncing(
133 syncer::SyncDataList(),
134 scoped_ptr
<syncer::SyncChangeProcessor
>(
135 new syncer::FakeSyncChangeProcessor
),
136 scoped_ptr
<syncer::SyncErrorFactory
>(
137 new syncer::SyncErrorFactoryMock
));
140 void WaitForLoadFromLastSession() {
141 content::RunAllBlockingPoolTasksUntilIdle();
144 static scoped_ptr
<KeyedService
> GetTabRestoreService(
145 content::BrowserContext
* browser_context
) {
146 return make_scoped_ptr(new PersistentTabRestoreService(
147 Profile::FromBrowserContext(browser_context
), NULL
));
150 sync_driver::OpenTabsUIDelegate
* GetOpenTabsDelegate() {
151 return manager_
.get();
154 void RegisterRecentTabs(RecentTabsBuilderTestHelper
* helper
) {
155 helper
->ExportToSessionsSyncManager(manager_
.get());
159 TestingProfile testing_profile_
;
160 testing::NiceMock
<ProfileSyncServiceMock
> sync_service_
;
162 scoped_ptr
<browser_sync::SessionsSyncManager
> manager_
;
163 scoped_ptr
<sync_driver::LocalDeviceInfoProviderMock
> local_device_
;
166 // Test disabled "Recently closed" header with no foreign tabs.
167 TEST_F(RecentTabsSubMenuModelTest
, NoTabs
) {
168 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
171 // Menu index Menu items
172 // ---------------------------------------------
175 // 2 Recently closed header (disabled)
177 // 4 No tabs from other Devices
179 int num_items
= model
.GetItemCount();
180 EXPECT_EQ(5, num_items
);
181 EXPECT_FALSE(model
.IsEnabledAt(2));
182 EXPECT_FALSE(model
.IsEnabledAt(4));
183 EXPECT_EQ(0, model
.enable_count());
185 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
186 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
187 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
188 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
189 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
192 base::string16 title
;
193 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
194 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
195 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
196 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
197 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
200 // Test enabled "Recently closed" header with no foreign tabs.
201 TEST_F(RecentTabsSubMenuModelTest
, RecentlyClosedTabsFromCurrentSession
) {
202 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
203 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
205 // Add 2 tabs and close them.
206 AddTab(browser(), GURL("http://foo/1"));
207 AddTab(browser(), GURL("http://foo/2"));
208 browser()->tab_strip_model()->CloseAllTabs();
210 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
212 // Menu index Menu items
213 // --------------------------------------
216 // 2 Recently closed header
217 // 3 <tab for http://foo/2>
218 // 4 <tab for http://foo/1>
220 // 6 No tabs from other Devices
221 int num_items
= model
.GetItemCount();
222 EXPECT_EQ(7, num_items
);
223 EXPECT_TRUE(model
.IsEnabledAt(0));
224 model
.ActivatedAt(0);
225 EXPECT_TRUE(model
.IsEnabledAt(1));
226 EXPECT_FALSE(model
.IsEnabledAt(2));
227 EXPECT_TRUE(model
.IsEnabledAt(3));
228 EXPECT_TRUE(model
.IsEnabledAt(4));
229 model
.ActivatedAt(3);
230 model
.ActivatedAt(4);
231 EXPECT_FALSE(model
.IsEnabledAt(6));
232 EXPECT_EQ(3, model
.enable_count());
233 EXPECT_EQ(3, model
.execute_count());
235 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
236 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
237 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
238 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
239 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
240 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
241 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
244 base::string16 title
;
245 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
246 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
247 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
248 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
249 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
250 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
251 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
254 // TODO(sail): enable this test when dynamic model is enabled in
255 // RecentTabsSubMenuModel.
256 #if defined(OS_MACOSX)
257 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
258 DISABLED_RecentlyClosedTabsAndWindowsFromLastSession
260 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
261 RecentlyClosedTabsAndWindowsFromLastSession
263 TEST_F(RecentTabsSubMenuModelTest
,
264 MAYBE_RecentlyClosedTabsAndWindowsFromLastSession
) {
265 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
266 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
268 // Add 2 tabs and close them.
269 AddTab(browser(), GURL("http://wnd/tab0"));
270 AddTab(browser(), GURL("http://wnd/tab1"));
271 browser()->tab_strip_model()->CloseAllTabs();
273 // Create a SessionService for the profile (profile owns the service) and add
274 // a window with a tab to this session.
275 SessionService
* session_service
= new SessionService(profile());
276 SessionServiceFactory::SetForTestProfile(profile(),
277 make_scoped_ptr(session_service
));
280 session_service
->SetWindowType(window_id
,
281 Browser::TYPE_TABBED
,
282 SessionService::TYPE_NORMAL
);
283 session_service
->SetTabWindow(window_id
, tab_id
);
284 session_service
->SetTabIndexInWindow(window_id
, tab_id
, 0);
285 session_service
->SetSelectedTabInWindow(window_id
, 0);
286 session_service
->UpdateTabNavigation(
288 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
289 "http://wnd1/tab0", "title"));
290 // Set this, otherwise previous session won't be loaded.
291 profile()->set_last_session_exited_cleanly(false);
292 // Move this session to the last so that TabRestoreService will load it as the
294 SessionServiceFactory::GetForProfile(profile())->
295 MoveCurrentSessionToLastSession();
297 // Create a new TabRestoreService so that it'll load the recently closed tabs
298 // and windows afresh.
299 TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
300 profile(), RecentTabsSubMenuModelTest::GetTabRestoreService
);
301 // Let the shutdown of previous TabRestoreService run.
302 content::RunAllBlockingPoolTasksUntilIdle();
304 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
305 TestRecentTabsMenuModelDelegate
delegate(&model
);
306 EXPECT_FALSE(delegate
.got_changes());
308 // Expected menu before tabs/windows from last session are loaded:
309 // Menu index Menu items
310 // ----------------------------------------------------------------
313 // 2 Recently closed header
315 // 4 No tabs from other Devices
317 int num_items
= model
.GetItemCount();
318 EXPECT_EQ(5, num_items
);
319 EXPECT_TRUE(model
.IsEnabledAt(0));
320 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
321 EXPECT_FALSE(model
.IsEnabledAt(2));
322 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(3));
323 EXPECT_FALSE(model
.IsEnabledAt(4));
324 EXPECT_EQ(1, model
.enable_count());
326 // Wait for tabs from last session to be loaded.
327 WaitForLoadFromLastSession();
329 // Expected menu after tabs/windows from last session are loaded:
330 // Menu index Menu items
331 // --------------------------------------------------------------
334 // 2 Recently closed header
335 // 3 <window for the tab http://wnd1/tab0>
336 // 4 <tab for http://wnd0/tab1>
337 // 5 <tab for http://wnd0/tab0>
339 // 7 No tabs from other Devices
341 EXPECT_TRUE(delegate
.got_changes());
343 num_items
= model
.GetItemCount();
344 EXPECT_EQ(8, num_items
);
346 EXPECT_TRUE(model
.IsEnabledAt(0));
347 model
.ActivatedAt(0);
348 EXPECT_TRUE(model
.IsEnabledAt(1));
349 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(1));
350 EXPECT_FALSE(model
.IsEnabledAt(2));
351 EXPECT_TRUE(model
.IsEnabledAt(3));
352 EXPECT_TRUE(model
.IsEnabledAt(4));
353 EXPECT_TRUE(model
.IsEnabledAt(5));
354 model
.ActivatedAt(3);
355 model
.ActivatedAt(4);
356 model
.ActivatedAt(5);
357 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
, model
.GetTypeAt(6));
358 EXPECT_FALSE(model
.IsEnabledAt(7));
359 EXPECT_EQ(5, model
.enable_count());
360 EXPECT_EQ(4, model
.execute_count());
362 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
363 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
364 EXPECT_TRUE(model
.GetLabelFontListAt(2) != nullptr);
365 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
366 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(4));
367 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
368 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
369 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
372 base::string16 title
;
373 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
374 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
375 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
376 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
377 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
378 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
379 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
380 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
383 // Test disabled "Recently closed" header with multiple sessions, multiple
384 // windows, and multiple enabled tabs from other devices.
385 TEST_F(RecentTabsSubMenuModelTest
, OtherDevices
) {
386 // Tabs are populated in decreasing timestamp.
387 base::Time timestamp
= base::Time::Now();
388 const base::TimeDelta time_delta
= base::TimeDelta::FromMinutes(10);
390 RecentTabsBuilderTestHelper recent_tabs_builder
;
392 // Create 1st session : 1 window, 3 tabs
393 recent_tabs_builder
.AddSession();
394 recent_tabs_builder
.AddWindow(0);
395 for (int i
= 0; i
< 3; ++i
) {
396 timestamp
-= time_delta
;
397 recent_tabs_builder
.AddTabWithInfo(0, 0, timestamp
, base::string16());
400 // Create 2nd session : 2 windows, 1 tab in 1st window, 2 tabs in 2nd window
401 recent_tabs_builder
.AddSession();
402 recent_tabs_builder
.AddWindow(1);
403 recent_tabs_builder
.AddWindow(1);
404 timestamp
-= time_delta
;
405 recent_tabs_builder
.AddTabWithInfo(1, 0, timestamp
, base::string16());
406 timestamp
-= time_delta
;
407 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
408 timestamp
-= time_delta
;
409 recent_tabs_builder
.AddTabWithInfo(1, 1, timestamp
, base::string16());
411 RegisterRecentTabs(&recent_tabs_builder
);
413 // Verify that data is populated correctly in RecentTabsSubMenuModel.
415 // - first inserted tab is most recent and hence is top
416 // Menu index Menu items
417 // -----------------------------------------------------
420 // 2 Recently closed header (disabled)
422 // 4 <section header for 1st session>
423 // 5-7 <3 tabs of the only window of session 0>
425 // 9 <section header for 2nd session>
426 // 10 <the only tab of window 0 of session 1>
427 // 11-12 <2 tabs of window 1 of session 2>
429 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
430 int num_items
= model
.GetItemCount();
431 EXPECT_EQ(13, num_items
);
432 model
.ActivatedAt(0);
433 EXPECT_TRUE(model
.IsEnabledAt(0));
434 model
.ActivatedAt(1);
435 EXPECT_TRUE(model
.IsEnabledAt(1));
436 model
.ActivatedAt(2);
437 EXPECT_FALSE(model
.IsEnabledAt(2));
438 model
.ActivatedAt(3);
439 EXPECT_TRUE(model
.IsEnabledAt(3));
440 model
.ActivatedAt(5);
441 EXPECT_TRUE(model
.IsEnabledAt(5));
442 model
.ActivatedAt(6);
443 EXPECT_TRUE(model
.IsEnabledAt(6));
444 model
.ActivatedAt(7);
445 EXPECT_TRUE(model
.IsEnabledAt(7));
446 model
.ActivatedAt(10);
447 EXPECT_TRUE(model
.IsEnabledAt(10));
448 model
.ActivatedAt(11);
449 EXPECT_TRUE(model
.IsEnabledAt(11));
450 model
.ActivatedAt(12);
451 EXPECT_TRUE(model
.IsEnabledAt(12));
453 EXPECT_EQ(7, model
.enable_count());
454 EXPECT_EQ(10, model
.execute_count());
456 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(0));
457 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(1));
458 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(2));
459 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(3));
460 EXPECT_TRUE(model
.GetLabelFontListAt(4) != nullptr);
461 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(5));
462 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(6));
463 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(7));
464 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(8));
465 EXPECT_TRUE(model
.GetLabelFontListAt(9) != nullptr);
466 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(10));
467 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(11));
468 EXPECT_EQ(NULL
, model
.GetLabelFontListAt(12));
471 base::string16 title
;
472 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(0, &url
, &title
));
473 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(1, &url
, &title
));
474 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(2, &url
, &title
));
475 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(3, &url
, &title
));
476 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(4, &url
, &title
));
477 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(5, &url
, &title
));
478 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(6, &url
, &title
));
479 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(7, &url
, &title
));
480 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(8, &url
, &title
));
481 EXPECT_FALSE(model
.GetURLAndTitleForItemAtIndex(9, &url
, &title
));
482 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(10, &url
, &title
));
483 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(11, &url
, &title
));
484 EXPECT_TRUE(model
.GetURLAndTitleForItemAtIndex(12, &url
, &title
));
487 TEST_F(RecentTabsSubMenuModelTest
, MaxSessionsAndRecency
) {
488 // Create 4 sessions : each session has 1 window with 1 tab each.
489 RecentTabsBuilderTestHelper recent_tabs_builder
;
490 for (int s
= 0; s
< 4; ++s
) {
491 recent_tabs_builder
.AddSession();
492 recent_tabs_builder
.AddWindow(s
);
493 recent_tabs_builder
.AddTab(s
, 0);
495 RegisterRecentTabs(&recent_tabs_builder
);
497 // Verify that data is populated correctly in RecentTabsSubMenuModel.
499 // - max sessions is 3, so only 3 most-recent sessions will show.
500 // Menu index Menu items
501 // ----------------------------------------------------------
504 // 2 Recently closed header (disabled)
506 // 4 <section header for 1st session>
507 // 5 <the only tab of the only window of session 3>
509 // 7 <section header for 2nd session>
510 // 8 <the only tab of the only window of session 2>
512 // 10 <section header for 3rd session>
513 // 11 <the only tab of the only window of session 1>
515 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
516 int num_items
= model
.GetItemCount();
517 EXPECT_EQ(12, num_items
);
519 std::vector
<base::string16
> tab_titles
=
520 recent_tabs_builder
.GetTabTitlesSortedByRecency();
521 EXPECT_EQ(tab_titles
[0], model
.GetLabelAt(5));
522 EXPECT_EQ(tab_titles
[1], model
.GetLabelAt(8));
523 EXPECT_EQ(tab_titles
[2], model
.GetLabelAt(11));
526 TEST_F(RecentTabsSubMenuModelTest
, MaxTabsPerSessionAndRecency
) {
527 // Create a session: 2 windows with 5 tabs each.
528 RecentTabsBuilderTestHelper recent_tabs_builder
;
529 recent_tabs_builder
.AddSession();
530 for (int w
= 0; w
< 2; ++w
) {
531 recent_tabs_builder
.AddWindow(0);
532 for (int t
= 0; t
< 5; ++t
)
533 recent_tabs_builder
.AddTab(0, w
);
535 RegisterRecentTabs(&recent_tabs_builder
);
537 // Verify that data is populated correctly in RecentTabsSubMenuModel.
539 // - max tabs per session is 4, so only 4 most-recent tabs will show,
540 // independent of which window they came from.
541 // Menu index Menu items
542 // ---------------------------------------------
545 // 2 Recently closed header (disabled)
547 // 4 <section header for session>
548 // 5-8 <4 most-recent tabs of session>
550 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
551 int num_items
= model
.GetItemCount();
552 EXPECT_EQ(9, num_items
);
554 std::vector
<base::string16
> tab_titles
=
555 recent_tabs_builder
.GetTabTitlesSortedByRecency();
556 for (int i
= 0; i
< 4; ++i
)
557 EXPECT_EQ(tab_titles
[i
], model
.GetLabelAt(i
+ 5));
560 TEST_F(RecentTabsSubMenuModelTest
, MaxWidth
) {
561 // Create 1 session with 1 window and 1 tab.
562 RecentTabsBuilderTestHelper recent_tabs_builder
;
563 recent_tabs_builder
.AddSession();
564 recent_tabs_builder
.AddWindow(0);
565 recent_tabs_builder
.AddTab(0, 0);
566 RegisterRecentTabs(&recent_tabs_builder
);
568 // Menu index Menu items
569 // ----------------------------------------------------------
572 // 2 Recently closed header (disabled)
574 // 4 <section header for 1st session>
575 // 5 <the only tab of the only window of session 1>
577 TestRecentTabsSubMenuModel
model(NULL
, browser(), GetOpenTabsDelegate());
578 EXPECT_EQ(6, model
.GetItemCount());
579 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
580 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
581 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(4));
582 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(5));
585 TEST_F(RecentTabsSubMenuModelTest
, MaxWidthNoDevices
) {
587 // Menu index Menu items
588 // --------------------------------------------
591 // 2 Recently closed heaer (disabled)
593 // 4 No tabs from other Devices
595 TestRecentTabsSubMenuModel
model(NULL
, browser(), NULL
);
596 EXPECT_EQ(5, model
.GetItemCount());
597 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(2));
598 EXPECT_NE(-1, model
.GetMaxWidthForItemAtIndex(3));
599 EXPECT_EQ(-1, model
.GetMaxWidthForItemAtIndex(4));