Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: chrome/browser/back_forward_menu_model.cc

Issue 5544002: Move a bunch more browser stuff around.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "build/build_config.h"
6
7 #include "chrome/browser/back_forward_menu_model.h"
8
9 #include "app/l10n_util.h"
10 #include "app/text_elider.h"
11 #include "app/resource_bundle.h"
12 #include "base/string_number_conversions.h"
13 #include "chrome/browser/metrics/user_metrics.h"
14 #include "chrome/browser/tab_contents/navigation_controller.h"
15 #include "chrome/browser/tab_contents/navigation_entry.h"
16 #include "chrome/browser/tab_contents/tab_contents.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/common/url_constants.h"
19 #include "grit/generated_resources.h"
20 #include "grit/theme_resources.h"
21 #include "net/base/registry_controlled_domain.h"
22
23 const int BackForwardMenuModel::kMaxHistoryItems = 12;
24 const int BackForwardMenuModel::kMaxChapterStops = 5;
25 static const int kMaxWidth = 700;
26
27 BackForwardMenuModel::BackForwardMenuModel(Browser* browser,
28 ModelType model_type)
29 : browser_(browser),
30 test_tab_contents_(NULL),
31 model_type_(model_type) {
32 }
33
34 bool BackForwardMenuModel::HasIcons() const {
35 return true;
36 }
37
38 int BackForwardMenuModel::GetItemCount() const {
39 int items = GetHistoryItemCount();
40
41 if (items > 0) {
42 int chapter_stops = 0;
43
44 // Next, we count ChapterStops, if any.
45 if (items == kMaxHistoryItems)
46 chapter_stops = GetChapterStopCount(items);
47
48 if (chapter_stops)
49 items += chapter_stops + 1; // Chapter stops also need a separator.
50
51 // If the menu is not empty, add two positions in the end
52 // for a separator and a "Show Full History" item.
53 items += 2;
54 }
55
56 return items;
57 }
58
59 menus::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const {
60 return IsSeparator(index) ? TYPE_SEPARATOR : TYPE_COMMAND;
61 }
62
63 int BackForwardMenuModel::GetCommandIdAt(int index) const {
64 return index;
65 }
66
67 string16 BackForwardMenuModel::GetLabelAt(int index) const {
68 // Return label "Show Full History" for the last item of the menu.
69 if (index == GetItemCount() - 1)
70 return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK);
71
72 // Return an empty string for a separator.
73 if (IsSeparator(index))
74 return string16();
75
76 // Return the entry title, escaping any '&' characters and eliding it if it's
77 // super long.
78 NavigationEntry* entry = GetNavigationEntry(index);
79 string16 menu_text(entry->GetTitleForDisplay(
80 &GetTabContents()->controller()));
81 menu_text = gfx::ElideText(menu_text, gfx::Font(), kMaxWidth, false);
82
83 for (size_t i = menu_text.find('&'); i != string16::npos;
84 i = menu_text.find('&', i + 2)) {
85 menu_text.insert(i, 1, '&');
86 }
87 return menu_text;
88 }
89
90 bool BackForwardMenuModel::IsLabelDynamicAt(int index) const {
91 // This object is only used for a single showing of a menu.
92 return false;
93 }
94
95 bool BackForwardMenuModel::GetAcceleratorAt(
96 int index,
97 menus::Accelerator* accelerator) const {
98 return false;
99 }
100
101 bool BackForwardMenuModel::IsItemCheckedAt(int index) const {
102 return false;
103 }
104
105 int BackForwardMenuModel::GetGroupIdAt(int index) const {
106 return false;
107 }
108
109 bool BackForwardMenuModel::GetIconAt(int index, SkBitmap* icon) const {
110 if (!ItemHasIcon(index))
111 return false;
112
113 if (index == GetItemCount() - 1) {
114 *icon = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
115 IDR_HISTORY_FAVICON);
116 } else {
117 NavigationEntry* entry = GetNavigationEntry(index);
118 *icon = entry->favicon().bitmap();
119 }
120
121 return true;
122 }
123
124 menus::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt(
125 int index) const {
126 return NULL;
127 }
128
129 bool BackForwardMenuModel::IsEnabledAt(int index) const {
130 return index < GetItemCount() && !IsSeparator(index);
131 }
132
133 menus::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const {
134 return NULL;
135 }
136
137 void BackForwardMenuModel::HighlightChangedTo(int index) {
138 }
139
140 void BackForwardMenuModel::ActivatedAt(int index) {
141 ActivatedAtWithDisposition(index, CURRENT_TAB);
142 }
143
144 void BackForwardMenuModel::ActivatedAtWithDisposition(
145 int index, int disposition) {
146 Profile* profile = browser_->profile();
147
148 DCHECK(!IsSeparator(index));
149
150 // Execute the command for the last item: "Show Full History".
151 if (index == GetItemCount() - 1) {
152 UserMetrics::RecordComputedAction(BuildActionName("ShowFullHistory", -1),
153 profile);
154 browser_->ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL), false);
155 return;
156 }
157
158 // Log whether it was a history or chapter click.
159 if (index < GetHistoryItemCount()) {
160 UserMetrics::RecordComputedAction(
161 BuildActionName("HistoryClick", index), profile);
162 } else {
163 UserMetrics::RecordComputedAction(
164 BuildActionName("ChapterClick", index - GetHistoryItemCount() - 1),
165 profile);
166 }
167
168 int controller_index = MenuIndexToNavEntryIndex(index);
169 if (!browser_->NavigateToIndexWithDisposition(
170 controller_index, static_cast<WindowOpenDisposition>(disposition))) {
171 NOTREACHED();
172 }
173 }
174
175 void BackForwardMenuModel::MenuWillShow() {
176 UserMetrics::RecordComputedAction(BuildActionName("Popup", -1),
177 browser_->profile());
178 }
179
180 bool BackForwardMenuModel::IsSeparator(int index) const {
181 int history_items = GetHistoryItemCount();
182 // If the index is past the number of history items + separator,
183 // we then consider if it is a chapter-stop entry.
184 if (index > history_items) {
185 // We either are in ChapterStop area, or at the end of the list (the "Show
186 // Full History" link).
187 int chapter_stops = GetChapterStopCount(history_items);
188 if (chapter_stops == 0)
189 return false; // We must have reached the "Show Full History" link.
190 // Otherwise, look to see if we have reached the separator for the
191 // chapter-stops. If not, this is a chapter stop.
192 return (index == history_items + 1 + chapter_stops);
193 }
194
195 // Look to see if we have reached the separator for the history items.
196 return index == history_items;
197 }
198
199 int BackForwardMenuModel::GetHistoryItemCount() const {
200 TabContents* contents = GetTabContents();
201 int items = 0;
202
203 if (model_type_ == FORWARD_MENU) {
204 // Only count items from n+1 to end (if n is current entry)
205 items = contents->controller().entry_count() -
206 contents->controller().GetCurrentEntryIndex() - 1;
207 } else {
208 items = contents->controller().GetCurrentEntryIndex();
209 }
210
211 if (items > kMaxHistoryItems)
212 items = kMaxHistoryItems;
213 else if (items < 0)
214 items = 0;
215
216 return items;
217 }
218
219 int BackForwardMenuModel::GetChapterStopCount(int history_items) const {
220 TabContents* contents = GetTabContents();
221
222 int chapter_stops = 0;
223 int current_entry = contents->controller().GetCurrentEntryIndex();
224
225 if (history_items == kMaxHistoryItems) {
226 int chapter_id = current_entry;
227 if (model_type_ == FORWARD_MENU) {
228 chapter_id += history_items;
229 } else {
230 chapter_id -= history_items;
231 }
232
233 do {
234 chapter_id = GetIndexOfNextChapterStop(chapter_id,
235 model_type_ == FORWARD_MENU);
236 if (chapter_id != -1)
237 ++chapter_stops;
238 } while (chapter_id != -1 && chapter_stops < kMaxChapterStops);
239 }
240
241 return chapter_stops;
242 }
243
244 int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from,
245 bool forward) const {
246 TabContents* contents = GetTabContents();
247 NavigationController& controller = contents->controller();
248
249 int max_count = controller.entry_count();
250 if (start_from < 0 || start_from >= max_count)
251 return -1; // Out of bounds.
252
253 if (forward) {
254 if (start_from < max_count - 1) {
255 // We want to advance over the current chapter stop, so we add one.
256 // We don't need to do this when direction is backwards.
257 start_from++;
258 } else {
259 return -1;
260 }
261 }
262
263 NavigationEntry* start_entry = controller.GetEntryAtIndex(start_from);
264 const GURL& url = start_entry->url();
265
266 if (!forward) {
267 // When going backwards we return the first entry we find that has a
268 // different domain.
269 for (int i = start_from - 1; i >= 0; --i) {
270 if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
271 controller.GetEntryAtIndex(i)->url()))
272 return i;
273 }
274 // We have reached the beginning without finding a chapter stop.
275 return -1;
276 } else {
277 // When going forwards we return the entry before the entry that has a
278 // different domain.
279 for (int i = start_from + 1; i < max_count; ++i) {
280 if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
281 controller.GetEntryAtIndex(i)->url()))
282 return i - 1;
283 }
284 // Last entry is always considered a chapter stop.
285 return max_count - 1;
286 }
287 }
288
289 int BackForwardMenuModel::FindChapterStop(int offset,
290 bool forward,
291 int skip) const {
292 if (offset < 0 || skip < 0)
293 return -1;
294
295 if (!forward)
296 offset *= -1;
297
298 TabContents* contents = GetTabContents();
299 int entry = contents->controller().GetCurrentEntryIndex() + offset;
300 for (int i = 0; i < skip + 1; i++)
301 entry = GetIndexOfNextChapterStop(entry, forward);
302
303 return entry;
304 }
305
306 bool BackForwardMenuModel::ItemHasCommand(int index) const {
307 return index < GetItemCount() && !IsSeparator(index);
308 }
309
310 bool BackForwardMenuModel::ItemHasIcon(int index) const {
311 return index < GetItemCount() && !IsSeparator(index);
312 }
313
314 string16 BackForwardMenuModel::GetShowFullHistoryLabel() const {
315 return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK);
316 }
317
318 TabContents* BackForwardMenuModel::GetTabContents() const {
319 // We use the test tab contents if the unit test has specified it.
320 return test_tab_contents_ ? test_tab_contents_ :
321 browser_->GetSelectedTabContents();
322 }
323
324 int BackForwardMenuModel::MenuIndexToNavEntryIndex(int index) const {
325 TabContents* contents = GetTabContents();
326 int history_items = GetHistoryItemCount();
327
328 DCHECK_GE(index, 0);
329
330 // Convert anything above the History items separator.
331 if (index < history_items) {
332 if (model_type_ == FORWARD_MENU) {
333 index += contents->controller().GetCurrentEntryIndex() + 1;
334 } else {
335 // Back menu is reverse.
336 index = contents->controller().GetCurrentEntryIndex() - (index + 1);
337 }
338 return index;
339 }
340 if (index == history_items)
341 return -1; // Don't translate the separator for history items.
342
343 if (index >= history_items + 1 + GetChapterStopCount(history_items))
344 return -1; // This is beyond the last chapter stop so we abort.
345
346 // This menu item is a chapter stop located between the two separators.
347 index = FindChapterStop(history_items,
348 model_type_ == FORWARD_MENU,
349 index - history_items - 1);
350
351 return index;
352 }
353
354 NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int index) const {
355 int controller_index = MenuIndexToNavEntryIndex(index);
356 NavigationController& controller = GetTabContents()->controller();
357 if (controller_index >= 0 && controller_index < controller.entry_count())
358 return controller.GetEntryAtIndex(controller_index);
359
360 NOTREACHED();
361 return NULL;
362 }
363
364 std::string BackForwardMenuModel::BuildActionName(
365 const std::string& action, int index) const {
366 DCHECK(!action.empty());
367 DCHECK(index >= -1);
368 std::string metric_string;
369 if (model_type_ == FORWARD_MENU)
370 metric_string += "ForwardMenu_";
371 else
372 metric_string += "BackMenu_";
373 metric_string += action;
374 if (index != -1) {
375 // +1 is for historical reasons (indices used to start at 1).
376 metric_string += base::IntToString(index + 1);
377 }
378 return metric_string;
379 }
OLDNEW
« no previous file with comments | « chrome/browser/back_forward_menu_model.h ('k') | chrome/browser/back_forward_menu_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698