OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h" | 5 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/prefs/scoped_user_pref_update.h" | 9 #include "base/prefs/scoped_user_pref_update.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 const int kFirstLocalTabCommandId = WrenchMenuModel::kMinRecentTabsCommandId; | 62 const int kFirstLocalTabCommandId = WrenchMenuModel::kMinRecentTabsCommandId; |
63 const int kFirstLocalWindowCommandId = 1031; | 63 const int kFirstLocalWindowCommandId = 1031; |
64 const int kFirstOtherDevicesTabCommandId = 1051; | 64 const int kFirstOtherDevicesTabCommandId = 1051; |
65 const int kMinDeviceNameCommandId = 1100; | 65 const int kMinDeviceNameCommandId = 1100; |
66 const int kMaxDeviceNameCommandId = 1110; | 66 const int kMaxDeviceNameCommandId = 1110; |
67 | 67 |
68 // The maximum number of local recently closed entries (tab or window) to be | 68 // The maximum number of local recently closed entries (tab or window) to be |
69 // shown in the menu. | 69 // shown in the menu. |
70 const int kMaxLocalEntries = 8; | 70 const int kMaxLocalEntries = 8; |
71 | 71 |
| 72 // Index of the separator that follows the history menu item. Used as a |
| 73 // reference position for inserting local entries. |
| 74 const int kHistorySeparatorIndex = 1; |
| 75 |
72 // Comparator function for use with std::sort that will sort sessions by | 76 // Comparator function for use with std::sort that will sort sessions by |
73 // descending modified_time (i.e., most recent first). | 77 // descending modified_time (i.e., most recent first). |
74 bool SortSessionsByRecency(const sync_driver::SyncedSession* s1, | 78 bool SortSessionsByRecency(const sync_driver::SyncedSession* s1, |
75 const sync_driver::SyncedSession* s2) { | 79 const sync_driver::SyncedSession* s2) { |
76 return s1->modified_time > s2->modified_time; | 80 return s1->modified_time > s2->modified_time; |
77 } | 81 } |
78 | 82 |
79 // Comparator function for use with std::sort that will sort tabs by | 83 // Comparator function for use with std::sort that will sort tabs by |
80 // descending timestamp (i.e., most recent first). | 84 // descending timestamp (i.e., most recent first). |
81 bool SortTabsByRecency(const sessions::SessionTab* t1, | 85 bool SortTabsByRecency(const sessions::SessionTab* t1, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 const int RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId = 1120; | 168 const int RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId = 1120; |
165 const int RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId = 1121; | 169 const int RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId = 1121; |
166 | 170 |
167 RecentTabsSubMenuModel::RecentTabsSubMenuModel( | 171 RecentTabsSubMenuModel::RecentTabsSubMenuModel( |
168 ui::AcceleratorProvider* accelerator_provider, | 172 ui::AcceleratorProvider* accelerator_provider, |
169 Browser* browser, | 173 Browser* browser, |
170 sync_driver::OpenTabsUIDelegate* open_tabs_delegate) | 174 sync_driver::OpenTabsUIDelegate* open_tabs_delegate) |
171 : ui::SimpleMenuModel(this), | 175 : ui::SimpleMenuModel(this), |
172 browser_(browser), | 176 browser_(browser), |
173 open_tabs_delegate_(open_tabs_delegate), | 177 open_tabs_delegate_(open_tabs_delegate), |
174 last_local_model_index_(-1), | 178 last_local_model_index_(kHistorySeparatorIndex), |
175 default_favicon_( | 179 default_favicon_(ui::ResourceBundle::GetSharedInstance(). |
176 ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( | 180 GetNativeImageNamed(IDR_DEFAULT_FAVICON)), |
177 IDR_DEFAULT_FAVICON)), | |
178 weak_ptr_factory_(this) { | 181 weak_ptr_factory_(this) { |
179 // Invoke asynchronous call to load tabs from local last session, which does | 182 // Invoke asynchronous call to load tabs from local last session, which does |
180 // nothing if the tabs have already been loaded or they shouldn't be loaded. | 183 // nothing if the tabs have already been loaded or they shouldn't be loaded. |
181 // TabRestoreServiceChanged() will be called after the tabs are loaded. | 184 // TabRestoreServiceChanged() will be called after the tabs are loaded. |
182 TabRestoreService* service = | 185 TabRestoreService* service = |
183 TabRestoreServiceFactory::GetForProfile(browser_->profile()); | 186 TabRestoreServiceFactory::GetForProfile(browser_->profile()); |
184 if (service) { | 187 if (service) { |
185 service->LoadTabsFromLastSession(); | 188 service->LoadTabsFromLastSession(); |
186 | 189 |
187 // TODO(sail): enable this when mac implements the dynamic menu, together with | 190 // TODO(sail): enable this when mac implements the dynamic menu, together with |
(...skipping 16 matching lines...) Expand all Loading... |
204 accel_data.modifiers); | 207 accel_data.modifiers); |
205 break; | 208 break; |
206 } | 209 } |
207 } | 210 } |
208 #else | 211 #else |
209 if (accelerator_provider) { | 212 if (accelerator_provider) { |
210 accelerator_provider->GetAcceleratorForCommandId( | 213 accelerator_provider->GetAcceleratorForCommandId( |
211 IDC_RESTORE_TAB, &reopen_closed_tab_accelerator_); | 214 IDC_RESTORE_TAB, &reopen_closed_tab_accelerator_); |
212 } | 215 } |
213 #endif // defined(USE_ASH) | 216 #endif // defined(USE_ASH) |
| 217 |
| 218 if (accelerator_provider) { |
| 219 accelerator_provider->GetAcceleratorForCommandId( |
| 220 IDC_SHOW_HISTORY, &show_history_accelerator_); |
| 221 } |
214 } | 222 } |
215 | 223 |
216 RecentTabsSubMenuModel::~RecentTabsSubMenuModel() { | 224 RecentTabsSubMenuModel::~RecentTabsSubMenuModel() { |
217 TabRestoreService* service = | 225 TabRestoreService* service = |
218 TabRestoreServiceFactory::GetForProfile(browser_->profile()); | 226 TabRestoreServiceFactory::GetForProfile(browser_->profile()); |
219 if (service) | 227 if (service) |
220 service->RemoveObserver(this); | 228 service->RemoveObserver(this); |
221 } | 229 } |
222 | 230 |
223 bool RecentTabsSubMenuModel::IsCommandIdChecked(int command_id) const { | 231 bool RecentTabsSubMenuModel::IsCommandIdChecked(int command_id) const { |
(...skipping 15 matching lines...) Expand all Loading... |
239 // If there are no recently closed items, we show the accelerator beside | 247 // If there are no recently closed items, we show the accelerator beside |
240 // the header, otherwise, we show it beside the first item underneath it. | 248 // the header, otherwise, we show it beside the first item underneath it. |
241 int index_in_menu = GetIndexOfCommandId(command_id); | 249 int index_in_menu = GetIndexOfCommandId(command_id); |
242 int header_index = GetIndexOfCommandId(kRecentlyClosedHeaderCommandId); | 250 int header_index = GetIndexOfCommandId(kRecentlyClosedHeaderCommandId); |
243 if ((command_id == kDisabledRecentlyClosedHeaderCommandId || | 251 if ((command_id == kDisabledRecentlyClosedHeaderCommandId || |
244 (header_index != -1 && index_in_menu == header_index + 1)) && | 252 (header_index != -1 && index_in_menu == header_index + 1)) && |
245 reopen_closed_tab_accelerator_.key_code() != ui::VKEY_UNKNOWN) { | 253 reopen_closed_tab_accelerator_.key_code() != ui::VKEY_UNKNOWN) { |
246 *accelerator = reopen_closed_tab_accelerator_; | 254 *accelerator = reopen_closed_tab_accelerator_; |
247 return true; | 255 return true; |
248 } | 256 } |
| 257 |
| 258 if (command_id == IDC_SHOW_HISTORY) { |
| 259 *accelerator = show_history_accelerator_; |
| 260 return true; |
| 261 } |
| 262 |
249 return false; | 263 return false; |
250 } | 264 } |
251 | 265 |
252 void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) { | 266 void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) { |
253 if (command_id == IDC_SHOW_HISTORY) { | 267 if (command_id == IDC_SHOW_HISTORY) { |
254 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", SHOW_MORE, | 268 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", SHOW_MORE, |
255 LIMIT_RECENT_TAB_ACTION); | 269 LIMIT_RECENT_TAB_ACTION); |
256 // We show all "other devices" on the history page. | 270 // We show all "other devices" on the history page. |
257 chrome::ExecuteCommandWithDisposition(browser_, IDC_SHOW_HISTORY, | 271 chrome::ExecuteCommandWithDisposition(browser_, IDC_SHOW_HISTORY, |
258 ui::DispositionFromEventFlags(event_flags)); | 272 ui::DispositionFromEventFlags(event_flags)); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 const TabNavigationItem& item = (*tab_items)[tab_items_idx]; | 374 const TabNavigationItem& item = (*tab_items)[tab_items_idx]; |
361 *url = item.url.possibly_invalid_spec(); | 375 *url = item.url.possibly_invalid_spec(); |
362 *title = item.title; | 376 *title = item.title; |
363 return true; | 377 return true; |
364 } | 378 } |
365 return false; | 379 return false; |
366 } | 380 } |
367 | 381 |
368 void RecentTabsSubMenuModel::Build() { | 382 void RecentTabsSubMenuModel::Build() { |
369 // The menu contains: | 383 // The menu contains: |
| 384 // - History to open the full history tab. |
| 385 // - Separator |
370 // - Recently closed header, then list of local recently closed tabs/windows, | 386 // - Recently closed header, then list of local recently closed tabs/windows, |
371 // then separator | 387 // then separator |
372 // - device 1 section header, then list of tabs from device, then separator | 388 // - device 1 section header, then list of tabs from device, then separator |
373 // - device 2 section header, then list of tabs from device, then separator | 389 // - device 2 section header, then list of tabs from device, then separator |
374 // - device 3 section header, then list of tabs from device, then separator | 390 // - device 3 section header, then list of tabs from device, then separator |
375 // - More... to open the history tab to get more other devices. | |
376 // |local_tab_navigation_items_| and |other_devices_tab_navigation_items_| | 391 // |local_tab_navigation_items_| and |other_devices_tab_navigation_items_| |
377 // only contain navigatable (and hence executable) tab items for local | 392 // only contain navigatable (and hence executable) tab items for local |
378 // recently closed tabs and tabs from other devices respectively. | 393 // recently closed tabs and tabs from other devices respectively. |
379 // |local_window_items_| contains the local recently closed windows. | 394 // |local_window_items_| contains the local recently closed windows. |
| 395 InsertItemWithStringIdAt(0, IDC_SHOW_HISTORY, IDS_SHOW_HISTORY); |
| 396 InsertSeparatorAt(1, ui::NORMAL_SEPARATOR); |
380 BuildLocalEntries(); | 397 BuildLocalEntries(); |
381 BuildTabsFromOtherDevices(); | 398 BuildTabsFromOtherDevices(); |
382 } | 399 } |
383 | 400 |
384 void RecentTabsSubMenuModel::BuildLocalEntries() { | 401 void RecentTabsSubMenuModel::BuildLocalEntries() { |
| 402 last_local_model_index_ = kHistorySeparatorIndex; |
| 403 |
385 // All local items use InsertItem*At() to append or insert a menu item. | 404 // All local items use InsertItem*At() to append or insert a menu item. |
386 // We're appending if building the entries for the first time i.e. invoked | 405 // We're appending if building the entries for the first time i.e. invoked |
387 // from Constructor(), inserting when local entries change subsequently i.e. | 406 // from Constructor(), inserting when local entries change subsequently i.e. |
388 // invoked from TabRestoreServiceChanged(). | 407 // invoked from TabRestoreServiceChanged(). |
389 | |
390 DCHECK_EQ(last_local_model_index_, -1); | |
391 | |
392 TabRestoreService* service = | 408 TabRestoreService* service = |
393 TabRestoreServiceFactory::GetForProfile(browser_->profile()); | 409 TabRestoreServiceFactory::GetForProfile(browser_->profile()); |
| 410 |
394 if (!service || service->entries().size() == 0) { | 411 if (!service || service->entries().size() == 0) { |
395 // This is to show a disabled restore tab entry with the accelerator to | 412 // This is to show a disabled restore tab entry with the accelerator to |
396 // teach users about this command. | 413 // teach users about this command. |
397 InsertItemWithStringIdAt(++last_local_model_index_, | 414 InsertItemWithStringIdAt(++last_local_model_index_, |
398 kDisabledRecentlyClosedHeaderCommandId, | 415 kDisabledRecentlyClosedHeaderCommandId, |
399 IDS_RECENTLY_CLOSED); | 416 IDS_RECENTLY_CLOSED); |
400 } else { | 417 } else { |
401 InsertItemWithStringIdAt(++last_local_model_index_, | 418 InsertItemWithStringIdAt(++last_local_model_index_, |
402 kRecentlyClosedHeaderCommandId, | 419 kRecentlyClosedHeaderCommandId, |
403 IDS_RECENTLY_CLOSED); | 420 IDS_RECENTLY_CLOSED); |
(...skipping 19 matching lines...) Expand all Loading... |
423 } else { | 440 } else { |
424 DCHECK_EQ(entry->type, TabRestoreService::WINDOW); | 441 DCHECK_EQ(entry->type, TabRestoreService::WINDOW); |
425 BuildLocalWindowItem( | 442 BuildLocalWindowItem( |
426 entry->id, | 443 entry->id, |
427 static_cast<TabRestoreService::Window*>(entry)->tabs.size(), | 444 static_cast<TabRestoreService::Window*>(entry)->tabs.size(), |
428 ++last_local_model_index_); | 445 ++last_local_model_index_); |
429 } | 446 } |
430 ++added_count; | 447 ++added_count; |
431 } | 448 } |
432 } | 449 } |
433 | |
434 DCHECK_GE(last_local_model_index_, 0); | 450 DCHECK_GE(last_local_model_index_, 0); |
435 } | 451 } |
436 | 452 |
437 void RecentTabsSubMenuModel::BuildTabsFromOtherDevices() { | 453 void RecentTabsSubMenuModel::BuildTabsFromOtherDevices() { |
438 // All other devices' items (device headers or tabs) use AddItem*() to append | 454 // All other devices' items (device headers or tabs) use AddItem*() to append |
439 // a menu item, because they are always only built once (i.e. invoked from | 455 // a menu item, because they are always only built once (i.e. invoked from |
440 // Constructor()) and don't change after that. | 456 // Constructor()) and don't change after that. |
441 | 457 |
442 sync_driver::OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(); | 458 sync_driver::OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(); |
443 std::vector<const sync_driver::SyncedSession*> sessions; | 459 std::vector<const sync_driver::SyncedSession*> sessions; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 k < std::min(tabs_in_session.size(), kMaxTabsPerSessionToShow); | 519 k < std::min(tabs_in_session.size(), kMaxTabsPerSessionToShow); |
504 ++k) { | 520 ++k) { |
505 BuildOtherDevicesTabItem(session_tag, *tabs_in_session[k]); | 521 BuildOtherDevicesTabItem(session_tag, *tabs_in_session[k]); |
506 } // for all tabs in one session | 522 } // for all tabs in one session |
507 | 523 |
508 ++num_sessions_added; | 524 ++num_sessions_added; |
509 } // for all sessions | 525 } // for all sessions |
510 | 526 |
511 // We are not supposed to get here unless at least some items were added. | 527 // We are not supposed to get here unless at least some items were added. |
512 DCHECK_GT(GetItemCount(), 0); | 528 DCHECK_GT(GetItemCount(), 0); |
513 AddSeparator(ui::NORMAL_SEPARATOR); | |
514 AddItemWithStringId(IDC_SHOW_HISTORY, IDS_RECENT_TABS_MORE); | |
515 } | 529 } |
516 | 530 |
517 void RecentTabsSubMenuModel::BuildLocalTabItem(int session_id, | 531 void RecentTabsSubMenuModel::BuildLocalTabItem(int session_id, |
518 const base::string16& title, | 532 const base::string16& title, |
519 const GURL& url, | 533 const GURL& url, |
520 int curr_model_index) { | 534 int curr_model_index) { |
521 TabNavigationItem item(std::string(), session_id, title, url); | 535 TabNavigationItem item(std::string(), session_id, title, url); |
522 int command_id = TabVectorIndexToCommandId( | 536 int command_id = TabVectorIndexToCommandId( |
523 local_tab_navigation_items_.size(), kFirstLocalTabCommandId); | 537 local_tab_navigation_items_.size(), kFirstLocalTabCommandId); |
524 // See comments in BuildLocalEntries() about usage of InsertItem*At(). | 538 // See comments in BuildLocalEntries() about usage of InsertItem*At(). |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 if (command_id >= kFirstOtherDevicesTabCommandId) { | 662 if (command_id >= kFirstOtherDevicesTabCommandId) { |
649 *tab_items = &other_devices_tab_navigation_items_; | 663 *tab_items = &other_devices_tab_navigation_items_; |
650 return command_id - kFirstOtherDevicesTabCommandId; | 664 return command_id - kFirstOtherDevicesTabCommandId; |
651 } | 665 } |
652 *tab_items = &local_tab_navigation_items_; | 666 *tab_items = &local_tab_navigation_items_; |
653 return command_id - kFirstLocalTabCommandId; | 667 return command_id - kFirstLocalTabCommandId; |
654 } | 668 } |
655 | 669 |
656 void RecentTabsSubMenuModel::ClearLocalEntries() { | 670 void RecentTabsSubMenuModel::ClearLocalEntries() { |
657 // Remove local items (recently closed tabs and windows) from menumodel. | 671 // Remove local items (recently closed tabs and windows) from menumodel. |
658 while (last_local_model_index_ >= 0) | 672 while (last_local_model_index_ > kHistorySeparatorIndex) |
659 RemoveItemAt(last_local_model_index_--); | 673 RemoveItemAt(last_local_model_index_--); |
660 | 674 |
661 // Cancel asynchronous FaviconService::GetFaviconImageForPageURL() tasks of | 675 // Cancel asynchronous FaviconService::GetFaviconImageForPageURL() tasks of |
662 // all | 676 // all local tabs. |
663 // local tabs. | |
664 local_tab_cancelable_task_tracker_.TryCancelAll(); | 677 local_tab_cancelable_task_tracker_.TryCancelAll(); |
665 | 678 |
666 // Remove all local tab navigation items. | 679 // Remove all local tab navigation items. |
667 local_tab_navigation_items_.clear(); | 680 local_tab_navigation_items_.clear(); |
668 | 681 |
669 // Remove all local window items. | 682 // Remove all local window items. |
670 local_window_items_.clear(); | 683 local_window_items_.clear(); |
671 } | 684 } |
672 | 685 |
673 sync_driver::OpenTabsUIDelegate* | 686 sync_driver::OpenTabsUIDelegate* |
(...skipping 16 matching lines...) Expand all Loading... |
690 | 703 |
691 ui::MenuModelDelegate* menu_model_delegate = GetMenuModelDelegate(); | 704 ui::MenuModelDelegate* menu_model_delegate = GetMenuModelDelegate(); |
692 if (menu_model_delegate) | 705 if (menu_model_delegate) |
693 menu_model_delegate->OnMenuStructureChanged(); | 706 menu_model_delegate->OnMenuStructureChanged(); |
694 } | 707 } |
695 | 708 |
696 void RecentTabsSubMenuModel::TabRestoreServiceDestroyed( | 709 void RecentTabsSubMenuModel::TabRestoreServiceDestroyed( |
697 TabRestoreService* service) { | 710 TabRestoreService* service) { |
698 TabRestoreServiceChanged(service); | 711 TabRestoreServiceChanged(service); |
699 } | 712 } |
OLD | NEW |