1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/toolbar/back_forward_menu_model.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/user_metrics.h" 113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/prefs/pref_service.h" 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/browser/profiles/profile.h" 134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "chrome/common/pref_names.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_controller.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_entry.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/registry_controlled_domain.h" 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/text/text_elider.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/codec/png_codec.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int BackForwardMenuModel::kMaxHistoryItems = 12; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int BackForwardMenuModel::kMaxChapterStops = 5; 29201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstatic const int kMaxWidth = 700; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBackForwardMenuModel::BackForwardMenuModel(Browser* browser, 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelType model_type) 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : browser_(browser), 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch test_tab_contents_(NULL), 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_type_(model_type), 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen menu_model_delegate_(NULL) { 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenBackForwardMenuModel::~BackForwardMenuModel() { 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::HasIcons() const { 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetItemCount() const { 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int items = GetHistoryItemCount(); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (items > 0) { 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chapter_stops = 0; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Next, we count ChapterStops, if any. 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (items == kMaxHistoryItems) 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chapter_stops = GetChapterStopCount(items); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chapter_stops) 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items += chapter_stops + 1; // Chapter stops also need a separator. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the menu is not empty, add two positions in the end 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for a separator and a "Show Full History" item. 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items += 2; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return items; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IsSeparator(index) ? TYPE_SEPARATOR : TYPE_COMMAND; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetCommandIdAt(int index) const { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 BackForwardMenuModel::GetLabelAt(int index) const { 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return label "Show Full History" for the last item of the menu. 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == GetItemCount() - 1) 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return an empty string for a separator. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsSeparator(index)) 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string16(); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Return the entry title, escaping any '&' characters and eliding it if it's 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // super long. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = GetNavigationEntry(index); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 menu_text(entry->GetTitleForDisplay( 883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GetTabContents()->profile()->GetPrefs()-> 893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GetString(prefs::kAcceptLanguages))); 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen menu_text = ui::ElideText(menu_text, gfx::Font(), kMaxWidth, false); 91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if !defined(OS_MACOSX) 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = menu_text.find('&'); i != string16::npos; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i = menu_text.find('&', i + 2)) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch menu_text.insert(i, 1, '&'); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return menu_text; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BackForwardMenuModel::IsItemDynamicAt(int index) const { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This object is only used for a single showing of a menu. 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::GetAcceleratorAt( 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index, 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Accelerator* accelerator) const { 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::IsItemCheckedAt(int index) const { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetGroupIdAt(int index) const { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BackForwardMenuModel::GetIconAt(int index, SkBitmap* icon) { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ItemHasIcon(index)) 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == GetItemCount() - 1) { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *icon = *ResourceBundle::GetSharedInstance().GetBitmapNamed( 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDR_HISTORY_FAVICON); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = GetNavigationEntry(index); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *icon = entry->favicon().bitmap(); 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!entry->favicon().is_valid() && menu_model_delegate()) { 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FetchFavicon(entry); 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt( 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) const { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::IsEnabledAt(int index) const { 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index < GetItemCount() && !IsSeparator(index); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenui::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackForwardMenuModel::HighlightChangedTo(int index) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackForwardMenuModel::ActivatedAt(int index) { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ActivatedAtWithDisposition(index, CURRENT_TAB); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackForwardMenuModel::ActivatedAtWithDisposition( 1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int index, int disposition) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = browser_->profile(); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!IsSeparator(index)); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Execute the command for the last item: "Show Full History". 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == GetItemCount() - 1) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordComputedAction(BuildActionName("ShowFullHistory", -1), 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen browser_->ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL)); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Log whether it was a history or chapter click. 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index < GetHistoryItemCount()) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordComputedAction( 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildActionName("HistoryClick", index), profile); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordComputedAction( 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildActionName("ChapterClick", index - GetHistoryItemCount() - 1), 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int controller_index = MenuIndexToNavEntryIndex(index); 1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!browser_->NavigateToIndexWithDisposition( 1854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch controller_index, static_cast<WindowOpenDisposition>(disposition))) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackForwardMenuModel::MenuWillShow() { 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserMetrics::RecordComputedAction(BuildActionName("Popup", -1), 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_->profile()); 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen requested_favicons_.clear(); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen load_consumer_.CancelAllRequests(); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::IsSeparator(int index) const { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int history_items = GetHistoryItemCount(); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the index is past the number of history items + separator, 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we then consider if it is a chapter-stop entry. 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index > history_items) { 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We either are in ChapterStop area, or at the end of the list (the "Show 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Full History" link). 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chapter_stops = GetChapterStopCount(history_items); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chapter_stops == 0) 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // We must have reached the "Show Full History" link. 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Otherwise, look to see if we have reached the separator for the 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // chapter-stops. If not, this is a chapter stop. 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (index == history_items + 1 + chapter_stops); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look to see if we have reached the separator for the history items. 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index == history_items; 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BackForwardMenuModel::SetMenuModelDelegate( 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ui::MenuModelDelegate* menu_model_delegate) { 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen menu_model_delegate_ = menu_model_delegate; 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BackForwardMenuModel::FetchFavicon(NavigationEntry* entry) { 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the favicon has already been requested for this menu, don't do 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // anything. 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (requested_favicons_.find(entry->unique_id()) != 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen requested_favicons_.end()) { 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen requested_favicons_.insert(entry->unique_id()); 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconService* favicon_service = 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!favicon_service) 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconService::Handle handle = favicon_service->GetFaviconForURL( 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->url(), history::FAVICON, &load_consumer_, 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewCallback(this, &BackForwardMenuModel::OnFavIconDataAvailable)); 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen load_consumer_.SetClientData(favicon_service, handle, entry->unique_id()); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BackForwardMenuModel::OnFavIconDataAvailable( 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FaviconService::Handle handle, 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history::FaviconData favicon) { 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (favicon.is_valid()) { 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int unique_id = load_consumer_.GetClientDataForCurrentRequest(); 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Find the current model_index for the unique_id. 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NavigationEntry* entry = NULL; 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int model_index = -1; 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < GetItemCount() - 1; i++) { 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsSeparator(i)) 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (GetNavigationEntry(i)->unique_id() == unique_id) { 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_index = i; 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry = GetNavigationEntry(i); 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!entry) 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The NavigationEntry wasn't found, this can happen if the user 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // navigates to another page and a NavigatationEntry falls out of the 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // range of kMaxHistoryItems. 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now that we have a valid NavigationEntry, decode the favicon and assign 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // it to the NavigationEntry. 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap fav_icon; 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (gfx::PNGCodec::Decode(favicon.image_data->front(), 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon.image_data->size(), 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &fav_icon)) { 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->favicon().set_is_valid(true); 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->favicon().set_url(favicon.icon_url); 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (fav_icon.empty()) 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->favicon().set_bitmap(fav_icon); 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (menu_model_delegate()) { 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen menu_model_delegate()->OnIconChanged(model_index); 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetHistoryItemCount() const { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int items = 0; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type_ == FORWARD_MENU) { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only count items from n+1 to end (if n is current entry) 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items = contents->controller().entry_count() - 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch contents->controller().GetCurrentEntryIndex() - 1; 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items = contents->controller().GetCurrentEntryIndex(); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (items > kMaxHistoryItems) 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items = kMaxHistoryItems; 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (items < 0) 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch items = 0; 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return items; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetChapterStopCount(int history_items) const { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chapter_stops = 0; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int current_entry = contents->controller().GetCurrentEntryIndex(); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (history_items == kMaxHistoryItems) { 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chapter_id = current_entry; 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type_ == FORWARD_MENU) { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chapter_id += history_items; 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chapter_id -= history_items; 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chapter_id = GetIndexOfNextChapterStop(chapter_id, 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type_ == FORWARD_MENU); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chapter_id != -1) 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++chapter_stops; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } while (chapter_id != -1 && chapter_stops < kMaxChapterStops); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return chapter_stops; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from, 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool forward) const { 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController& controller = contents->controller(); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int max_count = controller.entry_count(); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (start_from < 0 || start_from >= max_count) 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; // Out of bounds. 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (forward) { 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (start_from < max_count - 1) { 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We want to advance over the current chapter stop, so we add one. 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't need to do this when direction is backwards. 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_from++; 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* start_entry = controller.GetEntryAtIndex(start_from); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url = start_entry->url(); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!forward) { 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When going backwards we return the first entry we find that has a 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // different domain. 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = start_from - 1; i >= 0; --i) { 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!net::RegistryControlledDomainService::SameDomainOrHost(url, 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller.GetEntryAtIndex(i)->url())) 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i; 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We have reached the beginning without finding a chapter stop. 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When going forwards we return the entry before the entry that has a 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // different domain. 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = start_from + 1; i < max_count; ++i) { 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!net::RegistryControlledDomainService::SameDomainOrHost(url, 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller.GetEntryAtIndex(i)->url())) 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return i - 1; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last entry is always considered a chapter stop. 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return max_count - 1; 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::FindChapterStop(int offset, 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool forward, 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int skip) const { 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (offset < 0 || skip < 0) 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!forward) 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset *= -1; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int entry = contents->controller().GetCurrentEntryIndex() + offset; 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < skip + 1; i++) 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry = GetIndexOfNextChapterStop(entry, forward); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return entry; 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::ItemHasCommand(int index) const { 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index < GetItemCount() && !IsSeparator(index); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BackForwardMenuModel::ItemHasIcon(int index) const { 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index < GetItemCount() && !IsSeparator(index); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstring16 BackForwardMenuModel::GetShowFullHistoryLabel() const { 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabContents* BackForwardMenuModel::GetTabContents() const { 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We use the test tab contents if the unit test has specified it. 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return test_tab_contents_ ? test_tab_contents_ : 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_->GetSelectedTabContents(); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackForwardMenuModel::MenuIndexToNavEntryIndex(int index) const { 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* contents = GetTabContents(); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int history_items = GetHistoryItemCount(); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GE(index, 0); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Convert anything above the History items separator. 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index < history_items) { 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type_ == FORWARD_MENU) { 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index += contents->controller().GetCurrentEntryIndex() + 1; 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Back menu is reverse. 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = contents->controller().GetCurrentEntryIndex() - (index + 1); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == history_items) 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; // Don't translate the separator for history items. 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index >= history_items + 1 + GetChapterStopCount(history_items)) 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; // This is beyond the last chapter stop so we abort. 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This menu item is a chapter stop located between the two separators. 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = FindChapterStop(history_items, 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type_ == FORWARD_MENU, 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index - history_items - 1); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index; 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNavigationEntry* BackForwardMenuModel::GetNavigationEntry(int index) const { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int controller_index = MenuIndexToNavEntryIndex(index); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationController& controller = GetTabContents()->controller(); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (controller_index >= 0 && controller_index < controller.entry_count()) 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return controller.GetEntryAtIndex(controller_index); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string BackForwardMenuModel::BuildActionName( 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& action, int index) const { 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!action.empty()); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(index >= -1); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string metric_string; 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type_ == FORWARD_MENU) 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metric_string += "ForwardMenu_"; 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metric_string += "BackMenu_"; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metric_string += action; 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index != -1) { 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // +1 is for historical reasons (indices used to start at 1). 4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick metric_string += base::IntToString(index + 1); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return metric_string; 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 462