| Index: chrome/browser/back_forward_menu_model.cc
 | 
| ===================================================================
 | 
| --- chrome/browser/back_forward_menu_model.cc	(revision 68008)
 | 
| +++ chrome/browser/back_forward_menu_model.cc	(working copy)
 | 
| @@ -1,379 +0,0 @@
 | 
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#include "build/build_config.h"
 | 
| -
 | 
| -#include "chrome/browser/back_forward_menu_model.h"
 | 
| -
 | 
| -#include "app/l10n_util.h"
 | 
| -#include "app/text_elider.h"
 | 
| -#include "app/resource_bundle.h"
 | 
| -#include "base/string_number_conversions.h"
 | 
| -#include "chrome/browser/metrics/user_metrics.h"
 | 
| -#include "chrome/browser/tab_contents/navigation_controller.h"
 | 
| -#include "chrome/browser/tab_contents/navigation_entry.h"
 | 
| -#include "chrome/browser/tab_contents/tab_contents.h"
 | 
| -#include "chrome/browser/ui/browser.h"
 | 
| -#include "chrome/common/url_constants.h"
 | 
| -#include "grit/generated_resources.h"
 | 
| -#include "grit/theme_resources.h"
 | 
| -#include "net/base/registry_controlled_domain.h"
 | 
| -
 | 
| -const int BackForwardMenuModel::kMaxHistoryItems = 12;
 | 
| -const int BackForwardMenuModel::kMaxChapterStops = 5;
 | 
| -static const int kMaxWidth = 700;
 | 
| -
 | 
| -BackForwardMenuModel::BackForwardMenuModel(Browser* browser,
 | 
| -                                           ModelType model_type)
 | 
| -    : browser_(browser),
 | 
| -      test_tab_contents_(NULL),
 | 
| -      model_type_(model_type) {
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::HasIcons() const {
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetItemCount() const {
 | 
| -  int items = GetHistoryItemCount();
 | 
| -
 | 
| -  if (items > 0) {
 | 
| -    int chapter_stops = 0;
 | 
| -
 | 
| -    // Next, we count ChapterStops, if any.
 | 
| -    if (items == kMaxHistoryItems)
 | 
| -      chapter_stops = GetChapterStopCount(items);
 | 
| -
 | 
| -    if (chapter_stops)
 | 
| -      items += chapter_stops + 1;  // Chapter stops also need a separator.
 | 
| -
 | 
| -    // If the menu is not empty, add two positions in the end
 | 
| -    // for a separator and a "Show Full History" item.
 | 
| -    items += 2;
 | 
| -  }
 | 
| -
 | 
| -  return items;
 | 
| -}
 | 
| -
 | 
| -menus::MenuModel::ItemType BackForwardMenuModel::GetTypeAt(int index) const {
 | 
| -  return IsSeparator(index) ? TYPE_SEPARATOR : TYPE_COMMAND;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetCommandIdAt(int index) const {
 | 
| -  return index;
 | 
| -}
 | 
| -
 | 
| -string16 BackForwardMenuModel::GetLabelAt(int index) const {
 | 
| -  // Return label "Show Full History" for the last item of the menu.
 | 
| -  if (index == GetItemCount() - 1)
 | 
| -    return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK);
 | 
| -
 | 
| -  // Return an empty string for a separator.
 | 
| -  if (IsSeparator(index))
 | 
| -    return string16();
 | 
| -
 | 
| -  // Return the entry title, escaping any '&' characters and eliding it if it's
 | 
| -  // super long.
 | 
| -  NavigationEntry* entry = GetNavigationEntry(index);
 | 
| -  string16 menu_text(entry->GetTitleForDisplay(
 | 
| -      &GetTabContents()->controller()));
 | 
| -  menu_text = gfx::ElideText(menu_text, gfx::Font(), kMaxWidth, false);
 | 
| -
 | 
| -  for (size_t i = menu_text.find('&'); i != string16::npos;
 | 
| -       i = menu_text.find('&', i + 2)) {
 | 
| -    menu_text.insert(i, 1, '&');
 | 
| -  }
 | 
| -  return menu_text;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::IsLabelDynamicAt(int index) const {
 | 
| -  // This object is only used for a single showing of a menu.
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::GetAcceleratorAt(
 | 
| -    int index,
 | 
| -    menus::Accelerator* accelerator) const {
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::IsItemCheckedAt(int index) const {
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetGroupIdAt(int index) const {
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::GetIconAt(int index, SkBitmap* icon) const {
 | 
| -  if (!ItemHasIcon(index))
 | 
| -    return false;
 | 
| -
 | 
| -  if (index == GetItemCount() - 1) {
 | 
| -    *icon = *ResourceBundle::GetSharedInstance().GetBitmapNamed(
 | 
| -        IDR_HISTORY_FAVICON);
 | 
| -  } else {
 | 
| -    NavigationEntry* entry = GetNavigationEntry(index);
 | 
| -    *icon = entry->favicon().bitmap();
 | 
| -  }
 | 
| -
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -menus::ButtonMenuItemModel* BackForwardMenuModel::GetButtonMenuItemAt(
 | 
| -    int index) const {
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::IsEnabledAt(int index) const {
 | 
| -  return index < GetItemCount() && !IsSeparator(index);
 | 
| -}
 | 
| -
 | 
| -menus::MenuModel* BackForwardMenuModel::GetSubmenuModelAt(int index) const {
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -void BackForwardMenuModel::HighlightChangedTo(int index) {
 | 
| -}
 | 
| -
 | 
| -void BackForwardMenuModel::ActivatedAt(int index) {
 | 
| -  ActivatedAtWithDisposition(index, CURRENT_TAB);
 | 
| -}
 | 
| -
 | 
| -void BackForwardMenuModel::ActivatedAtWithDisposition(
 | 
| -      int index, int disposition) {
 | 
| -  Profile* profile = browser_->profile();
 | 
| -
 | 
| -  DCHECK(!IsSeparator(index));
 | 
| -
 | 
| -  // Execute the command for the last item: "Show Full History".
 | 
| -  if (index == GetItemCount() - 1) {
 | 
| -    UserMetrics::RecordComputedAction(BuildActionName("ShowFullHistory", -1),
 | 
| -                                      profile);
 | 
| -    browser_->ShowSingletonTab(GURL(chrome::kChromeUIHistoryURL), false);
 | 
| -    return;
 | 
| -  }
 | 
| -
 | 
| -  // Log whether it was a history or chapter click.
 | 
| -  if (index < GetHistoryItemCount()) {
 | 
| -    UserMetrics::RecordComputedAction(
 | 
| -        BuildActionName("HistoryClick", index), profile);
 | 
| -  } else {
 | 
| -    UserMetrics::RecordComputedAction(
 | 
| -        BuildActionName("ChapterClick", index - GetHistoryItemCount() - 1),
 | 
| -        profile);
 | 
| -  }
 | 
| -
 | 
| -  int controller_index = MenuIndexToNavEntryIndex(index);
 | 
| -  if (!browser_->NavigateToIndexWithDisposition(
 | 
| -          controller_index, static_cast<WindowOpenDisposition>(disposition))) {
 | 
| -    NOTREACHED();
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void BackForwardMenuModel::MenuWillShow() {
 | 
| -  UserMetrics::RecordComputedAction(BuildActionName("Popup", -1),
 | 
| -                                    browser_->profile());
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::IsSeparator(int index) const {
 | 
| -  int history_items = GetHistoryItemCount();
 | 
| -  // If the index is past the number of history items + separator,
 | 
| -  // we then consider if it is a chapter-stop entry.
 | 
| -  if (index > history_items) {
 | 
| -    // We either are in ChapterStop area, or at the end of the list (the "Show
 | 
| -    // Full History" link).
 | 
| -    int chapter_stops = GetChapterStopCount(history_items);
 | 
| -    if (chapter_stops == 0)
 | 
| -      return false;  // We must have reached the "Show Full History" link.
 | 
| -    // Otherwise, look to see if we have reached the separator for the
 | 
| -    // chapter-stops. If not, this is a chapter stop.
 | 
| -    return (index == history_items + 1 + chapter_stops);
 | 
| -  }
 | 
| -
 | 
| -  // Look to see if we have reached the separator for the history items.
 | 
| -  return index == history_items;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetHistoryItemCount() const {
 | 
| -  TabContents* contents = GetTabContents();
 | 
| -  int items = 0;
 | 
| -
 | 
| -  if (model_type_ == FORWARD_MENU) {
 | 
| -    // Only count items from n+1 to end (if n is current entry)
 | 
| -    items = contents->controller().entry_count() -
 | 
| -            contents->controller().GetCurrentEntryIndex() - 1;
 | 
| -  } else {
 | 
| -    items = contents->controller().GetCurrentEntryIndex();
 | 
| -  }
 | 
| -
 | 
| -  if (items > kMaxHistoryItems)
 | 
| -    items = kMaxHistoryItems;
 | 
| -  else if (items < 0)
 | 
| -    items = 0;
 | 
| -
 | 
| -  return items;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetChapterStopCount(int history_items) const {
 | 
| -  TabContents* contents = GetTabContents();
 | 
| -
 | 
| -  int chapter_stops = 0;
 | 
| -  int current_entry = contents->controller().GetCurrentEntryIndex();
 | 
| -
 | 
| -  if (history_items == kMaxHistoryItems) {
 | 
| -    int chapter_id = current_entry;
 | 
| -    if (model_type_ == FORWARD_MENU) {
 | 
| -      chapter_id += history_items;
 | 
| -    } else {
 | 
| -      chapter_id -= history_items;
 | 
| -    }
 | 
| -
 | 
| -    do {
 | 
| -      chapter_id = GetIndexOfNextChapterStop(chapter_id,
 | 
| -          model_type_ == FORWARD_MENU);
 | 
| -      if (chapter_id != -1)
 | 
| -        ++chapter_stops;
 | 
| -    } while (chapter_id != -1 && chapter_stops < kMaxChapterStops);
 | 
| -  }
 | 
| -
 | 
| -  return chapter_stops;
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from,
 | 
| -                                                    bool forward) const {
 | 
| -  TabContents* contents = GetTabContents();
 | 
| -  NavigationController& controller = contents->controller();
 | 
| -
 | 
| -  int max_count = controller.entry_count();
 | 
| -  if (start_from < 0 || start_from >= max_count)
 | 
| -    return -1;  // Out of bounds.
 | 
| -
 | 
| -  if (forward) {
 | 
| -    if (start_from < max_count - 1) {
 | 
| -      // We want to advance over the current chapter stop, so we add one.
 | 
| -      // We don't need to do this when direction is backwards.
 | 
| -      start_from++;
 | 
| -    } else {
 | 
| -      return -1;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  NavigationEntry* start_entry = controller.GetEntryAtIndex(start_from);
 | 
| -  const GURL& url = start_entry->url();
 | 
| -
 | 
| -  if (!forward) {
 | 
| -    // When going backwards we return the first entry we find that has a
 | 
| -    // different domain.
 | 
| -    for (int i = start_from - 1; i >= 0; --i) {
 | 
| -      if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
 | 
| -              controller.GetEntryAtIndex(i)->url()))
 | 
| -        return i;
 | 
| -    }
 | 
| -    // We have reached the beginning without finding a chapter stop.
 | 
| -    return -1;
 | 
| -  } else {
 | 
| -    // When going forwards we return the entry before the entry that has a
 | 
| -    // different domain.
 | 
| -    for (int i = start_from + 1; i < max_count; ++i) {
 | 
| -      if (!net::RegistryControlledDomainService::SameDomainOrHost(url,
 | 
| -              controller.GetEntryAtIndex(i)->url()))
 | 
| -        return i - 1;
 | 
| -    }
 | 
| -    // Last entry is always considered a chapter stop.
 | 
| -    return max_count - 1;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::FindChapterStop(int offset,
 | 
| -                                          bool forward,
 | 
| -                                          int skip) const {
 | 
| -  if (offset < 0 || skip < 0)
 | 
| -    return -1;
 | 
| -
 | 
| -  if (!forward)
 | 
| -    offset *= -1;
 | 
| -
 | 
| -  TabContents* contents = GetTabContents();
 | 
| -  int entry = contents->controller().GetCurrentEntryIndex() + offset;
 | 
| -  for (int i = 0; i < skip + 1; i++)
 | 
| -    entry = GetIndexOfNextChapterStop(entry, forward);
 | 
| -
 | 
| -  return entry;
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::ItemHasCommand(int index) const {
 | 
| -  return index < GetItemCount() && !IsSeparator(index);
 | 
| -}
 | 
| -
 | 
| -bool BackForwardMenuModel::ItemHasIcon(int index) const {
 | 
| -  return index < GetItemCount() && !IsSeparator(index);
 | 
| -}
 | 
| -
 | 
| -string16 BackForwardMenuModel::GetShowFullHistoryLabel() const {
 | 
| -  return l10n_util::GetStringUTF16(IDS_SHOWFULLHISTORY_LINK);
 | 
| -}
 | 
| -
 | 
| -TabContents* BackForwardMenuModel::GetTabContents() const {
 | 
| -  // We use the test tab contents if the unit test has specified it.
 | 
| -  return test_tab_contents_ ? test_tab_contents_ :
 | 
| -                              browser_->GetSelectedTabContents();
 | 
| -}
 | 
| -
 | 
| -int BackForwardMenuModel::MenuIndexToNavEntryIndex(int index) const {
 | 
| -  TabContents* contents = GetTabContents();
 | 
| -  int history_items = GetHistoryItemCount();
 | 
| -
 | 
| -  DCHECK_GE(index, 0);
 | 
| -
 | 
| -  // Convert anything above the History items separator.
 | 
| -  if (index < history_items) {
 | 
| -    if (model_type_ == FORWARD_MENU) {
 | 
| -      index += contents->controller().GetCurrentEntryIndex() + 1;
 | 
| -    } else {
 | 
| -      // Back menu is reverse.
 | 
| -      index = contents->controller().GetCurrentEntryIndex() - (index + 1);
 | 
| -    }
 | 
| -    return index;
 | 
| -  }
 | 
| -  if (index == history_items)
 | 
| -    return -1;  // Don't translate the separator for history items.
 | 
| -
 | 
| -  if (index >= history_items + 1 + GetChapterStopCount(history_items))
 | 
| -    return -1;  // This is beyond the last chapter stop so we abort.
 | 
| -
 | 
| -  // This menu item is a chapter stop located between the two separators.
 | 
| -  index = FindChapterStop(history_items,
 | 
| -                          model_type_ == FORWARD_MENU,
 | 
| -                          index - history_items - 1);
 | 
| -
 | 
| -  return index;
 | 
| -}
 | 
| -
 | 
| -NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int index) const {
 | 
| -  int controller_index = MenuIndexToNavEntryIndex(index);
 | 
| -  NavigationController& controller = GetTabContents()->controller();
 | 
| -  if (controller_index >= 0 && controller_index < controller.entry_count())
 | 
| -    return controller.GetEntryAtIndex(controller_index);
 | 
| -
 | 
| -  NOTREACHED();
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -std::string BackForwardMenuModel::BuildActionName(
 | 
| -    const std::string& action, int index) const {
 | 
| -  DCHECK(!action.empty());
 | 
| -  DCHECK(index >= -1);
 | 
| -  std::string metric_string;
 | 
| -  if (model_type_ == FORWARD_MENU)
 | 
| -    metric_string += "ForwardMenu_";
 | 
| -  else
 | 
| -    metric_string += "BackMenu_";
 | 
| -  metric_string += action;
 | 
| -  if (index != -1) {
 | 
| -    // +1 is for historical reasons (indices used to start at 1).
 | 
| -    metric_string += base::IntToString(index + 1);
 | 
| -  }
 | 
| -  return metric_string;
 | 
| -}
 | 
| 
 |