From 70b45efc15674aa7241bbb95dc81b3019eac294b Mon Sep 17 00:00:00 2001 From: "estade@chromium.org" Date: Wed, 18 Feb 2009 22:30:16 +0000 Subject: Port back_forward_menu_model to linux. * Refactor BackForwardMenuModel. - Create platform-specific subclasses that implement menu delegate interfaces - Push almost all functionality into BackForwardMenuModel * Implement GTK back/forward dropdowns (in MenuGtk and BrowserToolbarViewGtk) Review URL: http://codereview.chromium.org/21440 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9983 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/back_forward_menu_model.cc | 318 +++++++++++++++--------------- 1 file changed, 154 insertions(+), 164 deletions(-) (limited to 'chrome/browser/back_forward_menu_model.cc') diff --git a/chrome/browser/back_forward_menu_model.cc b/chrome/browser/back_forward_menu_model.cc index 50c7da1..f28c60c 100644 --- a/chrome/browser/back_forward_menu_model.cc +++ b/chrome/browser/back_forward_menu_model.cc @@ -1,39 +1,31 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 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 "chrome/browser/browser.h" -#include "chrome/browser/history_tab_ui.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/common/l10n_util.h" #include "net/base/registry_controlled_domain.h" +#if defined(OS_WIN) +// TODO(port): port these headers and remove the platform defines. +#include "chrome/browser/history_tab_ui.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#elif defined(OS_POSIX) +#include "chrome/common/temp_scaffolding_stubs.h" +#endif + #include "generated_resources.h" const int BackForwardMenuModel::kMaxHistoryItems = 12; const int BackForwardMenuModel::kMaxChapterStops = 5; -BackForwardMenuModel::BackForwardMenuModel(Browser* browser, - ModelType model_type) - : browser_(browser), - test_tab_contents_(NULL), - model_type_(model_type) { -} - -BackForwardMenuModel::~BackForwardMenuModel() { -} - -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::GetHistoryItemCount() const { TabContents* contents = GetTabContents(); NavigationController* controller = contents->controller(); @@ -82,7 +74,7 @@ int BackForwardMenuModel::GetChapterStopCount(int history_items) const { return chapter_stops; } -int BackForwardMenuModel::GetItemCount() const { +int BackForwardMenuModel::GetTotalItemCount() const { int items = GetHistoryItemCount(); if (items > 0) { @@ -103,70 +95,105 @@ int BackForwardMenuModel::GetItemCount() const { return items; } -int BackForwardMenuModel::MenuIdToNavEntryIndex(int menu_id) const { +int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from, + bool forward) const { TabContents* contents = GetTabContents(); NavigationController* controller = contents->controller(); - int history_items = GetHistoryItemCount(); - - DCHECK(menu_id > 0); + int max_count = controller->GetEntryCount(); + if (start_from < 0 || start_from >= max_count) + return -1; // Out of bounds. - // Convert anything above the History items separator. - if (menu_id <= history_items) { - if (model_type_ == FORWARD_MENU_DELEGATE) { - // The |menu_id| is relative to our current position, so we need to add. - menu_id += controller->GetCurrentEntryIndex(); + 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 { - // Back menu is reverse. - menu_id = controller->GetCurrentEntryIndex() - menu_id; + return -1; } - return menu_id; } - if (menu_id == history_items + 1) - return -1; // Don't translate the separator for history items. - if (menu_id >= history_items + 1 + GetChapterStopCount(history_items) + 1) - return -1; // This is beyond the last chapter stop so we abort. - - // This menu item is a chapter stop located between the two separators. - menu_id = FindChapterStop(history_items, - model_type_ == FORWARD_MENU_DELEGATE, - menu_id - history_items - 1 - 1); + NavigationEntry* start_entry = controller->GetEntryAtIndex(start_from); + const GURL& url = start_entry->url(); - return menu_id; + 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; + } } -NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int menu_id) const { +int BackForwardMenuModel::FindChapterStop(int offset, + bool forward, + int skip) const { + if (offset < 0 || skip < 0) + return -1; + + if (!forward) + offset *= -1; + TabContents* contents = GetTabContents(); NavigationController* controller = contents->controller(); - int index = MenuIdToNavEntryIndex(menu_id); - return controller->GetEntryAtIndex(index); + int entry = controller->GetCurrentEntryIndex() + offset; + + for (int i = 0; i < skip + 1; i++) + entry = GetIndexOfNextChapterStop(entry, forward); + + return entry; } -std::wstring BackForwardMenuModel::GetLabel(int menu_id) const { - // Return label "Show Full History" for the last item of the menu. - if (menu_id == GetItemCount()) - return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK); +void BackForwardMenuModel::ExecuteCommandById(int menu_id) { + TabContents* contents = GetTabContents(); + NavigationController* controller = contents->controller(); - // Return an empty string for a separator. - if (IsItemSeparator(menu_id)) - return L""; + DCHECK(!IsSeparator(menu_id)); - NavigationEntry* entry = GetNavigationEntry(menu_id); - return entry->title(); -} + // Execute the command for the last item: "Show Full History". + if (menu_id == GetTotalItemCount()) { + UserMetrics::RecordComputedAction(BuildActionName(L"ShowFullHistory", -1), + controller->profile()); +#if defined(OS_WIN) + browser_->ShowNativeUITab(HistoryTabUI::GetURL()); +#else + NOTIMPLEMENTED(); +#endif + return; + } -const SkBitmap& BackForwardMenuModel::GetIcon(int menu_id) const { - // Return NULL if the item doesn't have an icon - if (!HasIcon(menu_id)) - return GetEmptyIcon(); + // Log whether it was a history or chapter click. + if (menu_id <= GetHistoryItemCount()) { + UserMetrics::RecordComputedAction( + BuildActionName(L"HistoryClick", menu_id), controller->profile()); + } else { + UserMetrics::RecordComputedAction( + BuildActionName(L"ChapterClick", menu_id - GetHistoryItemCount() - 1), + controller->profile()); + } - NavigationEntry* entry = GetNavigationEntry(menu_id); - return entry->favicon().bitmap(); + int index = MenuIdToNavEntryIndex(menu_id); + if (index >= 0 && index < controller->GetEntryCount()) + controller->GoToIndex(index); } -bool BackForwardMenuModel::IsItemSeparator(int menu_id) const { +bool BackForwardMenuModel::IsSeparator(int menu_id) const { int history_items = GetHistoryItemCount(); // If the menu_id is higher than the number of history items + separator, // we then consider if it is a chapter-stop entry. @@ -186,135 +213,98 @@ bool BackForwardMenuModel::IsItemSeparator(int menu_id) const { return menu_id == history_items + 1; } -bool BackForwardMenuModel::HasIcon(int menu_id) const { - // Using "id" not "id - 1" because the last item "Show Full History" - // doesn't have an icon. - return menu_id < GetItemCount() && !IsItemSeparator(menu_id); -} - -bool BackForwardMenuModel::SupportsCommand(int menu_id) const { - return menu_id - 1 < GetItemCount() && !IsItemSeparator(menu_id); -} +std::wstring BackForwardMenuModel::GetItemLabel(int menu_id) const { + // Return label "Show Full History" for the last item of the menu. + if (menu_id == GetTotalItemCount()) + return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK); -bool BackForwardMenuModel::IsCommandEnabled(int menu_id) const { - return menu_id - 1 < GetItemCount() && !IsItemSeparator(menu_id); -} + // Return an empty string for a separator. + if (IsSeparator(menu_id)) + return L""; -std::wstring BackForwardMenuModel::BuildActionName( - const std::wstring& action, int index) const { - DCHECK(!action.empty()); - DCHECK(index >= -1); - std::wstring metric_string; - if (model_type_ == FORWARD_MENU_DELEGATE) - metric_string += L"ForwardMenu_"; - else - metric_string += L"BackMenu_"; - metric_string += action; - if (index != -1) - metric_string += IntToWString(index); - return metric_string; + NavigationEntry* entry = GetNavigationEntry(menu_id); + return entry->title(); } -void BackForwardMenuModel::ExecuteCommand(int menu_id) { - TabContents* contents = GetTabContents(); - NavigationController* controller = contents->controller(); - - DCHECK(!IsItemSeparator(menu_id)); +const SkBitmap& BackForwardMenuModel::GetItemIcon(int menu_id) const { + DCHECK(ItemHasIcon(menu_id)); - // Execute the command for the last item: "Show Full History". - if (menu_id == GetItemCount()) { - UserMetrics::RecordComputedAction(BuildActionName(L"ShowFullHistory", -1), - controller->profile()); - browser_->ShowNativeUITab(HistoryTabUI::GetURL()); - return; - } - - // Log whether it was a history or chapter click. - if (menu_id <= GetHistoryItemCount()) { - UserMetrics::RecordComputedAction( - BuildActionName(L"HistoryClick", menu_id), controller->profile()); - } else { - UserMetrics::RecordComputedAction( - BuildActionName(L"ChapterClick", menu_id - GetHistoryItemCount() - 1), - controller->profile()); - } + NavigationEntry* entry = GetNavigationEntry(menu_id); + return entry->favicon().bitmap(); +} - int index = MenuIdToNavEntryIndex(menu_id); - if (index >= 0 && index < controller->GetEntryCount()) - controller->GoToIndex(index); +bool BackForwardMenuModel::ItemHasIcon(int menu_id) const { + // Using "id" not "id - 1" because the last item "Show Full History" + // doesn't have an icon. + return menu_id < GetTotalItemCount() && !IsSeparator(menu_id); } -void BackForwardMenuModel::MenuWillShow() { - UserMetrics::RecordComputedAction(BuildActionName(L"Popup", -1), - browser_->profile()); +bool BackForwardMenuModel::ItemHasCommand(int menu_id) const { + return menu_id - 1 < GetTotalItemCount() && !IsSeparator(menu_id); } std::wstring BackForwardMenuModel::GetShowFullHistoryLabel() const { return l10n_util::GetString(IDS_SHOWFULLHISTORY_LINK); } -int BackForwardMenuModel::GetIndexOfNextChapterStop(int start_from, - bool forward) const { +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::MenuIdToNavEntryIndex(int menu_id) const { TabContents* contents = GetTabContents(); NavigationController* controller = contents->controller(); - int max_count = controller->GetEntryCount(); - if (start_from < 0 || start_from >= max_count) - return -1; // Out of bounds. + int history_items = GetHistoryItemCount(); - 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++; + DCHECK(menu_id > 0); + + // Convert anything above the History items separator. + if (menu_id <= history_items) { + if (model_type_ == FORWARD_MENU_DELEGATE) { + // The |menu_id| is relative to our current position, so we need to add. + menu_id += controller->GetCurrentEntryIndex(); } else { - return -1; + // Back menu is reverse. + menu_id = controller->GetCurrentEntryIndex() - menu_id; } + return menu_id; } + if (menu_id == history_items + 1) + return -1; // Don't translate the separator for history items. - 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; - } -} + if (menu_id >= history_items + 1 + GetChapterStopCount(history_items) + 1) + return -1; // This is beyond the last chapter stop so we abort. -int BackForwardMenuModel::FindChapterStop(int offset, - bool forward, - int skip) const { - if (offset < 0 || skip < 0) - return -1; + // This menu item is a chapter stop located between the two separators. + menu_id = FindChapterStop(history_items, + model_type_ == FORWARD_MENU_DELEGATE, + menu_id - history_items - 1 - 1); - if (!forward) - offset *= -1; + return menu_id; +} +NavigationEntry* BackForwardMenuModel::GetNavigationEntry(int menu_id) const { TabContents* contents = GetTabContents(); NavigationController* controller = contents->controller(); - int entry = controller->GetCurrentEntryIndex() + offset; - - for (int i = 0; i < skip + 1; i++) - entry = GetIndexOfNextChapterStop(entry, forward); - - return entry; + int index = MenuIdToNavEntryIndex(menu_id); + return controller->GetEntryAtIndex(index); } +std::wstring BackForwardMenuModel::BuildActionName( + const std::wstring& action, int index) const { + DCHECK(!action.empty()); + DCHECK(index >= -1); + std::wstring metric_string; + if (model_type_ == FORWARD_MENU_DELEGATE) + metric_string += L"ForwardMenu_"; + else + metric_string += L"BackMenu_"; + metric_string += action; + if (index != -1) + metric_string += IntToWString(index); + return metric_string; +} -- cgit v1.1