diff options
Diffstat (limited to 'chrome/browser/cocoa/history_menu_bridge.h')
-rw-r--r-- | chrome/browser/cocoa/history_menu_bridge.h | 148 |
1 files changed, 104 insertions, 44 deletions
diff --git a/chrome/browser/cocoa/history_menu_bridge.h b/chrome/browser/cocoa/history_menu_bridge.h index bfa7959b..ef84031 100644 --- a/chrome/browser/cocoa/history_menu_bridge.h +++ b/chrome/browser/cocoa/history_menu_bridge.h @@ -6,12 +6,14 @@ #define CHROME_BROWSER_COCOA_HISTORY_MENU_BRIDGE_H_ #import <Cocoa/Cocoa.h> +#include <map> + #include "base/scoped_nsobject.h" #include "base/scoped_ptr.h" -#include "base/scoped_vector.h" #include "chrome/browser/cancelable_request.h" #import "chrome/browser/favicon_service.h" #include "chrome/browser/history/history.h" +#include "chrome/browser/sessions/session_id.h" #include "chrome/browser/sessions/tab_restore_service.h" #include "chrome/common/notification_observer.h" @@ -22,24 +24,34 @@ class Profile; class TabNavigationEntry; @class HistoryMenuCocoaController; -// C++ controller for the history menu; one per AppController (means there +namespace { + +class HistoryMenuBridgeTest; + +} + +// C++ bridge for the history menu; one per AppController (means there // is only one). This class observes various data sources, namely the // HistoryService and the TabRestoreService, and then updates the NSMenu when // there is new data. // // The history menu is broken up into sections: most visisted and recently -// closed. The overall menu has a tag of IDC_HISTORY_MENU, with two sections -// IDC_HISTORY_MENU_VISITED and IDC_HISTORY_MENU_CLOSED, which are used to -// delineate the two sections. Items within these sections are assigned tags -// within IDC_HISTORY_MENU_* + 1..99. Most Chromium Cocoa menu items are static -// from a nib (e.g. New Tab), but may be enabled/disabled under certain -// circumstances (e.g. Cut and Paste). In addition, most Cocoa menu items have -// firstResponder: as a target. Unusually, history menu items are created -// dynamically. They also have a target of HistoryMenuCocoaController, not -// firstResponder. See HistoryMenuBridge::AddItemToMenu(). Unlike most of our -// Cocoa-Bridge classes, the HMCC is not at the root of the ownership model -// because its only function is to respond to menu item actions; everything -// else is done in this bridge. +// closed. The overall menu has a tag of IDC_HISTORY_MENU, with the user content +// items having the local tags defined in the enum below. Items within a section +// all share the same tag. The structure of the menu is laid out in MainMenu.xib +// and the generated content is inserted after the Title elements. The recently +// closed section is special in that those menu items can have submenus to list +// all the tabs within that closed window. By convention, these submenu items +// have a tag that's equal to the parent + 1. Tags within the history menu have +// a range of [400,500) and do not go through CommandDispatch for their target- +// action mechanism. +// +// These menu items do not use firstResponder as their target. Rather, they are +// hooked directly up to the HistoryMenuCocoaController that then bridges back +// to this class. These items are created via the AddItemToMenu() helper. Also, +// unlike the typical ownership model, this bridge owns its controller. The +// controller is very thin and only exists to interact with Cocoa, but this +// class does the bulk of the work. class HistoryMenuBridge : public NotificationObserver, public TabRestoreService::Observer { public: @@ -47,7 +59,19 @@ class HistoryMenuBridge : public NotificationObserver, // we pull things from different sources with different data types. struct HistoryItem { public: - HistoryItem() : icon_requested(false) {} + HistoryItem() + : icon_requested(false), + menu_item(nil), + session_id(0) {} + + // Copy constructor allowed. + HistoryItem(const HistoryItem& copy) + : title(copy.title), + url(copy.url), + icon_requested(false), + menu_item(nil), + session_id(copy.session_id) {} + ~HistoryItem() {} // The title for the menu item. @@ -67,8 +91,36 @@ class HistoryMenuBridge : public NotificationObserver, // The pointer to the item after it has been created. Weak. NSMenuItem* menu_item; + // This ID is unique for a browser session and can be passed to the + // TabRestoreService to re-open the closed window or tab that this + // references. A non-0 session ID indicates that this is an entry can be + // restored that way. Otherwise, the URL will be used to open the item and + // this ID will be 0. + SessionID::id_type session_id; + + // If the HistoryItem is a window, this will be the vector of tabs. Note + // that this is a list of weak references. The |menu_item_map_| is the owner + // of all items. If it is not a window, then the entry is a single page and + // the vector will be empty. + std::vector<HistoryItem*> tabs; + private: - DISALLOW_COPY_AND_ASSIGN(HistoryItem); + // Copying is explicitly allowed, but assignment is not. + void operator=(const HistoryItem&); + }; + + // These tags are not global view tags and are local to the history menu. The + // normal procedure for menu items is to go through CommandDispatch, but since + // history menu items are hooked directly up to their target, they do not need + // to have the global IDC view tags. + enum Tags { + kMostVisitedSeparator = 400, // Separator before most visited section. + kMostVisitedTitle = 401, // Title of the most visited section. + kMostVisited = 420, // Used for all entries in the most visited section. + kRecentlyClosedSeparator = 440, // Item before recently closed section. + kRecentlyClosedTitle = 441, // Title of recently closed section. + kRecentlyClosed = 460, // Used for items in the recently closed section. + kShowFullSeparator = 480 // Separator after the recently closed section. }; explicit HistoryMenuBridge(Profile* profile); @@ -83,27 +135,34 @@ class HistoryMenuBridge : public NotificationObserver, virtual void TabRestoreServiceChanged(TabRestoreService* service); virtual void TabRestoreServiceDestroyed(TabRestoreService* service); + // Looks up an NSMenuItem in the |menu_item_map_| and returns the + // corresponding HistoryItem. + HistoryItem* HistoryItemForMenuItem(NSMenuItem* item); + // I wish I has a "friend @class" construct. These are used by the HMCC // to access model information when responding to actions. HistoryService* service(); Profile* profile(); - const ScopedVector<HistoryItem>* const visited_results(); - const ScopedVector<HistoryItem>* const closed_results(); protected: // Return the History menu. - NSMenu* HistoryMenu(); - - // Clear items in the given |menu|. The menu is broken into sections, defined - // by IDC_HISTORY_MENU_* constants. This function will clear |count| menu - // items, starting from |tag|. - void ClearMenuSection(NSMenu* menu, NSInteger tag, unsigned int count); - - // Adds a given title and URL to HistoryMenu() with a certain tag and index. - void AddItemToMenu(HistoryItem* item, - NSMenu* menu, - NSInteger tag, - NSInteger index); + virtual NSMenu* HistoryMenu(); + + // Clear items in the given |menu|. Menu items in the same section are given + // the same tag. This will go through the entire history menu, removing all + // items with a given tag. Note that this will recurse to submenus, removing + // child items from the menu item map. This will only remove items that have + // a target hooked up to the |controller_|. + void ClearMenuSection(NSMenu* menu, NSInteger tag); + + // Adds a given title and URL to the passed-in menu with a certain tag and + // index. This will add |item| and the newly created menu item to the + // |menu_item_map_|, which takes ownership. Items are deleted in + // ClearMenuSection(). This returns the new menu item that was just added. + NSMenuItem* AddItemToMenu(HistoryItem* item, + NSMenu* menu, + NSInteger tag, + NSInteger index); // Called by the ctor if |service_| is ready at the time, or by a // notification receiver. Finishes initialization tasks by subscribing for @@ -118,9 +177,9 @@ class HistoryMenuBridge : public NotificationObserver, void OnVisitedHistoryResults(CancelableRequestProvider::Handle handle, std::vector<PageUsageData*>* results); - // Tries to add the current Tab's TabNavigationEntry's NavigationEntry object - // to |closed_results_|. Return TRUE if the operation completed successfully. - bool AddNavigationForTab(const TabRestoreService::Tab& entry); + // Creates a HistoryItem* for the given tab entry. Caller takes ownership of + // the result and must delete it when finished. + HistoryItem* HistoryItemForTab(const TabRestoreService::Tab& entry); // Helper function that sends an async request to the FaviconService to get // an icon. The callback will update the NSMenuItem directly. @@ -141,28 +200,29 @@ class HistoryMenuBridge : public NotificationObserver, void CancelFaviconRequest(HistoryItem* item); private: - friend class HistoryMenuBridgeTest; + friend class ::HistoryMenuBridgeTest; + friend class HistoryMenuCocoaControllerTest; scoped_nsobject<HistoryMenuCocoaController> controller_; // strong - Profile* profile_; // weak - HistoryService* history_service_; // weak - TabRestoreService* tab_restore_service_; // weak + Profile* profile_; // weak + HistoryService* history_service_; // weak + TabRestoreService* tab_restore_service_; // weak NotificationRegistrar registrar_; CancelableRequestConsumer cancelable_request_consumer_; - // The most recent results we've received. - ScopedVector<HistoryItem> visited_results_; - ScopedVector<HistoryItem> closed_results_; + // Mapping of NSMenuItems to HistoryItems. This owns the HistoryItems until + // they are removed and deleted via ClearMenuSection(). + std::map<NSMenuItem*, HistoryItem*> menu_item_map_; // Maps HistoryItems to favicon request Handles. CancelableRequestConsumerTSimple<HistoryItem*> favicon_consumer_; - // We coalesce requests to re-create the menu. |create_in_progress_| is true - // whenever we are either waiting for the history service to return query - // results, or when we are rebuilding. |need_recreate_| is true whenever a - // rebuild has been scheduled but is waiting for the current one to finish. + // Requests to re-create the menu are coalesced. |create_in_progress_| is true + // when either waiting for the history service to return query results, or + // when the menu is rebuilding. |need_recreate_| is true whenever a rebuild + // has been scheduled but is waiting for the current one to finish. bool create_in_progress_; bool need_recreate_; |