summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/history_menu_bridge.h
blob: c67ba8327308d7a61132c172951b6b51b86f43ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 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.

// C++ controller 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, bookmark 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.

#ifndef CHROME_BROWSER_COCOA_HISTORY_MENU_BRIDGE_H_
#define CHROME_BROWSER_COCOA_HISTORY_MENU_BRIDGE_H_

#import <Cocoa/Cocoa.h>
#include "base/scoped_nsobject.h"
#include "chrome/browser/cancelable_request.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/common/notification_observer.h"

class NavigationEntry;
class NotificationRegistrar;
class PageUsageData;
class Profile;
class TabNavigationEntry;
@class HistoryMenuCocoaController;

class HistoryMenuBridge : public NotificationObserver,
                          public TabRestoreService::Observer {
 public:
  // This is a generalization of the data we store in the history menu because
  // we pull things from different sources with different data types.
  struct HistoryItem {
    HistoryItem() {}
    ~HistoryItem() {}

    string16 title;
    GURL url;
  };

  HistoryMenuBridge(Profile* profile);
  virtual ~HistoryMenuBridge();

  // Overriden from NotificationObserver.
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // For TabRestoreService::Observer
  virtual void TabRestoreServiceChanged(TabRestoreService* service);
  virtual void TabRestoreServiceDestroyed(TabRestoreService* service);

  // 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();
  std::vector<HistoryItem>* visited_results();
  std::vector<HistoryItem>* 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(const 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
  // change notifications and calling CreateMenu().
  void Init();

  // Does the query for the history information to create the menu.
  void CreateMenu();

  // Callback method for when HistoryService query results are ready with the
  // most recently-visited sites.
  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);

 private:
  friend class HistoryMenuBridgeTest;

  scoped_nsobject<HistoryMenuCocoaController> controller_;  // strong

  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.
  std::vector<HistoryItem> visited_results_;
  std::vector<HistoryItem> closed_results_;

  // 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.
  bool create_in_progress_;
  bool need_recreate_;

  DISALLOW_COPY_AND_ASSIGN(HistoryMenuBridge);
};

#endif  // CHROME_BROWSER_COCOA_HISTORY_MENU_BRIDGE_H_