1 // Copyright (c) 2011 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 #ifndef CHROME_BROWSER_UI_TOOLBAR_BACK_FORWARD_MENU_MODEL_H_ 6 #define CHROME_BROWSER_UI_TOOLBAR_BACK_FORWARD_MENU_MODEL_H_ 7 #pragma once 8 9 #include <set> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/string16.h" 15 #include "chrome/browser/favicon_service.h" 16 #include "ui/base/models/menu_model.h" 17 #include "webkit/glue/window_open_disposition.h" 18 19 class Browser; 20 class SkBitmap; 21 class TabContents; 22 class NavigationEntry; 23 24 /////////////////////////////////////////////////////////////////////////////// 25 // 26 // BackForwardMenuModel 27 // 28 // Interface for the showing of the dropdown menu for the Back/Forward buttons. 29 // Actual implementations are platform-specific. 30 /////////////////////////////////////////////////////////////////////////////// 31 class BackForwardMenuModel : public ui::MenuModel { 32 public: 33 // These are IDs used to identify individual UI elements within the 34 // browser window using View::GetViewByID. 35 enum ModelType { 36 FORWARD_MENU = 1, 37 BACKWARD_MENU = 2 38 }; 39 40 BackForwardMenuModel(Browser* browser, ModelType model_type); 41 virtual ~BackForwardMenuModel(); 42 43 // MenuModel implementation. 44 virtual bool HasIcons() const; 45 // Returns how many items the menu should show, including history items, 46 // chapter-stops, separators and the Show Full History link. This function 47 // uses GetHistoryItemCount() and GetChapterStopCount() internally to figure 48 // out the total number of items to show. 49 virtual int GetItemCount() const; 50 virtual ItemType GetTypeAt(int index) const; 51 virtual int GetCommandIdAt(int index) const; 52 virtual string16 GetLabelAt(int index) const; 53 virtual bool IsItemDynamicAt(int index) const; 54 virtual bool GetAcceleratorAt(int index, 55 ui::Accelerator* accelerator) const; 56 virtual bool IsItemCheckedAt(int index) const; 57 virtual int GetGroupIdAt(int index) const; 58 virtual bool GetIconAt(int index, SkBitmap* icon); 59 virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const; 60 virtual bool IsEnabledAt(int index) const; 61 virtual MenuModel* GetSubmenuModelAt(int index) const; 62 virtual void HighlightChangedTo(int index); 63 virtual void ActivatedAt(int index); 64 virtual void ActivatedAtWithDisposition(int index, int disposition); 65 virtual void MenuWillShow(); 66 67 // Is the item at |index| a separator? 68 bool IsSeparator(int index) const; 69 70 // Set the delegate for triggering OnIconChanged. 71 virtual void SetMenuModelDelegate(ui::MenuModelDelegate* menu_model_delegate); 72 73 protected: 74 ui::MenuModelDelegate* menu_model_delegate() { return menu_model_delegate_; } 75 76 private: 77 friend class BackFwdMenuModelTest; 78 FRIEND_TEST_ALL_PREFIXES(BackFwdMenuModelTest, BasicCase); 79 FRIEND_TEST_ALL_PREFIXES(BackFwdMenuModelTest, MaxItemsTest); 80 FRIEND_TEST_ALL_PREFIXES(BackFwdMenuModelTest, ChapterStops); 81 FRIEND_TEST_ALL_PREFIXES(BackFwdMenuModelTest, EscapeLabel); 82 FRIEND_TEST_ALL_PREFIXES(BackFwdMenuModelTest, FaviconLoadTest); 83 84 // Requests a favicon from the FaviconService. Called by GetIconAt if the 85 // NavigationEntry has an invalid favicon. 86 void FetchFavicon(NavigationEntry* entry); 87 88 // Callback from the favicon service. 89 void OnFavIconDataAvailable(FaviconService::Handle handle, 90 history::FaviconData favicon); 91 92 // Allows the unit test to use its own dummy tab contents. 93 void set_test_tab_contents(TabContents* test_tab_contents) { 94 test_tab_contents_ = test_tab_contents; 95 } 96 97 // Returns how many history items the menu should show. For example, if the 98 // navigation controller of the current tab has a current entry index of 5 and 99 // forward_direction_ is false (we are the back button delegate) then this 100 // function will return 5 (representing 0-4). If forward_direction_ is 101 // true (we are the forward button delegate), then this function will return 102 // the number of entries after 5. Note, though, that in either case it will 103 // not report more than kMaxHistoryItems. The number returned also does not 104 // include the separator line after the history items (nor the separator for 105 // the "Show Full History" link). 106 int GetHistoryItemCount() const; 107 108 // Returns how many chapter-stop items the menu should show. For the 109 // definition of a chapter-stop, see GetIndexOfNextChapterStop(). The number 110 // returned does not include the separator lines before and after the 111 // chapter-stops. 112 int GetChapterStopCount(int history_items) const; 113 114 // Finds the next chapter-stop in the NavigationEntryList starting from 115 // the index specified in |start_from| and continuing in the direction 116 // specified (|forward|) until either a chapter-stop is found or we reach the 117 // end, in which case -1 is returned. If |start_from| is out of bounds, -1 118 // will also be returned. A chapter-stop is defined as the last page the user 119 // browsed to within the same domain. For example, if the user's homepage is 120 // Google and she navigates to Google pages G1, G2 and G3 before heading over 121 // to WikiPedia for pages W1 and W2 and then back to Google for pages G4 and 122 // G5 then G3, W2 and G5 are considered chapter-stops. The return value from 123 // this function is an index into the NavigationEntryList vector. 124 int GetIndexOfNextChapterStop(int start_from, bool forward) const; 125 126 // Finds a given chapter-stop starting at the currently active entry in the 127 // NavigationEntryList vector advancing first forward or backward by |offset| 128 // (depending on the direction specified in parameter |forward|). It also 129 // allows you to skip chapter-stops by specifying a positive value for |skip|. 130 // Example: FindChapterStop(5, false, 3) starts with the currently active 131 // index, subtracts 5 from it and then finds the fourth chapter-stop before 132 // that index (skipping the first 3 it finds). 133 // Example: FindChapterStop(0, true, 0) is functionally equivalent to 134 // calling GetIndexOfNextChapterStop(GetCurrentEntryIndex(), true). 135 // 136 // NOTE: Both |offset| and |skip| must be non-negative. The return value from 137 // this function is an index into the NavigationEntryList vector. If |offset| 138 // is out of bounds or if we skip too far (run out of chapter-stops) this 139 // function returns -1. 140 int FindChapterStop(int offset, bool forward, int skip) const; 141 142 // How many items (max) to show in the back/forward history menu dropdown. 143 static const int kMaxHistoryItems; 144 145 // How many chapter-stops (max) to show in the back/forward dropdown list. 146 static const int kMaxChapterStops; 147 148 // Takes a menu item index as passed in through one of the menu delegate 149 // functions and converts it into an index into the NavigationEntryList 150 // vector. |index| can point to a separator, or the 151 // "Show Full History" link in which case this function returns -1. 152 int MenuIndexToNavEntryIndex(int index) const; 153 154 // Does the item have a command associated with it? 155 bool ItemHasCommand(int index) const; 156 157 // Returns true if there is an icon for this menu item. 158 bool ItemHasIcon(int index) const; 159 160 // Allow the unit test to use the "Show Full History" label. 161 string16 GetShowFullHistoryLabel() const; 162 163 // Looks up a NavigationEntry by menu id. 164 NavigationEntry* GetNavigationEntry(int index) const; 165 166 // Retrieves the TabContents pointer to use, which is either the one that 167 // the unit test sets (using SetTabContentsForUnitTest) or the one from 168 // the browser window. 169 TabContents* GetTabContents() const; 170 171 // Build a string version of a user action on this menu, used as an 172 // identifier for logging user behavior. 173 // E.g. BuildActionName("Click", 2) returns "BackMenu_Click2". 174 // An index of -1 means no index. 175 std::string BuildActionName(const std::string& name, int index) const; 176 177 Browser* browser_; 178 179 // The unit tests will provide their own TabContents to use. 180 TabContents* test_tab_contents_; 181 182 // Represents whether this is the delegate for the forward button or the 183 // back button. 184 ModelType model_type_; 185 186 // Keeps track of which favicons have already been requested from the history 187 // to prevent duplicate requests, identified by NavigationEntry->unique_id(). 188 std::set<int> requested_favicons_; 189 190 // Used for loading favicons from history. 191 CancelableRequestConsumerTSimple<int> load_consumer_; 192 193 // Used for receiving notifications when an icon is changed. 194 ui::MenuModelDelegate* menu_model_delegate_; 195 196 DISALLOW_COPY_AND_ASSIGN(BackForwardMenuModel); 197 }; 198 199 #endif // CHROME_BROWSER_UI_TOOLBAR_BACK_FORWARD_MENU_MODEL_H_ 200