summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/history_menu_bridge.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa/history_menu_bridge.h')
-rw-r--r--chrome/browser/cocoa/history_menu_bridge.h148
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_;