- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / toolbar / recent_tabs_sub_menu_model_unittest.cc
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.
4
5 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h"
6
7 #include "base/run_loop.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/sessions/session_service.h"
10 #include "chrome/browser/sessions/session_service_factory.h"
11 #include "chrome/browser/sessions/session_types.h"
12 #include "chrome/browser/sessions/persistent_tab_restore_service.h"
13 #include "chrome/browser/sessions/tab_restore_service_factory.h"
14 #include "chrome/browser/sync/glue/session_model_associator.h"
15 #include "chrome/browser/sync/glue/synced_session.h"
16 #include "chrome/browser/sync/profile_sync_service_mock.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_tabstrip.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/browser/ui/toolbar/recent_tabs_builder_test_helper.h"
21 #include "chrome/test/base/browser_with_test_window_test.h"
22 #include "chrome/test/base/menu_model_test.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "components/sessions/serialized_navigation_entry_test_helper.h"
25 #include "grit/generated_resources.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace {
30
31 // This copies parts of MenuModelTest::Delegate and combines them with the
32 // RecentTabsSubMenuModel since RecentTabsSubMenuModel is a
33 // SimpleMenuModel::Delegate and not just derived from SimpleMenuModel.
34 class TestRecentTabsSubMenuModel : public RecentTabsSubMenuModel {
35  public:
36   TestRecentTabsSubMenuModel(ui::AcceleratorProvider* provider,
37                              Browser* browser,
38                              browser_sync::SessionModelAssociator* associator)
39       : RecentTabsSubMenuModel(provider, browser, associator),
40         execute_count_(0),
41         enable_count_(0) {
42   }
43
44   // Testing overrides to ui::SimpleMenuModel::Delegate:
45   virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
46     bool val = RecentTabsSubMenuModel::IsCommandIdEnabled(command_id);
47     if (val)
48       ++enable_count_;
49     return val;
50   }
51
52   virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE {
53     ++execute_count_;
54   }
55
56   int execute_count() const { return execute_count_; }
57   int enable_count() const { return enable_count_; }
58
59  private:
60   int execute_count_;
61   int mutable enable_count_;  // Mutable because IsCommandIdEnabledAt is const.
62
63   DISALLOW_COPY_AND_ASSIGN(TestRecentTabsSubMenuModel);
64 };
65
66 class TestRecentTabsMenuModelDelegate : public ui::MenuModelDelegate {
67  public:
68   explicit TestRecentTabsMenuModelDelegate(ui::MenuModel* model)
69       : model_(model),
70         got_changes_(false) {
71     model_->SetMenuModelDelegate(this);
72   }
73
74   virtual ~TestRecentTabsMenuModelDelegate() {
75     model_->SetMenuModelDelegate(NULL);
76   }
77
78   // ui::MenuModelDelegate implementation:
79
80   virtual void OnIconChanged(int index) OVERRIDE {
81   }
82
83   virtual void OnMenuStructureChanged() OVERRIDE {
84     got_changes_ = true;
85   }
86
87   bool got_changes() const { return got_changes_; }
88
89  private:
90   ui::MenuModel* model_;
91   bool got_changes_;
92
93   DISALLOW_COPY_AND_ASSIGN(TestRecentTabsMenuModelDelegate);
94 };
95
96 }  // namespace
97
98 class RecentTabsSubMenuModelTest : public BrowserWithTestWindowTest {
99  public:
100    RecentTabsSubMenuModelTest()
101        : sync_service_(&testing_profile_),
102          associator_(&sync_service_, true) {
103     associator_.SetCurrentMachineTagForTesting("RecentTabsSubMenuModelTest");
104   }
105
106   void WaitForLoadFromLastSession() {
107     content::BrowserThread::GetBlockingPool()->FlushForTesting();
108     base::RunLoop().RunUntilIdle();
109     content::BrowserThread::GetBlockingPool()->FlushForTesting();
110   }
111
112   static BrowserContextKeyedService* GetTabRestoreService(
113       content::BrowserContext* browser_context) {
114     // Ownership is tranfered to the profile.
115     return new PersistentTabRestoreService(
116         Profile::FromBrowserContext(browser_context), NULL);;
117   }
118
119  private:
120   TestingProfile testing_profile_;
121   testing::NiceMock<ProfileSyncServiceMock> sync_service_;
122
123  protected:
124   browser_sync::SessionModelAssociator associator_;
125 };
126
127 // Test disabled "Recently closed" header with no foreign tabs.
128 TEST_F(RecentTabsSubMenuModelTest, NoTabs) {
129   TestRecentTabsSubMenuModel model(NULL, browser(), NULL);
130
131   // Expected menu:
132   // Menu index  Menu items
133   // ---------------------------------------------
134   // 0           Recently closed header (disabled)
135   // 1           <separator>
136   // 2           No tabs from other Devices
137
138   int num_items = model.GetItemCount();
139   EXPECT_EQ(3, num_items);
140   EXPECT_FALSE(model.IsEnabledAt(0));
141   EXPECT_FALSE(model.IsEnabledAt(2));
142   EXPECT_EQ(0, model.enable_count());
143
144   EXPECT_EQ(NULL, model.GetLabelFontAt(0));
145   EXPECT_EQ(NULL, model.GetLabelFontAt(1));
146   EXPECT_EQ(NULL, model.GetLabelFontAt(2));
147
148   std::string url;
149   string16 title;
150   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(0, &url, &title));
151   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(1, &url, &title));
152   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(2, &url, &title));
153 }
154
155 // Test enabled "Recently closed" header with no foreign tabs.
156 TEST_F(RecentTabsSubMenuModelTest, RecentlyClosedTabsFromCurrentSession) {
157   TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
158       profile(), RecentTabsSubMenuModelTest::GetTabRestoreService);
159
160   // Add 2 tabs and close them.
161   AddTab(browser(), GURL("http://foo/1"));
162   AddTab(browser(), GURL("http://foo/2"));
163   browser()->tab_strip_model()->CloseAllTabs();
164
165   TestRecentTabsSubMenuModel model(NULL, browser(), NULL);
166   // Expected menu:
167   // Menu index  Menu items
168   // --------------------------------------
169   // 0           Recently closed header
170   // 1           <tab for http://foo/2>
171   // 2           <tab for http://foo/1>
172   // 3           <separator>
173   // 4           No tabs from other Devices
174   int num_items = model.GetItemCount();
175   EXPECT_EQ(5, num_items);
176   EXPECT_FALSE(model.IsEnabledAt(0));
177   EXPECT_TRUE(model.IsEnabledAt(1));
178   EXPECT_TRUE(model.IsEnabledAt(2));
179   model.ActivatedAt(1);
180   model.ActivatedAt(2);
181   EXPECT_FALSE(model.IsEnabledAt(4));
182   EXPECT_EQ(2, model.enable_count());
183   EXPECT_EQ(2, model.execute_count());
184
185   EXPECT_TRUE(model.GetLabelFontAt(0) != NULL);
186   EXPECT_EQ(NULL, model.GetLabelFontAt(1));
187   EXPECT_EQ(NULL, model.GetLabelFontAt(2));
188   EXPECT_EQ(NULL, model.GetLabelFontAt(3));
189   EXPECT_EQ(NULL, model.GetLabelFontAt(4));
190
191   std::string url;
192   string16 title;
193   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(0, &url, &title));
194   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(1, &url, &title));
195   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(2, &url, &title));
196   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(3, &url, &title));
197   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(4, &url, &title));
198 }
199
200 // TODO(sail): enable this test when dynamic model is enabled in
201 // RecentTabsSubMenuModel.
202 #if defined(OS_MACOSX)
203 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
204     DISABLED_RecentlyClosedTabsAndWindowsFromLastSession
205 #else
206 #define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \
207     RecentlyClosedTabsAndWindowsFromLastSession
208 #endif
209 TEST_F(RecentTabsSubMenuModelTest,
210        MAYBE_RecentlyClosedTabsAndWindowsFromLastSession) {
211   TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
212       profile(), RecentTabsSubMenuModelTest::GetTabRestoreService);
213
214   // Add 2 tabs and close them.
215   AddTab(browser(), GURL("http://wnd/tab0"));
216   AddTab(browser(), GURL("http://wnd/tab1"));
217   browser()->tab_strip_model()->CloseAllTabs();
218
219   // Create a SessionService for the profile (profile owns the service) and add
220   // a window with a tab to this session.
221   SessionService* session_service = new SessionService(profile());
222   SessionServiceFactory::SetForTestProfile(profile(), session_service);
223   SessionID tab_id;
224   SessionID window_id;
225   session_service->SetWindowType(
226       window_id, Browser::TYPE_TABBED, SessionService::TYPE_NORMAL);
227   session_service->SetTabWindow(window_id, tab_id);
228   session_service->SetTabIndexInWindow(window_id, tab_id, 0);
229   session_service->SetSelectedTabInWindow(window_id, 0);
230   session_service->UpdateTabNavigation(
231       window_id, tab_id,
232       sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
233           "http://wnd1/tab0", "title"));
234   // Set this, otherwise previous session won't be loaded.
235   profile()->set_last_session_exited_cleanly(false);
236   // Move this session to the last so that TabRestoreService will load it as the
237   // last session.
238   SessionServiceFactory::GetForProfile(profile())->
239       MoveCurrentSessionToLastSession();
240
241   // Create a new TabRestoreService so that it'll load the recently closed tabs
242   // and windows afresh.
243   TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
244       profile(), RecentTabsSubMenuModelTest::GetTabRestoreService);
245   // Let the shutdown of previous TabRestoreService run.
246   content::BrowserThread::GetBlockingPool()->FlushForTesting();
247
248   TestRecentTabsSubMenuModel model(NULL, browser(), NULL);
249   TestRecentTabsMenuModelDelegate delegate(&model);
250   EXPECT_FALSE(delegate.got_changes());
251
252   // Expected menu before tabs/windows from last session are loaded:
253   // Menu index  Menu items
254   // ----------------------------------------------------------------
255   // 0           Recently closed header
256   // 1           <separator>
257   // 2           No tabs from other Devices
258
259   int num_items = model.GetItemCount();
260   EXPECT_EQ(3, num_items);
261   EXPECT_FALSE(model.IsEnabledAt(0));
262   EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model.GetTypeAt(1));
263   EXPECT_FALSE(model.IsEnabledAt(2));
264   EXPECT_EQ(0, model.enable_count());
265
266   // Wait for tabs from last session to be loaded.
267   WaitForLoadFromLastSession();
268
269   // Expected menu after tabs/windows from last session are loaded:
270   // Menu index  Menu items
271   // --------------------------------------------------------------
272   // 0           Recently closed header
273   // 1           <window for the tab http://wnd1/tab0>
274   // 2           <tab for http://wnd0/tab1>
275   // 3           <tab for http://wnd0/tab0>
276   // 4           <separator>
277   // 5           No tabs from other Devices
278
279   EXPECT_TRUE(delegate.got_changes());
280
281   num_items = model.GetItemCount();
282   EXPECT_EQ(6, num_items);
283   EXPECT_FALSE(model.IsEnabledAt(0));
284   EXPECT_TRUE(model.IsEnabledAt(1));
285   EXPECT_TRUE(model.IsEnabledAt(2));
286   EXPECT_TRUE(model.IsEnabledAt(3));
287   model.ActivatedAt(1);
288   model.ActivatedAt(2);
289   model.ActivatedAt(3);
290   EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, model.GetTypeAt(4));
291   EXPECT_FALSE(model.IsEnabledAt(5));
292   EXPECT_EQ(3, model.enable_count());
293   EXPECT_EQ(3, model.execute_count());
294
295   EXPECT_TRUE(model.GetLabelFontAt(0) != NULL);
296   EXPECT_EQ(NULL, model.GetLabelFontAt(1));
297   EXPECT_EQ(NULL, model.GetLabelFontAt(2));
298   EXPECT_EQ(NULL, model.GetLabelFontAt(3));
299   EXPECT_EQ(NULL, model.GetLabelFontAt(4));
300   EXPECT_EQ(NULL, model.GetLabelFontAt(5));
301
302   std::string url;
303   string16 title;
304   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(0, &url, &title));
305   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(1, &url, &title));
306   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(2, &url, &title));
307   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(3, &url, &title));
308   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(4, &url, &title));
309   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(5, &url, &title));
310 }
311
312 // Test disabled "Recently closed" header with multiple sessions, multiple
313 // windows, and multiple enabled tabs from other devices.
314 TEST_F(RecentTabsSubMenuModelTest, OtherDevices) {
315   // Tabs are populated in decreasing timestamp.
316   base::Time timestamp = base::Time::Now();
317   const base::TimeDelta time_delta = base::TimeDelta::FromMinutes(10);
318
319   RecentTabsBuilderTestHelper recent_tabs_builder;
320
321   // Create 1st session : 1 window, 3 tabs
322   recent_tabs_builder.AddSession();
323   recent_tabs_builder.AddWindow(0);
324   for (int i = 0; i < 3; ++i) {
325     timestamp -= time_delta;
326     recent_tabs_builder.AddTabWithInfo(0, 0, timestamp, string16());
327   }
328
329   // Create 2nd session : 2 windows, 1 tab in 1st window, 2 tabs in 2nd window
330   recent_tabs_builder.AddSession();
331   recent_tabs_builder.AddWindow(1);
332   recent_tabs_builder.AddWindow(1);
333   timestamp -= time_delta;
334   recent_tabs_builder.AddTabWithInfo(1, 0, timestamp, string16());
335   timestamp -= time_delta;
336   recent_tabs_builder.AddTabWithInfo(1, 1, timestamp, string16());
337   timestamp -= time_delta;
338   recent_tabs_builder.AddTabWithInfo(1, 1, timestamp, string16());
339
340   recent_tabs_builder.RegisterRecentTabs(&associator_);
341
342   // Verify that data is populated correctly in RecentTabsSubMenuModel.
343   // Expected menu:
344   // - first inserted tab is most recent and hence is top
345   // Menu index  Menu items
346   // -----------------------------------------------------
347   // 0           Recently closed header (disabled)
348   // 1           <separator>
349   // 2           <section header for 1st session>
350   // 3-5         <3 tabs of the only window of session 0>
351   // 6           <separator>
352   // 7           <section header for 2nd session>
353   // 8           <the only tab of window 0 of session 1>
354   // 9-10        <2 tabs of window 1 of session 2>
355   // 11          <separator>
356   // 12          More...
357
358   TestRecentTabsSubMenuModel model(NULL, browser(), &associator_);
359   int num_items = model.GetItemCount();
360   EXPECT_EQ(13, num_items);
361   model.ActivatedAt(0);
362   EXPECT_FALSE(model.IsEnabledAt(0));
363   model.ActivatedAt(3);
364   EXPECT_TRUE(model.IsEnabledAt(3));
365   model.ActivatedAt(4);
366   EXPECT_TRUE(model.IsEnabledAt(4));
367   model.ActivatedAt(5);
368   EXPECT_TRUE(model.IsEnabledAt(5));
369   model.ActivatedAt(8);
370   EXPECT_TRUE(model.IsEnabledAt(8));
371   model.ActivatedAt(9);
372   EXPECT_TRUE(model.IsEnabledAt(9));
373   model.ActivatedAt(10);
374   EXPECT_TRUE(model.IsEnabledAt(10));
375   EXPECT_TRUE(model.IsEnabledAt(12));
376   EXPECT_EQ(7, model.enable_count());
377   EXPECT_EQ(7, model.execute_count());
378
379   EXPECT_EQ(NULL, model.GetLabelFontAt(0));
380   EXPECT_EQ(NULL, model.GetLabelFontAt(1));
381   EXPECT_TRUE(model.GetLabelFontAt(2) != NULL);
382   EXPECT_EQ(NULL, model.GetLabelFontAt(3));
383   EXPECT_EQ(NULL, model.GetLabelFontAt(4));
384   EXPECT_EQ(NULL, model.GetLabelFontAt(5));
385   EXPECT_EQ(NULL, model.GetLabelFontAt(6));
386   EXPECT_TRUE(model.GetLabelFontAt(7) != NULL);
387   EXPECT_EQ(NULL, model.GetLabelFontAt(8));
388   EXPECT_EQ(NULL, model.GetLabelFontAt(9));
389   EXPECT_EQ(NULL, model.GetLabelFontAt(10));
390   EXPECT_EQ(NULL, model.GetLabelFontAt(11));
391   EXPECT_EQ(NULL, model.GetLabelFontAt(12));
392
393   std::string url;
394   string16 title;
395   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(0, &url, &title));
396   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(1, &url, &title));
397   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(2, &url, &title));
398   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(3, &url, &title));
399   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(4, &url, &title));
400   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(5, &url, &title));
401   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(6, &url, &title));
402   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(7, &url, &title));
403   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(8, &url, &title));
404   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(9, &url, &title));
405   EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(10, &url, &title));
406   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(11, &url, &title));
407   EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(12, &url, &title));
408 }
409
410 TEST_F(RecentTabsSubMenuModelTest, MaxSessionsAndRecency) {
411   // Create 4 sessions : each session has 1 window with 1 tab each.
412   RecentTabsBuilderTestHelper recent_tabs_builder;
413   for (int s = 0; s < 4; ++s) {
414     recent_tabs_builder.AddSession();
415     recent_tabs_builder.AddWindow(s);
416     recent_tabs_builder.AddTab(s, 0);
417   }
418   recent_tabs_builder.RegisterRecentTabs(&associator_);
419
420   // Verify that data is populated correctly in RecentTabsSubMenuModel.
421   // Expected menu:
422   // - max sessions is 3, so only 3 most-recent sessions will show.
423   // Menu index  Menu items
424   // ----------------------------------------------------------
425   // 0           Recently closed header (disabled)
426   // 1           <separator>
427   // 2           <section header for 1st session>
428   // 3           <the only tab of the only window of session 3>
429   // 4           <separator>
430   // 5           <section header for 2nd session>
431   // 6           <the only tab of the only window of session 2>
432   // 7           <separator>
433   // 8           <section header for 3rd session>
434   // 9           <the only tab of the only window of session 1>
435   // 10          <separator>
436   // 11          More...
437
438   TestRecentTabsSubMenuModel model(NULL, browser(), &associator_);
439   int num_items = model.GetItemCount();
440   EXPECT_EQ(12, num_items);
441
442   std::vector<string16> tab_titles =
443       recent_tabs_builder.GetTabTitlesSortedByRecency();
444   EXPECT_EQ(tab_titles[0], model.GetLabelAt(3));
445   EXPECT_EQ(tab_titles[1], model.GetLabelAt(6));
446   EXPECT_EQ(tab_titles[2], model.GetLabelAt(9));
447 }
448
449 TEST_F(RecentTabsSubMenuModelTest, MaxTabsPerSessionAndRecency) {
450   // Create a session: 2 windows with 5 tabs each.
451   RecentTabsBuilderTestHelper recent_tabs_builder;
452   recent_tabs_builder.AddSession();
453   for (int w = 0; w < 2; ++w) {
454     recent_tabs_builder.AddWindow(0);
455     for (int t = 0; t < 5; ++t)
456       recent_tabs_builder.AddTab(0, w);
457   }
458   recent_tabs_builder.RegisterRecentTabs(&associator_);
459
460   // Verify that data is populated correctly in RecentTabsSubMenuModel.
461   // Expected menu:
462   // - max tabs per session is 4, so only 4 most-recent tabs will show,
463   //   independent of which window they came from.
464   // Menu index  Menu items
465   // ---------------------------------------------
466   // 0           Recently closed header (disabled)
467   // 1           <separator>
468   // 2           <section header for session>
469   // 3-6         <4 most-recent tabs of session>
470   // 7           <separator>
471   // 8           More...
472
473   TestRecentTabsSubMenuModel model(NULL, browser(), &associator_);
474   int num_items = model.GetItemCount();
475   EXPECT_EQ(9, num_items);
476
477   std::vector<string16> tab_titles =
478       recent_tabs_builder.GetTabTitlesSortedByRecency();
479   for (int i = 0; i < 4; ++i)
480     EXPECT_EQ(tab_titles[i], model.GetLabelAt(i + 3));
481 }
482
483 TEST_F(RecentTabsSubMenuModelTest, MaxWidth) {
484   // Create 1 session with 1 window and 1 tab.
485   RecentTabsBuilderTestHelper recent_tabs_builder;
486   recent_tabs_builder.AddSession();
487   recent_tabs_builder.AddWindow(0);
488   recent_tabs_builder.AddTab(0, 0);
489   recent_tabs_builder.RegisterRecentTabs(&associator_);
490
491   // Menu index  Menu items
492   // ----------------------------------------------------------
493   // 0           Recently closed header (disabled)
494   // 1           <separator>
495   // 2           <section header for 1st session>
496   // 3           <the only tab of the only window of session 1>
497   // 4           <separator>
498   // 5           More...
499
500   TestRecentTabsSubMenuModel model(NULL, browser(), &associator_);
501   EXPECT_EQ(6, model.GetItemCount());
502   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(0));
503   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(1));
504   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(2));
505   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(3));
506 }
507
508 TEST_F(RecentTabsSubMenuModelTest, MaxWidthNoDevices) {
509   // Expected menu:
510   // Menu index  Menu items
511   // --------------------------------------------
512   // 0           Recently closed heaer (disabled)
513   // 1           <separator>
514   // 2           No tabs from other Devices
515
516   TestRecentTabsSubMenuModel model(NULL, browser(), NULL);
517   EXPECT_EQ(3, model.GetItemCount());
518   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(0));
519   EXPECT_NE(-1, model.GetMaxWidthForItemAtIndex(1));
520   EXPECT_EQ(-1, model.GetMaxWidthForItemAtIndex(2));
521 }