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/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
12 #include "chrome/browser/favicon/favicon_service_factory.h" | 12 #include "chrome/browser/favicon/favicon_service_factory.h" |
13 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 13 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/search/search.h" | 15 #include "chrome/browser/search/search.h" |
16 #include "chrome/browser/sessions/session_restore.h" | 16 #include "chrome/browser/sessions/session_restore.h" |
17 #include "chrome/browser/sessions/tab_restore_service.h" | 17 #include "chrome/browser/sessions/tab_restore_service.h" |
18 #include "chrome/browser/sessions/tab_restore_service_delegate.h" | 18 #include "chrome/browser/sessions/tab_restore_service_delegate.h" |
19 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 19 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
20 #include "chrome/browser/sync/glue/session_model_associator.h" | 20 #include "chrome/browser/sync/glue/session_model_associator.h" |
21 #include "chrome/browser/sync/glue/synced_session.h" | 21 #include "chrome/browser/sync/glue/synced_session.h" |
22 #include "chrome/browser/sync/profile_sync_service.h" | 22 #include "chrome/browser/sync/profile_sync_service.h" |
23 #include "chrome/browser/sync/profile_sync_service_factory.h" | 23 #include "chrome/browser/sync/profile_sync_service_factory.h" |
24 #include "chrome/browser/ui/browser.h" | 24 #include "chrome/browser/ui/browser.h" |
25 #include "chrome/browser/ui/browser_commands.h" | 25 #include "chrome/browser/ui/browser_commands.h" |
26 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
27 #include "chrome/browser/ui/toolbar/wrench_menu_model.h" | |
28 #include "chrome/common/favicon/favicon_types.h" | 27 #include "chrome/common/favicon/favicon_types.h" |
29 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
30 #include "grit/browser_resources.h" | 29 #include "grit/browser_resources.h" |
31 #include "grit/generated_resources.h" | 30 #include "grit/generated_resources.h" |
32 #include "grit/theme_resources.h" | 31 #include "grit/theme_resources.h" |
33 #include "grit/ui_resources.h" | 32 #include "grit/ui_resources.h" |
34 #include "ui/base/accelerators/accelerator.h" | 33 #include "ui/base/accelerators/accelerator.h" |
35 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
36 #include "ui/base/resource/resource_bundle.h" | 35 #include "ui/base/resource/resource_bundle.h" |
37 #include "ui/gfx/favicon_size.h" | 36 #include "ui/gfx/favicon_size.h" |
38 | 37 |
39 #if defined(USE_ASH) | 38 #if defined(USE_ASH) |
40 #include "ash/accelerators/accelerator_table.h" | 39 #include "ash/accelerators/accelerator_table.h" |
41 #endif // defined(USE_ASH) | 40 #endif // defined(USE_ASH) |
42 | 41 |
43 namespace { | 42 namespace { |
44 | 43 |
45 // First comamnd id for navigatable (and hence executable) tab menu item. | 44 // First comamnd id for navigatable (and hence executable) tab menu item. |
46 // The models and menu are not 1-1: | 45 // The models and menu are not 1-1: |
47 // - menu has "Reopen closed tab", "No tabs from other devices", device section | 46 // - menu has "Reopen closed tab", "No tabs from other devices", device section |
48 // headers, separators and executable tab items. | 47 // headers, separators and executable tab items. |
49 // - |tab_navigation_items_| only has navigatabale/executable tab items. | 48 // - |tab_navigation_items_| only has navigatabale/executable tab items. |
50 // - |window_items_| only has executable open window items. | 49 // - |window_items_| only has executable open window items. |
51 // Using an initial command ids for tab/window items makes it easier and less | 50 // Using an initial command ids for tab/window items makes it easier and less |
52 // error-prone to manipulate the models and menu. | 51 // error-prone to manipulate the models and menu. |
53 // These values must be bigger than the maximum possible number of items in | 52 // These values must be bigger than the maximum possible number of items in |
54 // menu, so that index of last menu item doesn't clash with this value when menu | 53 // menu, so that index of last menu item doesn't clash with this value when menu |
55 // items are retrieved via GetIndexOfCommandId. | 54 // items are retrieved via GetIndexOfCommandId. |
56 // The range of all command ID's used in RecentTabsSubMenuModel must be between | 55 const int kFirstTabCommandId = 100; |
57 // WrenchMenuModel::kMinRecentTabsCommandId i.e. 1001 and 1200 | 56 const int kFirstWindowCommandId = 200; |
58 // (WrenchMenuModel::kMaxRecentTabsCommandId) inclusively. | |
59 const int kFirstTabCommandId = WrenchMenuModel::kMinRecentTabsCommandId; | |
60 const int kFirstWindowCommandId = 1051; | |
61 const int kMinDeviceNameCommandId = 1100; | |
62 const int kMaxDeviceNameCommandId = 1110; | |
63 | 57 |
64 // The maximum number of recently closed entries to be shown in the menu. | 58 // The maximum number of recently closed entries to be shown in the menu. |
65 const int kMaxRecentlyClosedEntries = 8; | 59 const int kMaxRecentlyClosedEntries = 8; |
66 | 60 |
67 // Comparator function for use with std::sort that will sort sessions by | 61 // Comparator function for use with std::sort that will sort sessions by |
68 // descending modified_time (i.e., most recent first). | 62 // descending modified_time (i.e., most recent first). |
69 bool SortSessionsByRecency(const browser_sync::SyncedSession* s1, | 63 bool SortSessionsByRecency(const browser_sync::SyncedSession* s1, |
70 const browser_sync::SyncedSession* s2) { | 64 const browser_sync::SyncedSession* s2) { |
71 return s1->modified_time > s2->modified_time; | 65 return s1->modified_time > s2->modified_time; |
72 } | 66 } |
73 | 67 |
74 // Comparator function for use with std::sort that will sort tabs by | 68 // Comparator function for use with std::sort that will sort tabs by |
75 // descending timestamp (i.e., most recent first). | 69 // descending timestamp (i.e., most recent first). |
76 bool SortTabsByRecency(const SessionTab* t1, const SessionTab* t2) { | 70 bool SortTabsByRecency(const SessionTab* t1, const SessionTab* t2) { |
77 return t1->timestamp > t2->timestamp; | 71 return t1->timestamp > t2->timestamp; |
78 } | 72 } |
79 | 73 |
80 // Returns true if the command id is related to a tab model index. | 74 // Returns true if the command id is related to a tab model index. |
81 bool IsTabModelCommandId(int command_id) { | 75 bool IsTabModelCommandId(int command_id) { |
82 return command_id >= kFirstTabCommandId && command_id < kFirstWindowCommandId; | 76 return command_id >= kFirstTabCommandId && command_id < kFirstWindowCommandId; |
83 } | 77 } |
84 | 78 |
85 // Returns true if the command id is related to a window model index. | 79 // Returns true if the command id is related to a window model index. |
86 bool IsWindowModelCommandId(int command_id) { | 80 bool IsWindowModelCommandId(int command_id) { |
87 return command_id >= kFirstWindowCommandId && | 81 return command_id >= kFirstWindowCommandId && |
88 command_id < RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId; | 82 command_id < RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId; |
89 } | 83 } |
90 | 84 |
91 bool IsDeviceNameCommandId(int command_id) { | |
92 return command_id >= kMinDeviceNameCommandId && | |
93 command_id <= kMaxDeviceNameCommandId; | |
94 } | |
95 | |
96 // Convert |tab_model_index| to command id of menu item. | 85 // Convert |tab_model_index| to command id of menu item. |
97 int TabModelIndexToCommandId(int tab_model_index) { | 86 int TabModelIndexToCommandId(int tab_model_index) { |
98 int command_id = tab_model_index + kFirstTabCommandId; | 87 int command_id = tab_model_index + kFirstTabCommandId; |
99 DCHECK_LT(command_id, kFirstWindowCommandId); | 88 DCHECK_LT(command_id, kFirstWindowCommandId); |
100 return command_id; | 89 return command_id; |
101 } | 90 } |
102 | 91 |
103 // Convert |command_id| of menu item to index in tab model. | 92 // Convert |command_id| of menu item to index in tab model. |
104 int CommandIdToTabModelIndex(int command_id) { | 93 int CommandIdToTabModelIndex(int command_id) { |
105 DCHECK_GE(command_id, kFirstTabCommandId); | 94 DCHECK_GE(command_id, kFirstTabCommandId); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 bool operator<(const TabNavigationItem& other) const { | 139 bool operator<(const TabNavigationItem& other) const { |
151 return url < other.url; | 140 return url < other.url; |
152 } | 141 } |
153 | 142 |
154 std::string session_tag; // Empty for local tabs, non-empty for foreign tabs. | 143 std::string session_tag; // Empty for local tabs, non-empty for foreign tabs. |
155 SessionID::id_type tab_id; // -1 for invalid, >= 0 otherwise. | 144 SessionID::id_type tab_id; // -1 for invalid, >= 0 otherwise. |
156 string16 title; | 145 string16 title; |
157 GURL url; | 146 GURL url; |
158 }; | 147 }; |
159 | 148 |
160 const int RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId = 1120; | 149 const int RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId = 500; |
161 const int RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId = 1121; | 150 const int RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId = 501; |
| 151 const int RecentTabsSubMenuModel::kDeviceNameCommandId = 1000; |
162 | 152 |
163 RecentTabsSubMenuModel::RecentTabsSubMenuModel( | 153 RecentTabsSubMenuModel::RecentTabsSubMenuModel( |
164 ui::AcceleratorProvider* accelerator_provider, | 154 ui::AcceleratorProvider* accelerator_provider, |
165 Browser* browser, | 155 Browser* browser, |
166 browser_sync::SessionModelAssociator* associator) | 156 browser_sync::SessionModelAssociator* associator) |
167 : ui::SimpleMenuModel(this), | 157 : ui::SimpleMenuModel(this), |
168 browser_(browser), | 158 browser_(browser), |
169 associator_(associator), | 159 associator_(associator), |
170 default_favicon_(ResourceBundle::GetSharedInstance(). | 160 default_favicon_(ResourceBundle::GetSharedInstance(). |
171 GetNativeImageNamed(IDR_DEFAULT_FAVICON)), | 161 GetNativeImageNamed(IDR_DEFAULT_FAVICON)), |
(...skipping 23 matching lines...) Expand all Loading... |
195 RecentTabsSubMenuModel::~RecentTabsSubMenuModel() { | 185 RecentTabsSubMenuModel::~RecentTabsSubMenuModel() { |
196 } | 186 } |
197 | 187 |
198 bool RecentTabsSubMenuModel::IsCommandIdChecked(int command_id) const { | 188 bool RecentTabsSubMenuModel::IsCommandIdChecked(int command_id) const { |
199 return false; | 189 return false; |
200 } | 190 } |
201 | 191 |
202 bool RecentTabsSubMenuModel::IsCommandIdEnabled(int command_id) const { | 192 bool RecentTabsSubMenuModel::IsCommandIdEnabled(int command_id) const { |
203 if (command_id == kRecentlyClosedHeaderCommandId || | 193 if (command_id == kRecentlyClosedHeaderCommandId || |
204 command_id == kDisabledRecentlyClosedHeaderCommandId || | 194 command_id == kDisabledRecentlyClosedHeaderCommandId || |
205 command_id == IDC_RECENT_TABS_NO_DEVICE_TABS || | 195 command_id == kDeviceNameCommandId || |
206 IsDeviceNameCommandId(command_id)) { | 196 command_id == IDC_RECENT_TABS_NO_DEVICE_TABS) { |
207 return false; | 197 return false; |
208 } | 198 } |
209 return true; | 199 return true; |
210 } | 200 } |
211 | 201 |
212 bool RecentTabsSubMenuModel::GetAcceleratorForCommandId( | 202 bool RecentTabsSubMenuModel::GetAcceleratorForCommandId( |
213 int command_id, ui::Accelerator* accelerator) { | 203 int command_id, ui::Accelerator* accelerator) { |
214 // If there are no recently closed items, we show the accelerator beside | 204 // If there are no recently closed items, we show the accelerator beside |
215 // the header, otherwise, we show it beside the first item underneath it. | 205 // the header, otherwise, we show it beside the first item underneath it. |
216 int index_in_menu = GetIndexOfCommandId(command_id); | 206 int index_in_menu = GetIndexOfCommandId(command_id); |
(...skipping 10 matching lines...) Expand all Loading... |
227 void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) { | 217 void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) { |
228 if (command_id == IDC_SHOW_HISTORY) { | 218 if (command_id == IDC_SHOW_HISTORY) { |
229 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", SHOW_MORE, | 219 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", SHOW_MORE, |
230 LIMIT_RECENT_TAB_ACTION); | 220 LIMIT_RECENT_TAB_ACTION); |
231 // We show all "other devices" on the history page. | 221 // We show all "other devices" on the history page. |
232 chrome::ExecuteCommandWithDisposition(browser_, IDC_SHOW_HISTORY, | 222 chrome::ExecuteCommandWithDisposition(browser_, IDC_SHOW_HISTORY, |
233 ui::DispositionFromEventFlags(event_flags)); | 223 ui::DispositionFromEventFlags(event_flags)); |
234 return; | 224 return; |
235 } | 225 } |
236 | 226 |
| 227 DCHECK_NE(kDeviceNameCommandId, command_id); |
237 DCHECK_NE(IDC_RECENT_TABS_NO_DEVICE_TABS, command_id); | 228 DCHECK_NE(IDC_RECENT_TABS_NO_DEVICE_TABS, command_id); |
238 DCHECK(!IsDeviceNameCommandId(command_id)); | |
239 | 229 |
240 WindowOpenDisposition disposition = | 230 WindowOpenDisposition disposition = |
241 ui::DispositionFromEventFlags(event_flags); | 231 ui::DispositionFromEventFlags(event_flags); |
242 if (disposition == CURRENT_TAB) // Force to open a new foreground tab. | 232 if (disposition == CURRENT_TAB) // Force to open a new foreground tab. |
243 disposition = NEW_FOREGROUND_TAB; | 233 disposition = NEW_FOREGROUND_TAB; |
244 | 234 |
245 TabRestoreService* service = | 235 TabRestoreService* service = |
246 TabRestoreServiceFactory::GetForProfile(browser_->profile()); | 236 TabRestoreServiceFactory::GetForProfile(browser_->profile()); |
247 TabRestoreServiceDelegate* delegate = | 237 TabRestoreServiceDelegate* delegate = |
248 TabRestoreServiceDelegate::FindDelegateForWebContents( | 238 TabRestoreServiceDelegate::FindDelegateForWebContents( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", RESTORE_WINDOW, | 275 UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", RESTORE_WINDOW, |
286 LIMIT_RECENT_TAB_ACTION); | 276 LIMIT_RECENT_TAB_ACTION); |
287 service->RestoreEntryById(delegate, window_items_[model_idx], | 277 service->RestoreEntryById(delegate, window_items_[model_idx], |
288 browser_->host_desktop_type(), disposition); | 278 browser_->host_desktop_type(), disposition); |
289 } | 279 } |
290 } | 280 } |
291 } | 281 } |
292 | 282 |
293 const gfx::Font* RecentTabsSubMenuModel::GetLabelFontAt(int index) const { | 283 const gfx::Font* RecentTabsSubMenuModel::GetLabelFontAt(int index) const { |
294 int command_id = GetCommandIdAt(index); | 284 int command_id = GetCommandIdAt(index); |
295 if (command_id == kRecentlyClosedHeaderCommandId || | 285 if (command_id == kDeviceNameCommandId || |
296 IsDeviceNameCommandId(command_id)) { | 286 command_id == kRecentlyClosedHeaderCommandId) { |
297 return &ResourceBundle::GetSharedInstance().GetFont( | 287 return &ResourceBundle::GetSharedInstance().GetFont( |
298 ResourceBundle::BoldFont); | 288 ResourceBundle::BoldFont); |
299 } | 289 } |
300 return NULL; | 290 return NULL; |
301 } | 291 } |
302 | 292 |
303 int RecentTabsSubMenuModel::GetMaxWidthForItemAtIndex(int item_index) const { | 293 int RecentTabsSubMenuModel::GetMaxWidthForItemAtIndex(int item_index) const { |
304 int command_id = GetCommandIdAt(item_index); | 294 int command_id = GetCommandIdAt(item_index); |
305 if (command_id == IDC_RECENT_TABS_NO_DEVICE_TABS || | 295 if (command_id == IDC_RECENT_TABS_NO_DEVICE_TABS || |
306 command_id == kRecentlyClosedHeaderCommandId || | 296 command_id == kRecentlyClosedHeaderCommandId || |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 } | 424 } |
435 } | 425 } |
436 if (tabs_in_session.empty()) | 426 if (tabs_in_session.empty()) |
437 continue; | 427 continue; |
438 std::sort(tabs_in_session.begin(), tabs_in_session.end(), | 428 std::sort(tabs_in_session.begin(), tabs_in_session.end(), |
439 SortTabsByRecency); | 429 SortTabsByRecency); |
440 | 430 |
441 // Add the header for the device session. | 431 // Add the header for the device session. |
442 DCHECK(!session->session_name.empty()); | 432 DCHECK(!session->session_name.empty()); |
443 AddSeparator(ui::NORMAL_SEPARATOR); | 433 AddSeparator(ui::NORMAL_SEPARATOR); |
444 AddItem(kMinDeviceNameCommandId + i, UTF8ToUTF16(session->session_name)); | 434 AddItem(kDeviceNameCommandId, UTF8ToUTF16(session->session_name)); |
445 AddDeviceFavicon(GetItemCount() - 1, session->device_type); | 435 AddDeviceFavicon(GetItemCount() - 1, session->device_type); |
446 | 436 |
447 // Build tab menu items from sorted session tabs. | 437 // Build tab menu items from sorted session tabs. |
448 const size_t kMaxTabsPerSessionToShow = 4; | 438 const size_t kMaxTabsPerSessionToShow = 4; |
449 for (size_t k = 0; | 439 for (size_t k = 0; |
450 k < std::min(tabs_in_session.size(), kMaxTabsPerSessionToShow); | 440 k < std::min(tabs_in_session.size(), kMaxTabsPerSessionToShow); |
451 ++k) { | 441 ++k) { |
452 BuildForeignTabItem(session_tag, *tabs_in_session[k]); | 442 BuildForeignTabItem(session_tag, *tabs_in_session[k]); |
453 } // for all tabs in one session | 443 } // for all tabs in one session |
454 | 444 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 RecentTabsSubMenuModel::GetModelAssociator() { | 581 RecentTabsSubMenuModel::GetModelAssociator() { |
592 if (!associator_) { | 582 if (!associator_) { |
593 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()-> | 583 ProfileSyncService* service = ProfileSyncServiceFactory::GetInstance()-> |
594 GetForProfile(browser_->profile()); | 584 GetForProfile(browser_->profile()); |
595 // Only return the associator if it exists and it is done syncing sessions. | 585 // Only return the associator if it exists and it is done syncing sessions. |
596 if (service && service->ShouldPushChanges()) | 586 if (service && service->ShouldPushChanges()) |
597 associator_ = service->GetSessionModelAssociator(); | 587 associator_ = service->GetSessionModelAssociator(); |
598 } | 588 } |
599 return associator_; | 589 return associator_; |
600 } | 590 } |
OLD | NEW |