| OLD | NEW |
| (Empty) | |
| 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/rand_util.h" |
| 8 #include "base/string_number_conversions.h" |
| 9 #include "base/stringprintf.h" |
| 10 #include "chrome/app/chrome_command_ids.h" |
| 11 #include "chrome/browser/sessions/session_types.h" |
| 12 #include "chrome/browser/sessions/session_types_test_helper.h" |
| 13 #include "chrome/browser/sync/glue/session_model_associator.h" |
| 14 #include "chrome/browser/sync/glue/synced_session.h" |
| 15 #include "chrome/browser/sync/profile_sync_service_mock.h" |
| 16 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/browser_tabstrip.h" |
| 18 #include "chrome/test/base/browser_with_test_window_test.h" |
| 19 #include "chrome/test/base/menu_model_test.h" |
| 20 #include "chrome/test/base/testing_profile.h" |
| 21 #include "grit/generated_resources.h" |
| 22 #include "sync/protocol/session_specifics.pb.h" |
| 23 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" |
| 25 |
| 26 namespace { |
| 27 |
| 28 const char kBaseSessionTag[] = "session_tag"; |
| 29 const char kBaseSessionName[] = "session_name"; |
| 30 const char kBaseTabUrl[] = "http://foo/?"; |
| 31 const char kTabTitleFormat[] = "session=%d;window=%d;tab=%d"; |
| 32 |
| 33 struct TabTime { |
| 34 TabTime(SessionID::id_type session_id, |
| 35 SessionID::id_type window_id, |
| 36 SessionID::id_type tab_id, |
| 37 const base::Time& timestamp) |
| 38 : session_id(session_id), |
| 39 window_id(window_id), |
| 40 tab_id(tab_id), |
| 41 timestamp(timestamp) {} |
| 42 |
| 43 SessionID::id_type session_id; |
| 44 SessionID::id_type window_id; |
| 45 SessionID::id_type tab_id; |
| 46 base::Time timestamp; |
| 47 }; |
| 48 |
| 49 bool SortTabTimesByRecency(const TabTime& t1, const TabTime& t2) { |
| 50 return t1.timestamp > t2.timestamp; |
| 51 } |
| 52 |
| 53 std::string ToSessionTag(SessionID::id_type session_id) { |
| 54 return std::string(kBaseSessionTag + base::IntToString(session_id)); |
| 55 } |
| 56 |
| 57 std::string ToSessionName(SessionID::id_type session_id) { |
| 58 return std::string(kBaseSessionName + base::IntToString(session_id)); |
| 59 } |
| 60 |
| 61 std::string ToTabTitle(SessionID::id_type session_id, |
| 62 SessionID::id_type window_id, |
| 63 SessionID::id_type tab_id) { |
| 64 return base::StringPrintf(kTabTitleFormat, session_id, window_id, tab_id); |
| 65 } |
| 66 |
| 67 std::string ToTabUrl(SessionID::id_type session_id, |
| 68 SessionID::id_type window_id, |
| 69 SessionID::id_type tab_id) { |
| 70 return std::string(kBaseTabUrl + ToTabTitle(session_id, window_id, tab_id)); |
| 71 } |
| 72 |
| 73 void BuildSessionSpecifics(SessionID::id_type session_id, |
| 74 sync_pb::SessionSpecifics* meta) { |
| 75 meta->set_session_tag(ToSessionTag(session_id)); |
| 76 sync_pb::SessionHeader* header = meta->mutable_header(); |
| 77 header->set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_CROS); |
| 78 header->set_client_name(ToSessionName(session_id)); |
| 79 } |
| 80 |
| 81 void AddWindowSpecifics(int window_id, int num_tabs, int* tab_id, |
| 82 std::vector<SessionID::id_type>* tab_ids, |
| 83 sync_pb::SessionSpecifics* meta) { |
| 84 sync_pb::SessionHeader* header = meta->mutable_header(); |
| 85 sync_pb::SessionWindow* window = header->add_window(); |
| 86 window->set_window_id(window_id); |
| 87 window->set_selected_tab_index(0); |
| 88 window->set_browser_type(sync_pb::SessionWindow_BrowserType_TYPE_TABBED); |
| 89 for (int i = 0; i < num_tabs; ++i) { |
| 90 SessionID::id_type id = (*tab_id)++; |
| 91 window->add_tab(id); |
| 92 tab_ids->push_back(id); |
| 93 } |
| 94 } |
| 95 |
| 96 void BuildTabsSpecifics(SessionID::id_type session_id, |
| 97 SessionID::id_type window_id, |
| 98 const std::vector<SessionID::id_type>& tab_ids, |
| 99 std::vector<sync_pb::SessionSpecifics>* tab_bases) { |
| 100 tab_bases->resize(tab_ids.size()); |
| 101 for (size_t i = 0; i < tab_ids.size(); ++i) { |
| 102 SessionID::id_type tab_id = tab_ids[i]; |
| 103 sync_pb::SessionSpecifics& tab_base = (*tab_bases)[i]; |
| 104 tab_base.set_session_tag(ToSessionTag(session_id)); |
| 105 sync_pb::SessionTab* tab = tab_base.mutable_tab(); |
| 106 tab->set_window_id(window_id); |
| 107 tab->set_tab_id(tab_id); |
| 108 tab->set_tab_visual_index(1); |
| 109 tab->set_current_navigation_index(0); |
| 110 tab->set_pinned(true); |
| 111 tab->set_extension_app_id("app_id"); |
| 112 sync_pb::TabNavigation* navigation = tab->add_navigation(); |
| 113 navigation->set_virtual_url(ToTabUrl(session_id, window_id, tab_id)); |
| 114 navigation->set_referrer("referrer"); |
| 115 navigation->set_title(ToTabTitle(session_id, window_id, tab_id)); |
| 116 navigation->set_page_transition(sync_pb::SyncEnums_PageTransition_TYPED); |
| 117 } |
| 118 } |
| 119 |
| 120 // This copies parts of MenuModelTest::Delegate and combines them with the |
| 121 // RecentTabsSubMenuModel since RecentTabsSubMenuModel is a |
| 122 // SimpleMenuModel::Delegate and not just derived from SimpleMenuModel. |
| 123 class TestRecentTabsSubMenuModel : public RecentTabsSubMenuModel { |
| 124 public: |
| 125 TestRecentTabsSubMenuModel(ui::AcceleratorProvider* provider, |
| 126 Browser* browser, |
| 127 browser_sync::SessionModelAssociator* associator, |
| 128 bool can_restore_tab) |
| 129 : RecentTabsSubMenuModel(provider, browser, associator), |
| 130 can_restore_tab_(can_restore_tab), |
| 131 execute_count_(0), |
| 132 enable_count_(0) { |
| 133 } |
| 134 |
| 135 // Testing overrides to ui::SimpleMenuModel::Delegate: |
| 136 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE { |
| 137 bool val = command_id == IDC_RESTORE_TAB ? can_restore_tab_ : |
| 138 RecentTabsSubMenuModel::IsCommandIdEnabled(command_id); |
| 139 if (val) |
| 140 ++enable_count_; |
| 141 return val; |
| 142 } |
| 143 |
| 144 virtual void ExecuteCommand(int command_id) OVERRIDE { |
| 145 ++execute_count_; |
| 146 } |
| 147 |
| 148 bool can_restore_tab_; |
| 149 int execute_count_; |
| 150 int mutable enable_count_; // Mutable because IsCommandIdEnabledAt is const. |
| 151 }; |
| 152 |
| 153 } // namespace |
| 154 |
| 155 class RecentTabsSubMenuModelTest : public BrowserWithTestWindowTest, |
| 156 public ui::AcceleratorProvider { |
| 157 public: |
| 158 RecentTabsSubMenuModelTest() |
| 159 : sync_service_(&testing_profile_), |
| 160 associator_(&sync_service_, true) { |
| 161 associator_.SetCurrentMachineTagForTesting("RecentTabsSubMenuModelTest"); |
| 162 } |
| 163 |
| 164 // Don't handle accelerators. |
| 165 virtual bool GetAcceleratorForCommandId( |
| 166 int command_id, |
| 167 ui::Accelerator* accelerator) OVERRIDE { |
| 168 return false; |
| 169 } |
| 170 |
| 171 private: |
| 172 TestingProfile testing_profile_; |
| 173 testing::NiceMock<ProfileSyncServiceMock> sync_service_; |
| 174 |
| 175 protected: |
| 176 browser_sync::SessionModelAssociator associator_; |
| 177 }; |
| 178 |
| 179 // Test disabled "Reopen closed tab" with no foreign tabs. |
| 180 TEST_F(RecentTabsSubMenuModelTest, NoTabs) { |
| 181 TestRecentTabsSubMenuModel model(this, browser(), NULL, false); |
| 182 |
| 183 // Expected menu: |
| 184 // Menu index Menu items |
| 185 // -------------------------------------- |
| 186 // 0 Reopen closed tab |
| 187 // 1 <separator> |
| 188 // 2 No tabs from other Devices |
| 189 |
| 190 int num_items = model.GetItemCount(); |
| 191 EXPECT_EQ(3, num_items); |
| 192 EXPECT_FALSE(model.IsEnabledAt(0)); |
| 193 EXPECT_FALSE(model.IsEnabledAt(2)); |
| 194 EXPECT_EQ(0, model.enable_count_); |
| 195 } |
| 196 |
| 197 // Test enabled "Reopen closed tab" with no foreign tabs. |
| 198 TEST_F(RecentTabsSubMenuModelTest, ReopenClosedTab) { |
| 199 TestRecentTabsSubMenuModel model(this, browser(), NULL, true); |
| 200 // Menu contents are identical to NoTabs test. |
| 201 int num_items = model.GetItemCount(); |
| 202 EXPECT_EQ(3, num_items); |
| 203 EXPECT_TRUE(model.IsEnabledAt(0)); |
| 204 model.ActivatedAt(0); |
| 205 EXPECT_FALSE(model.IsEnabledAt(2)); |
| 206 EXPECT_EQ(1, model.enable_count_); |
| 207 EXPECT_EQ(1, model.execute_count_); |
| 208 } |
| 209 |
| 210 // Test enabled "Reopen closed tab" with multiple sessions, multiple windows, |
| 211 // and multiple enabled tabs from other devices. |
| 212 TEST_F(RecentTabsSubMenuModelTest, OtherDevices) { |
| 213 SessionID::id_type id = 0; |
| 214 std::vector<SessionID::id_type> session_ids; |
| 215 // Tabs are populated in decreasing timestamp. |
| 216 base::Time now = base::Time::Now(); |
| 217 |
| 218 // Create 1st session : 1 window, 3 tabs |
| 219 SessionID::id_type session_id = id++; |
| 220 session_ids.push_back(session_id); |
| 221 sync_pb::SessionSpecifics meta1; |
| 222 BuildSessionSpecifics(session_id, &meta1); |
| 223 SessionID::id_type window_id = id++; |
| 224 std::vector<SessionID::id_type> tab_ids; |
| 225 AddWindowSpecifics(window_id, 3, &id, &tab_ids, &meta1); |
| 226 std::vector<sync_pb::SessionSpecifics> tabs; |
| 227 BuildTabsSpecifics(session_id, window_id, tab_ids, &tabs); |
| 228 base::Time timestamp = now - base::TimeDelta::FromMinutes(window_id * 10); |
| 229 // First tab's timestamp is the most recent in session, so use it as session's |
| 230 // modified time. |
| 231 associator_.AssociateForeignSpecifics(meta1, timestamp); |
| 232 std::vector<base::Time> tab_times; |
| 233 for (size_t i = 0; i < tabs.size(); ++i) |
| 234 tab_times.push_back(timestamp - base::TimeDelta::FromMinutes(i)); |
| 235 for (size_t i = 0; i < tabs.size(); ++i) |
| 236 associator_.AssociateForeignSpecifics(tabs[i], tab_times[i]); |
| 237 |
| 238 // Create 2nd session : 2 windows, 1 tab in 1st window, 2 tabs in 2nd window |
| 239 session_id = id++; |
| 240 session_ids.push_back(session_id); |
| 241 sync_pb::SessionSpecifics meta2; |
| 242 BuildSessionSpecifics(session_id, &meta2); |
| 243 window_id = id++; |
| 244 std::vector<SessionID::id_type> tab_ids1; |
| 245 AddWindowSpecifics(window_id, 1, &id, &tab_ids1, &meta2); |
| 246 std::vector<sync_pb::SessionSpecifics> tabs1; |
| 247 BuildTabsSpecifics(session_id, window_id, tab_ids1, &tabs1); |
| 248 timestamp = now - base::TimeDelta::FromMinutes(window_id * 10); |
| 249 associator_.AssociateForeignSpecifics(meta2, timestamp); |
| 250 std::vector<base::Time> tab_times1; |
| 251 for (size_t i = 0; i < tabs1.size(); ++i) |
| 252 tab_times1.push_back(timestamp - base::TimeDelta::FromMinutes(i)); |
| 253 for (size_t i = 0; i < tabs1.size(); ++i) |
| 254 associator_.AssociateForeignSpecifics(tabs1[i], tab_times1[i]); |
| 255 window_id = id++; |
| 256 std::vector<SessionID::id_type> tab_ids2; |
| 257 AddWindowSpecifics(window_id, 2, &id, &tab_ids2, &meta2); |
| 258 std::vector<sync_pb::SessionSpecifics> tabs2; |
| 259 BuildTabsSpecifics(session_id, window_id, tab_ids2, &tabs2); |
| 260 timestamp = now - base::TimeDelta::FromMinutes(window_id * 10); |
| 261 // First tab's timestamp is the most recent in session, so use it as session's |
| 262 // modified time. |
| 263 associator_.AssociateForeignSpecifics(meta2, timestamp); |
| 264 std::vector<base::Time> tab_times2; |
| 265 for (size_t i = 0; i < tabs2.size(); ++i) |
| 266 tab_times2.push_back(timestamp - base::TimeDelta::FromMinutes(i)); |
| 267 for (size_t i = 0; i < tabs2.size(); ++i) |
| 268 associator_.AssociateForeignSpecifics(tabs2[i], tab_times2[i]); |
| 269 |
| 270 // Make sure data is populated correctly in SessionModelAssociator. |
| 271 std::vector<const browser_sync::SyncedSession*> sessions; |
| 272 ASSERT_TRUE(associator_.GetAllForeignSessions(&sessions)); |
| 273 ASSERT_EQ(2U, sessions.size()); |
| 274 std::vector<const SessionWindow*> windows; |
| 275 ASSERT_TRUE(associator_.GetForeignSession(ToSessionTag(session_ids[0]), |
| 276 &windows)); |
| 277 ASSERT_EQ(1U, windows.size()); |
| 278 ASSERT_EQ(3U, windows[0]->tabs.size()); |
| 279 windows.clear(); |
| 280 ASSERT_TRUE(associator_.GetForeignSession(ToSessionTag(session_ids[1]), |
| 281 &windows)); |
| 282 ASSERT_EQ(2U, windows.size()); |
| 283 ASSERT_EQ(1U, windows[0]->tabs.size()); |
| 284 ASSERT_EQ(2U, windows[1]->tabs.size()); |
| 285 |
| 286 // Verify that data is populated correctly in RecentTabsSubMenuModel. |
| 287 // Expected menu: |
| 288 // - first inserted tab is most recent and hence is top |
| 289 // Menu index Menu items |
| 290 // -------------------------------------- |
| 291 // 0 Reopen closed tab |
| 292 // 1 <separator> |
| 293 // 2 <section header for 1st session> |
| 294 // 3-5 <3 tabs of the only window of session 0> |
| 295 // 6 <separator> |
| 296 // 7 <section header for 2nd session> |
| 297 // 8 <the only tab of window 0 of session 1> |
| 298 // 9-10 <2 tabs of window 1 of session 2> |
| 299 |
| 300 TestRecentTabsSubMenuModel model(this, browser(), &associator_, true); |
| 301 int num_items = model.GetItemCount(); |
| 302 EXPECT_EQ(11, num_items); |
| 303 model.ActivatedAt(0); |
| 304 EXPECT_TRUE(model.IsEnabledAt(0)); |
| 305 model.ActivatedAt(3); |
| 306 EXPECT_TRUE(model.IsEnabledAt(3)); |
| 307 model.ActivatedAt(4); |
| 308 EXPECT_TRUE(model.IsEnabledAt(4)); |
| 309 model.ActivatedAt(5); |
| 310 EXPECT_TRUE(model.IsEnabledAt(5)); |
| 311 model.ActivatedAt(8); |
| 312 EXPECT_TRUE(model.IsEnabledAt(8)); |
| 313 model.ActivatedAt(9); |
| 314 EXPECT_TRUE(model.IsEnabledAt(9)); |
| 315 model.ActivatedAt(10); |
| 316 EXPECT_TRUE(model.IsEnabledAt(10)); |
| 317 EXPECT_EQ(7, model.enable_count_); |
| 318 EXPECT_EQ(7, model.execute_count_); |
| 319 } |
| 320 |
| 321 TEST_F(RecentTabsSubMenuModelTest, MaxSessionsAndRecency) { |
| 322 SessionID::id_type id = 0; |
| 323 std::vector<SessionID::id_type> session_ids; |
| 324 base::Time now = base::Time::Now(); |
| 325 |
| 326 // Create 4 sessions : each session has 1 window with 1 tab each. |
| 327 std::vector<TabTime> tab_times; |
| 328 for (int i = 0; i < 4; ++i) { |
| 329 SessionID::id_type session_id = id++; |
| 330 session_ids.push_back(session_id); |
| 331 sync_pb::SessionSpecifics meta; |
| 332 BuildSessionSpecifics(session_id, &meta); |
| 333 SessionID::id_type window_id = id++; |
| 334 std::vector<SessionID::id_type> tab_ids; |
| 335 AddWindowSpecifics(window_id, 1, &id, &tab_ids, &meta); |
| 336 std::vector<sync_pb::SessionSpecifics> tabs; |
| 337 BuildTabsSpecifics(session_id, window_id, tab_ids, &tabs); |
| 338 base::Time timestamp = |
| 339 now + base::TimeDelta::FromMinutes(base::RandUint64()); |
| 340 tab_times.push_back(TabTime(session_id, window_id, tab_ids[0], timestamp)); |
| 341 // Use tab's timestamp as session's modified time. |
| 342 associator_.AssociateForeignSpecifics(meta, timestamp); |
| 343 associator_.AssociateForeignSpecifics(tabs[0], timestamp); |
| 344 } |
| 345 |
| 346 // Make sure data is populated correctly in SessionModelAssociator. |
| 347 std::vector<const browser_sync::SyncedSession*> sessions; |
| 348 ASSERT_TRUE(associator_.GetAllForeignSessions(&sessions)); |
| 349 ASSERT_EQ(4U, sessions.size()); |
| 350 std::vector<const SessionWindow*> windows; |
| 351 for (size_t i = 0; i < sessions.size(); ++i) { |
| 352 ASSERT_TRUE(associator_.GetForeignSession(ToSessionTag(session_ids[i]), |
| 353 &windows)); |
| 354 ASSERT_EQ(1U, windows.size()); |
| 355 ASSERT_EQ(1U, windows[0]->tabs.size()); |
| 356 } |
| 357 |
| 358 // Verify that data is populated correctly in RecentTabsSubMenuModel. |
| 359 // Expected menu: |
| 360 // - max sessions is 3, so only 3 most-recent sessions will show |
| 361 // Menu index Menu items |
| 362 // -------------------------------------- |
| 363 // 0 Reopen closed tab |
| 364 // 1 <separator> |
| 365 // 2 <section header for 1st session> |
| 366 // 3 <the only tab of the only window of session 3> |
| 367 // 4 <separator> |
| 368 // 5 <section header for 2nd session> |
| 369 // 6 <the only tab of the only window of session 2> |
| 370 // 7 <separator> |
| 371 // 8 <section header for 3rd session> |
| 372 // 9 <the only tab of the only window of session 1> |
| 373 |
| 374 TestRecentTabsSubMenuModel model(this, browser(), &associator_, true); |
| 375 int num_items = model.GetItemCount(); |
| 376 EXPECT_EQ(10, num_items); |
| 377 |
| 378 sort(tab_times.begin(), tab_times.end(), SortTabTimesByRecency); |
| 379 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[0].session_id, |
| 380 tab_times[0].window_id, |
| 381 tab_times[0].tab_id)), |
| 382 model.GetLabelAt(3)); |
| 383 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[1].session_id, |
| 384 tab_times[1].window_id, |
| 385 tab_times[1].tab_id)), |
| 386 model.GetLabelAt(6)); |
| 387 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[2].session_id, |
| 388 tab_times[2].window_id, |
| 389 tab_times[2].tab_id)), |
| 390 model.GetLabelAt(9)); |
| 391 } |
| 392 |
| 393 TEST_F(RecentTabsSubMenuModelTest, MaxTabsPerSessionAndRecency) { |
| 394 SessionID::id_type id = 0; |
| 395 base::Time now = base::Time::Now(); |
| 396 |
| 397 // Create a session: 2 windows with 5 tabs each. |
| 398 std::vector<TabTime> tab_times; |
| 399 SessionID::id_type session_id = id++; |
| 400 sync_pb::SessionSpecifics meta; |
| 401 BuildSessionSpecifics(session_id, &meta); |
| 402 for (int i = 0; i < 2; ++i) { |
| 403 SessionID::id_type window_id = id++; |
| 404 std::vector<SessionID::id_type> tab_ids; |
| 405 AddWindowSpecifics(window_id, 5, &id, &tab_ids, &meta); |
| 406 std::vector<sync_pb::SessionSpecifics> tabs; |
| 407 BuildTabsSpecifics(session_id, window_id, tab_ids, &tabs); |
| 408 // There's no session recency sorting with only one session, so just use now |
| 409 // as session's modified time. |
| 410 associator_.AssociateForeignSpecifics(meta, now); |
| 411 for (size_t i = 0; i < tabs.size(); ++i) { |
| 412 base::Time timestamp = now + |
| 413 base::TimeDelta::FromMinutes(base::RandUint64()); |
| 414 tab_times.push_back(TabTime(session_id, window_id, tab_ids[i], |
| 415 timestamp)); |
| 416 associator_.AssociateForeignSpecifics(tabs[i], timestamp); |
| 417 } |
| 418 } |
| 419 |
| 420 // Make sure data is populated correctly in SessionModelAssociator. |
| 421 std::vector<const browser_sync::SyncedSession*> sessions; |
| 422 ASSERT_TRUE(associator_.GetAllForeignSessions(&sessions)); |
| 423 ASSERT_EQ(1U, sessions.size()); |
| 424 std::vector<const SessionWindow*> windows; |
| 425 ASSERT_TRUE(associator_.GetForeignSession(ToSessionTag(session_id), |
| 426 &windows)); |
| 427 ASSERT_EQ(2U, windows.size()); |
| 428 ASSERT_EQ(5U, windows[0]->tabs.size()); |
| 429 ASSERT_EQ(5U, windows[1]->tabs.size()); |
| 430 |
| 431 // Verify that data is populated correctly in RecentTabsSubMenuModel. |
| 432 // Expected menu: |
| 433 // - max tabs per session is 4, so only 4 most-recent tabs will show, |
| 434 // independent of which window they came from |
| 435 // Menu index Menu items |
| 436 // -------------------------------------- |
| 437 // 0 Reopen closed tab |
| 438 // 1 <separator> |
| 439 // 2 <section header for session> |
| 440 // 3-6 <4 most-recent tabs of session> |
| 441 |
| 442 TestRecentTabsSubMenuModel model(this, browser(), &associator_, true); |
| 443 int num_items = model.GetItemCount(); |
| 444 EXPECT_EQ(7, num_items); |
| 445 |
| 446 sort(tab_times.begin(), tab_times.end(), SortTabTimesByRecency); |
| 447 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[0].session_id, |
| 448 tab_times[0].window_id, |
| 449 tab_times[0].tab_id)), |
| 450 model.GetLabelAt(3)); |
| 451 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[1].session_id, |
| 452 tab_times[1].window_id, |
| 453 tab_times[1].tab_id)), |
| 454 model.GetLabelAt(4)); |
| 455 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[2].session_id, |
| 456 tab_times[2].window_id, |
| 457 tab_times[2].tab_id)), |
| 458 model.GetLabelAt(5)); |
| 459 EXPECT_EQ(UTF8ToUTF16(ToTabTitle(tab_times[3].session_id, |
| 460 tab_times[3].window_id, |
| 461 tab_times[3].tab_id)), |
| 462 model.GetLabelAt(6)); |
| 463 } |
| OLD | NEW |