12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CHROME_BROWSER_UI_TOOLBAR_RECENT_TABS_SUB_MENU_MODEL_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CHROME_BROWSER_UI_TOOLBAR_RECENT_TABS_SUB_MENU_MODEL_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_observer.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/glue/synced_session.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/accelerators/accelerator.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/models/simple_menu_model.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Browser;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct SessionTab;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace browser_sync {
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class OpenTabsUIDelegate;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace favicon_base {
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct FaviconImageResult;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gfx {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Image;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ui {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AcceleratorProvider;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A menu model that builds the contents of "Recent tabs" submenu, which include
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// the recently closed tabs/windows of current device i.e. local entries, and
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// opened tabs of other devices.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RecentTabsSubMenuModel : public ui::SimpleMenuModel,
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               public ui::SimpleMenuModel::Delegate,
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               public TabRestoreServiceObserver {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Command Id for recently closed items header or disabled item to which the
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // accelerator string will be appended.
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const int kRecentlyClosedHeaderCommandId;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const int kDisabledRecentlyClosedHeaderCommandId;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Exposed for tests only: return the Command Id for the first entry in the
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // recently closed window items list.
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  static int GetFirstRecentTabsCommandId();
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If |open_tabs_delegate| is NULL, the default delegate for |browser|'s
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // profile will be used. Testing may require a specific |open_tabs_delegate|.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecentTabsSubMenuModel(ui::AcceleratorProvider* accelerator_provider,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         Browser* browser,
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         browser_sync::OpenTabsUIDelegate* open_tabs_delegate);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~RecentTabsSubMenuModel();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from ui::SimpleMenuModel::Delegate:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetAcceleratorForCommandId(
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int command_id,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::Accelerator* accelerator) OVERRIDE;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int GetMaxWidthForItemAtIndex(int item_index) const;
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool GetURLAndTitleForItemAtIndex(int index,
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    std::string* url,
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    base::string16* title);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct TabNavigationItem;
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef std::vector<TabNavigationItem> TabNavigationItems;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef std::vector<SessionID::id_type> WindowItems;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build the menu items by populating the menumodel.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Build();
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build the recently closed tabs and windows items.
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void BuildLocalEntries();
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build the tabs items from other devices.
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void BuildTabsFromOtherDevices();
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build a recently closed tab item with parameters needed to restore it, and
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // add it to the menumodel at |curr_model_index|.
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void BuildLocalTabItem(int seesion_id,
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         const base::string16& title,
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                         const GURL& url,
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                         int curr_model_index);
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build the recently closed window item with parameters needed to restore it,
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // and add it to the menumodel at |curr_model_index|.
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void BuildLocalWindowItem(const SessionID::id_type& window_id,
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int num_tabs,
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            int curr_model_index);
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Build the tab item for other devices with parameters needed to restore it.
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void BuildOtherDevicesTabItem(const std::string& session_tag,
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                const SessionTab& tab);
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Add the favicon for the device section header.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddDeviceFavicon(int index_in_menu,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        browser_sync::SyncedSession::DeviceType device_type);
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Add the favicon for a local or other devices' tab asynchronously,
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // OnFaviconDataAvailable() will be invoked when the favicon is ready.
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void AddTabFavicon(int command_id, const GURL& url);
1140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void OnFaviconDataAvailable(
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      int command_id,
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const favicon_base::FaviconImageResult& image_result);
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Clear all recently closed tabs and windows.
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void ClearLocalEntries();
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Converts |command_id| of menu item to index in local or other devices'
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TabNavigationItems, and returns the corresponding local or other devices'
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TabNavigationItems in |tab_items|.
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int CommandIdToTabVectorIndex(int command_id, TabNavigationItems** tab_items);
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Used to access (and lazily initialize) open_tabs_delegate_.
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // TODO(tim): This lazy-init for member variables is error prone because you
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // can always skip going through the function and access the field directly.
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Consider instead having code just deal with potentially NULL open_tabs_
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // and have it initialized by an event / callback.
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  browser_sync::OpenTabsUIDelegate* GetOpenTabsUIDelegate();
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Overridden from TabRestoreServiceObserver:
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE;
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE;
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* browser_;  // Weak.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  browser_sync::OpenTabsUIDelegate* open_tabs_delegate_;  // Weak.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Accelerator for reopening last closed tab.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::Accelerator reopen_closed_tab_accelerator_;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Navigation items for local recently closed tabs.  The |command_id| for
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // these is set to |kFirstLocalTabCommandId| plus the index into the vector.
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Upon invocation of the menu, the navigation information is retrieved from
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |local_tab_navigation_items_| and used to navigate to the item specified.
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TabNavigationItems local_tab_navigation_items_;
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Similar to |local_tab_navigation_items_| except the tabs are opened tabs
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // from other devices, and the first |command_id| is
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |kFirstOtherDevicesTabCommandId|.
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TabNavigationItems other_devices_tab_navigation_items_;
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Window items for local recently closed windows.  The |command_id| for
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // these is set to |kFirstLocalWindowCommandId| plus the index into the
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // vector.  Upon invocation of the menu, information is retrieved from
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // |local_window_items_| and used to create the specified window.
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WindowItems local_window_items_;
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Index of the last local entry (recently closed tab or window) in the
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // menumodel.
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int last_local_model_index_;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Image default_favicon_;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::CancelableTaskTracker local_tab_cancelable_task_tracker_;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::CancelableTaskTracker other_devices_tab_cancelable_task_tracker_;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WeakPtrFactory<RecentTabsSubMenuModel> weak_ptr_factory_;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RecentTabsSubMenuModel);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CHROME_BROWSER_UI_TOOLBAR_RECENT_TABS_SUB_MENU_MODEL_H_
176