| Index: chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
|
| diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
|
| index 0ab3291188a7d7226e938272c0ed03b7daf2ff2c..33a24ffd96f6b3d58b3d9236c8ce576ee90154bb 100644
|
| --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
|
| +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
|
| @@ -41,22 +41,26 @@
|
|
|
| namespace {
|
|
|
| -// First comamnd id for navigatable (and hence executable) tab menu item.
|
| +// First comamnd id for navigatable (and hence executable) tab/window menu item.
|
| // The models and menu are not 1-1:
|
| -// - menu has "Reopen closed tab", "No tabs from other devices", device section
|
| -// headers, separators and executable tab items.
|
| -// - |tab_navigation_items_| only has navigatabale/executable tab items.
|
| -// - |window_items_| only has executable open window items.
|
| -// Using an initial command ids for tab/window items makes it easier and less
|
| -// error-prone to manipulate the models and menu.
|
| -// These values must be bigger than the maximum possible number of items in
|
| -// menu, so that index of last menu item doesn't clash with this value when menu
|
| -// items are retrieved via GetIndexOfCommandId.
|
| -const int kFirstTabCommandId = 100;
|
| -const int kFirstWindowCommandId = 200;
|
| -
|
| -// The maximum number of recently closed entries to be shown in the menu.
|
| -const int kMaxRecentlyClosedEntries = 8;
|
| +// - menu has "Recently closed" header, "No tabs from other devices", device
|
| +// section headers, separators, executable local and foreign tab items, and
|
| +// executable local window items.
|
| +// - |local_tab_navigation_items_| and |foreign_tab_navigation_items_| only have
|
| +// navigatabale/executable tab items.
|
| +// - |local_window_items_| only has executable open window items.
|
| +// Using initial command ids for local tab, local window and foreign tab items
|
| +// makes it easier and less error-prone to manipulate the models, data vectors
|
| +// and menu. These ids must be bigger than the maximum possible number of
|
| +// items in menu, so that index of the last menu item doesn't clash with these
|
| +// values when menu items are retrieved via GetIndexOfCommandId.
|
| +const int kFirstLocalTabCommandId = 100;
|
| +const int kFirstLocalWindowCommandId = 200;
|
| +const int kFirstForeignTabCommandId = 300;
|
| +
|
| +// The maximum number of local recently closed entries (tab or window) to be
|
| +// shown in the menu.
|
| +const int kMaxLocalEntries = 8;
|
|
|
| // Comparator function for use with std::sort that will sort sessions by
|
| // descending modified_time (i.e., most recent first).
|
| @@ -71,43 +75,42 @@ bool SortTabsByRecency(const SessionTab* t1, const SessionTab* t2) {
|
| return t1->timestamp > t2->timestamp;
|
| }
|
|
|
| -// Returns true if the command id is related to a tab model index.
|
| +// Returns true if the command id identifies a tab model index.
|
| bool IsTabModelCommandId(int command_id) {
|
| - return command_id >= kFirstTabCommandId && command_id < kFirstWindowCommandId;
|
| + return command_id >= kFirstForeignTabCommandId ||
|
| + (command_id >= kFirstLocalTabCommandId &&
|
| + command_id < kFirstLocalWindowCommandId);
|
| }
|
|
|
| -// Returns true if the command id is related to a window model index.
|
| +// Returns true if the command id identifies a window model index.
|
| bool IsWindowModelCommandId(int command_id) {
|
| - return command_id >= kFirstWindowCommandId &&
|
| + return command_id >= kFirstLocalWindowCommandId &&
|
| command_id < RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId;
|
| }
|
|
|
| -// Convert |tab_model_index| to command id of menu item.
|
| -int TabModelIndexToCommandId(int tab_model_index) {
|
| - int command_id = tab_model_index + kFirstTabCommandId;
|
| - DCHECK_LT(command_id, kFirstWindowCommandId);
|
| +// Convert |tab_model_index| to command id of menu item, with |first_command_id|
|
| +// as the base command id.
|
| +int TabModelIndexToCommandId(int tab_model_index, int first_command_id) {
|
| + int command_id = tab_model_index + first_command_id;
|
| + DCHECK(first_command_id == kFirstForeignTabCommandId ||
|
| + command_id < kFirstLocalWindowCommandId);
|
| return command_id;
|
| }
|
|
|
| -// Convert |command_id| of menu item to index in tab model.
|
| -int CommandIdToTabModelIndex(int command_id) {
|
| - DCHECK_GE(command_id, kFirstTabCommandId);
|
| - DCHECK_LT(command_id, kFirstWindowCommandId);
|
| - return command_id - kFirstTabCommandId;
|
| -}
|
| -
|
| // Convert |window_model_index| to command id of menu item.
|
| int WindowModelIndexToCommandId(int window_model_index) {
|
| - int command_id = window_model_index + kFirstWindowCommandId;
|
| + int command_id = window_model_index + kFirstLocalWindowCommandId;
|
| + DCHECK_LT(command_id, kFirstForeignTabCommandId);
|
| DCHECK_LT(command_id, RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId);
|
| return command_id;
|
| }
|
|
|
| // Convert |command_id| of menu item to index in window model.
|
| int CommandIdToWindowModelIndex(int command_id) {
|
| - DCHECK_GE(command_id, kFirstWindowCommandId);
|
| + DCHECK_GE(command_id, kFirstLocalWindowCommandId);
|
| + DCHECK_LT(command_id, kFirstForeignTabCommandId);
|
| DCHECK_LT(command_id, RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId);
|
| - return command_id - kFirstWindowCommandId;
|
| + return command_id - kFirstLocalWindowCommandId;
|
| }
|
|
|
| } // namespace
|
| @@ -120,7 +123,8 @@ enum RecentTabAction {
|
| LIMIT_RECENT_TAB_ACTION
|
| };
|
|
|
| -// An element in |RecentTabsSubMenuModel::tab_navigation_items_| that stores
|
| +// An element in |RecentTabsSubMenuModel::local_tab_navigation_items_| or
|
| +// |RecentTabsSubMenuModel::foreign_tab_navigation_items_| that stores
|
| // the navigation information of a local or foreign tab required to restore the
|
| // tab.
|
| struct RecentTabsSubMenuModel::TabNavigationItem {
|
| @@ -157,9 +161,26 @@ RecentTabsSubMenuModel::RecentTabsSubMenuModel(
|
| : ui::SimpleMenuModel(this),
|
| browser_(browser),
|
| associator_(associator),
|
| + last_local_model_index_(-1),
|
| default_favicon_(ResourceBundle::GetSharedInstance().
|
| GetNativeImageNamed(IDR_DEFAULT_FAVICON)),
|
| weak_ptr_factory_(this) {
|
| + // Invoke asynchronous call to load tabs from local last session, which does
|
| + // nothing if the tabs have already been loaded or they shouldn't be loaded.
|
| + // TabRestoreServiceChanged() will be called after the tabs are loaded.
|
| + TabRestoreService* service =
|
| + TabRestoreServiceFactory::GetForProfile(browser_->profile());
|
| + if (service) {
|
| + service->LoadTabsFromLastSession();
|
| +
|
| +// TODO(sail): enable this when mac implements the dynamic menu, together with
|
| +// MenuModelDelegate::PrepareChange, OnItemRemoved, OnItemAdded and ChangesDone.
|
| +#if !defined(OS_MACOSX)
|
| + service->AddObserver(this);
|
| +#endif
|
| + }
|
| +
|
| + // Build the menu.
|
| Build();
|
|
|
| // Retrieve accelerator key for IDC_RESTORE_TAB now, because on ASH, it's not
|
| @@ -183,6 +204,29 @@ RecentTabsSubMenuModel::RecentTabsSubMenuModel(
|
| }
|
|
|
| RecentTabsSubMenuModel::~RecentTabsSubMenuModel() {
|
| + TabRestoreService* service =
|
| + TabRestoreServiceFactory::GetForProfile(browser_->profile());
|
| + if (service)
|
| + service->RemoveObserver(this);
|
| +}
|
| +
|
| +int RecentTabsSubMenuModel::ModelIndexToIdInParentMenu(int model_index) const {
|
| + // If |model_index| identifies a local tab/window menu item, return as is;
|
| + // otherwise, reserve enough id's for maximum possible local entries.
|
| + if (model_index <= last_local_model_index_)
|
| + return model_index;
|
| + return model_index + kMaxLocalEntries - last_local_model_index_;
|
| +}
|
| +
|
| +int RecentTabsSubMenuModel::IdInParentMenuToModelIndex(
|
| + int id_in_parent_menu) const {
|
| + // If |id_in_parent_menu| identifies a local tab/window menu item, return as
|
| + // is; otherwise, ModelIndexToIdInParentMenu() would have reserved enough Id's
|
| + // for maximum possible local entries, so reverse that logic.
|
| + int index = id_in_parent_menu <= last_local_model_index_ ? id_in_parent_menu :
|
| + id_in_parent_menu - kMaxLocalEntries + last_local_model_index_;
|
| + DCHECK(index >= 0 && index < GetItemCount());
|
| + return index;
|
| }
|
|
|
| bool RecentTabsSubMenuModel::IsCommandIdChecked(int command_id) const {
|
| @@ -238,10 +282,9 @@ void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
|
| TabRestoreServiceDelegate::FindDelegateForWebContents(
|
| browser_->tab_strip_model()->GetActiveWebContents());
|
| if (IsTabModelCommandId(command_id)) {
|
| - int model_idx = CommandIdToTabModelIndex(command_id);
|
| - DCHECK(model_idx >= 0 &&
|
| - model_idx < static_cast<int>(tab_navigation_items_.size()));
|
| - const TabNavigationItem& item = tab_navigation_items_[model_idx];
|
| + TabNavigationItems* tab_items = NULL;
|
| + int model_idx = CommandIdToTabModelIndex(command_id, &tab_items);
|
| + const TabNavigationItem& item = tab_items->at(model_idx);
|
| DCHECK(item.tab_id > -1 && item.url.is_valid());
|
|
|
| if (item.session_tag.empty()) { // Restore tab of local session.
|
| @@ -271,10 +314,10 @@ void RecentTabsSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
|
| if (service && delegate) {
|
| int model_idx = CommandIdToWindowModelIndex(command_id);
|
| DCHECK(model_idx >= 0 &&
|
| - model_idx < static_cast<int>(window_items_.size()));
|
| + model_idx < static_cast<int>(local_window_items_.size()));
|
| UMA_HISTOGRAM_ENUMERATION("WrenchMenu.RecentTabsSubMenu", RESTORE_WINDOW,
|
| LIMIT_RECENT_TAB_ACTION);
|
| - service->RestoreEntryById(delegate, window_items_[model_idx],
|
| + service->RestoreEntryById(delegate, local_window_items_[model_idx],
|
| browser_->host_desktop_type(), disposition);
|
| }
|
| }
|
| @@ -300,17 +343,15 @@ int RecentTabsSubMenuModel::GetMaxWidthForItemAtIndex(int item_index) const {
|
| return 320;
|
| }
|
|
|
| -bool RecentTabsSubMenuModel::GetURLAndTitleForItemAtIndex(
|
| - int index,
|
| - std::string* url,
|
| - string16* title) const {
|
| +bool RecentTabsSubMenuModel::GetURLAndTitleForItemAtIndex(int index,
|
| + std::string* url,
|
| + string16* title) {
|
| int command_id = GetCommandIdAt(index);
|
| if (IsTabModelCommandId(command_id)) {
|
| - int model_idx = CommandIdToTabModelIndex(command_id);
|
| - DCHECK(model_idx >= 0 &&
|
| - model_idx < static_cast<int>(tab_navigation_items_.size()));
|
| - *url = tab_navigation_items_[model_idx].url.possibly_invalid_spec();
|
| - *title = tab_navigation_items_[model_idx].title;
|
| + TabNavigationItems* tab_items = NULL;
|
| + int model_idx = CommandIdToTabModelIndex(command_id, &tab_items);
|
| + *url = tab_items->at(model_idx).url.possibly_invalid_spec();
|
| + *title = tab_items->at(model_idx).title;
|
| return true;
|
| }
|
| return false;
|
| @@ -318,66 +359,81 @@ bool RecentTabsSubMenuModel::GetURLAndTitleForItemAtIndex(
|
|
|
| void RecentTabsSubMenuModel::Build() {
|
| // The menu contains:
|
| - // - Recently closed tabs header, then list of tabs, then separator
|
| + // - Recently closed header, then list of local recently closed tabs/windows,
|
| + // then separator
|
| // - device 1 section header, then list of tabs from device, then separator
|
| // - device 2 section header, then list of tabs from device, then separator
|
| // - device 3 section header, then list of tabs from device, then separator
|
| // - More... to open the history tab to get more other devices.
|
| - // |tab_navigation_items_| only contains navigatable (and hence executable)
|
| - // tab items for other devices, and |window_items_| contains the recently
|
| - // closed windows.
|
| - BuildRecentTabs();
|
| - BuildDevices();
|
| + // |local_tab_navigation_items_| and |foreign_tab_navigation_items_| only
|
| + // contain navigatable (and hence executable) tab items for local recently
|
| + // closed tabs and tabs of other devices respectively.
|
| + // |local_window_items_| contains the local recently closed windows.
|
| + BuildLocalEntries();
|
| + BuildForeignTabs();
|
| }
|
|
|
| -void RecentTabsSubMenuModel::BuildRecentTabs() {
|
| - ListValue recently_closed_list;
|
| +void RecentTabsSubMenuModel::BuildLocalEntries() {
|
| + // All local items use InsertItem*At() to append or insert a menu item.
|
| + // We're appending if building the entries for the first time i.e. invoked
|
| + // from Constructor(), inserting when local entries change subsequently i.e.
|
| + // invoked from TabRestoreServiceChanged().
|
| +
|
| + int curr_model_index = 0;
|
| +
|
| TabRestoreService* service =
|
| TabRestoreServiceFactory::GetForProfile(browser_->profile());
|
| - if (service) {
|
| - // This does nothing if the tabs have already been loaded or they
|
| - // shouldn't be loaded.
|
| - service->LoadTabsFromLastSession();
|
| - }
|
| -
|
| if (!service || service->entries().size() == 0) {
|
| // This is to show a disabled restore tab entry with the accelerator to
|
| // teach users about this command.
|
| - AddItemWithStringId(kDisabledRecentlyClosedHeaderCommandId,
|
| - IDS_NEW_TAB_RECENTLY_CLOSED);
|
| - return;
|
| - }
|
| -
|
| - AddItemWithStringId(kRecentlyClosedHeaderCommandId,
|
| - IDS_NEW_TAB_RECENTLY_CLOSED);
|
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| - SetIcon(GetItemCount() - 1,
|
| - rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
|
| -
|
| - int added_count = 0;
|
| - TabRestoreService::Entries entries = service->entries();
|
| - for (TabRestoreService::Entries::const_iterator it = entries.begin();
|
| - it != entries.end() && added_count < kMaxRecentlyClosedEntries; ++it) {
|
| - TabRestoreService::Entry* entry = *it;
|
| - if (entry->type == TabRestoreService::TAB) {
|
| - TabRestoreService::Tab* tab = static_cast<TabRestoreService::Tab*>(entry);
|
| - const sessions::SerializedNavigationEntry& current_navigation =
|
| - tab->navigations.at(tab->current_navigation_index);
|
| - BuildLocalTabItem(
|
| - entry->id,
|
| - current_navigation.title(),
|
| - current_navigation.virtual_url());
|
| - } else {
|
| - DCHECK_EQ(entry->type, TabRestoreService::WINDOW);
|
| - BuildWindowItem(
|
| - entry->id,
|
| - static_cast<TabRestoreService::Window*>(entry)->tabs.size());
|
| + InsertItemWithStringIdAt(curr_model_index++,
|
| + kDisabledRecentlyClosedHeaderCommandId,
|
| + IDS_NEW_TAB_RECENTLY_CLOSED);
|
| + } else {
|
| + InsertItemWithStringIdAt(curr_model_index,
|
| + kRecentlyClosedHeaderCommandId,
|
| + IDS_NEW_TAB_RECENTLY_CLOSED);
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + SetIcon(curr_model_index,
|
| + rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
|
| + ++curr_model_index;
|
| +
|
| + int added_count = 0;
|
| + TabRestoreService::Entries entries = service->entries();
|
| + for (TabRestoreService::Entries::const_iterator it = entries.begin();
|
| + it != entries.end() && added_count < kMaxLocalEntries; ++it) {
|
| + TabRestoreService::Entry* entry = *it;
|
| + if (entry->type == TabRestoreService::TAB) {
|
| + TabRestoreService::Tab* tab =
|
| + static_cast<TabRestoreService::Tab*>(entry);
|
| + const sessions::SerializedNavigationEntry& current_navigation =
|
| + tab->navigations.at(tab->current_navigation_index);
|
| + BuildLocalTabItem(
|
| + entry->id,
|
| + current_navigation.title(),
|
| + current_navigation.virtual_url(),
|
| + curr_model_index);
|
| + } else {
|
| + DCHECK_EQ(entry->type, TabRestoreService::WINDOW);
|
| + BuildLocalWindowItem(
|
| + entry->id,
|
| + static_cast<TabRestoreService::Window*>(entry)->tabs.size(),
|
| + curr_model_index);
|
| + }
|
| + ++added_count;
|
| + ++curr_model_index;
|
| }
|
| - ++added_count;
|
| }
|
| +
|
| + DCHECK_GT(curr_model_index, 0);
|
| + last_local_model_index_ = curr_model_index - 1;
|
| }
|
|
|
| -void RecentTabsSubMenuModel::BuildDevices() {
|
| +void RecentTabsSubMenuModel::BuildForeignTabs() {
|
| + // All foreign items (device headers or tabs) use AddItem*() to append a menu
|
| + // item, because they are always only built once (i.e. invoked from
|
| + // Constructor()) and don't change after that.
|
| +
|
| browser_sync::SessionModelAssociator* associator = GetModelAssociator();
|
| std::vector<const browser_sync::SyncedSession*> sessions;
|
| if (!associator || !associator->GetAllForeignSessions(&sessions)) {
|
| @@ -451,50 +507,56 @@ void RecentTabsSubMenuModel::BuildDevices() {
|
| AddItemWithStringId(IDC_SHOW_HISTORY, IDS_RECENT_TABS_MORE);
|
| }
|
|
|
| -void RecentTabsSubMenuModel::BuildLocalTabItem(
|
| - int session_id,
|
| - const string16& title,
|
| - const GURL& url) {
|
| +void RecentTabsSubMenuModel::BuildLocalTabItem(int session_id,
|
| + const string16& title,
|
| + const GURL& url,
|
| + int curr_model_index) {
|
| TabNavigationItem item("", session_id, title, url);
|
| - int command_id = TabModelIndexToCommandId(tab_navigation_items_.size());
|
| + int command_id = TabModelIndexToCommandId(
|
| + local_tab_navigation_items_.size(), kFirstLocalTabCommandId);
|
| + // See comments in BuildLocalEntries() about usage of InsertItem*At().
|
| // There may be no tab title, in which case, use the url as tab title.
|
| - AddItem(command_id, title.empty() ? UTF8ToUTF16(item.url.spec()) : title);
|
| - AddTabFavicon(tab_navigation_items_.size(), command_id, item.url);
|
| - tab_navigation_items_.push_back(item);
|
| + InsertItemAt(curr_model_index, command_id,
|
| + title.empty() ? UTF8ToUTF16(item.url.spec()) : title);
|
| + AddTabFavicon(command_id, item.url);
|
| + local_tab_navigation_items_.push_back(item);
|
| }
|
|
|
| -void RecentTabsSubMenuModel::BuildForeignTabItem(
|
| - const std::string& session_tag,
|
| - const SessionTab& tab) {
|
| +void RecentTabsSubMenuModel::BuildLocalWindowItem(
|
| + const SessionID::id_type& window_id,
|
| + int num_tabs,
|
| + int curr_model_index) {
|
| + int command_id = WindowModelIndexToCommandId(local_window_items_.size());
|
| + // See comments in BuildLocalEntries() about usage of InsertItem*At().
|
| + if (num_tabs == 1) {
|
| + InsertItemWithStringIdAt(curr_model_index, command_id,
|
| + IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE);
|
| + } else {
|
| + InsertItemAt(curr_model_index, command_id, l10n_util::GetStringFUTF16(
|
| + IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE,
|
| + base::IntToString16(num_tabs)));
|
| + }
|
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| + SetIcon(curr_model_index, rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
|
| + local_window_items_.push_back(window_id);
|
| +}
|
| +
|
| +void RecentTabsSubMenuModel::BuildForeignTabItem(const std::string& session_tag,
|
| + const SessionTab& tab) {
|
| const sessions::SerializedNavigationEntry& current_navigation =
|
| tab.navigations.at(tab.normalized_navigation_index());
|
| TabNavigationItem item(session_tag, tab.tab_id.id(),
|
| current_navigation.title(),
|
| current_navigation.virtual_url());
|
| - int command_id = TabModelIndexToCommandId(tab_navigation_items_.size());
|
| + int command_id = TabModelIndexToCommandId(
|
| + foreign_tab_navigation_items_.size(), kFirstForeignTabCommandId);
|
| + // See comments in BuildForeignTabs() about usage of AddItem*().
|
| // There may be no tab title, in which case, use the url as tab title.
|
| AddItem(command_id,
|
| current_navigation.title().empty() ?
|
| UTF8ToUTF16(item.url.spec()) : current_navigation.title());
|
| - AddTabFavicon(tab_navigation_items_.size(), command_id, item.url);
|
| - tab_navigation_items_.push_back(item);
|
| -}
|
| -
|
| -void RecentTabsSubMenuModel::BuildWindowItem(
|
| - const SessionID::id_type& window_id,
|
| - int num_tabs) {
|
| - int command_id = WindowModelIndexToCommandId(window_items_.size());
|
| - if (num_tabs == 1) {
|
| - AddItemWithStringId(command_id, IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE);
|
| - } else {
|
| - AddItem(command_id, l10n_util::GetStringFUTF16(
|
| - IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE,
|
| - base::IntToString16(num_tabs)));
|
| - }
|
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance();
|
| - SetIcon(GetItemCount() - 1,
|
| - rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW));
|
| - window_items_.push_back(window_id);
|
| + AddTabFavicon(command_id, item.url);
|
| + foreign_tab_navigation_items_.push_back(item);
|
| }
|
|
|
| void RecentTabsSubMenuModel::AddDeviceFavicon(
|
| @@ -524,9 +586,7 @@ void RecentTabsSubMenuModel::AddDeviceFavicon(
|
| SetIcon(index_in_menu, rb.GetNativeImageNamed(favicon_id));
|
| }
|
|
|
| -void RecentTabsSubMenuModel::AddTabFavicon(int model_index,
|
| - int command_id,
|
| - const GURL& url) {
|
| +void RecentTabsSubMenuModel::AddTabFavicon(int command_id, const GURL& url) {
|
| int index_in_menu = GetIndexOfCommandId(command_id);
|
|
|
| // If tab has synced favicon, use it.
|
| @@ -537,9 +597,8 @@ void RecentTabsSubMenuModel::AddTabFavicon(int model_index,
|
| scoped_refptr<base::RefCountedMemory> favicon_png;
|
| if (associator &&
|
| associator->GetSyncedFaviconForPageURL(url.spec(), &favicon_png)) {
|
| - gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
|
| - favicon_png->front(),
|
| - favicon_png->size());
|
| + gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(favicon_png->front(),
|
| + favicon_png->size());
|
| SetIcon(index_in_menu, image);
|
| return;
|
| }
|
| @@ -561,7 +620,9 @@ void RecentTabsSubMenuModel::AddTabFavicon(int model_index,
|
| base::Bind(&RecentTabsSubMenuModel::OnFaviconDataAvailable,
|
| weak_ptr_factory_.GetWeakPtr(),
|
| command_id),
|
| - &cancelable_task_tracker_);
|
| + command_id >= kFirstForeignTabCommandId ?
|
| + &foreign_tab_cancelable_task_tracker_ :
|
| + &local_tab_cancelable_task_tracker_);
|
| }
|
|
|
| void RecentTabsSubMenuModel::OnFaviconDataAvailable(
|
| @@ -569,14 +630,41 @@ void RecentTabsSubMenuModel::OnFaviconDataAvailable(
|
| const chrome::FaviconImageResult& image_result) {
|
| if (image_result.image.IsEmpty())
|
| return;
|
| - DCHECK(!tab_navigation_items_.empty());
|
| int index_in_menu = GetIndexOfCommandId(command_id);
|
| - DCHECK(index_in_menu != -1);
|
| + DCHECK_GT(index_in_menu, -1);
|
| SetIcon(index_in_menu, image_result.image);
|
| if (GetMenuModelDelegate())
|
| GetMenuModelDelegate()->OnIconChanged(index_in_menu);
|
| }
|
|
|
| +int RecentTabsSubMenuModel::CommandIdToTabModelIndex(
|
| + int command_id, TabNavigationItems** tab_items) {
|
| + if (command_id >= kFirstForeignTabCommandId) {
|
| + *tab_items = &foreign_tab_navigation_items_;
|
| + return command_id - kFirstForeignTabCommandId;
|
| + }
|
| + DCHECK_GE(command_id, kFirstLocalTabCommandId);
|
| + DCHECK_LT(command_id, kFirstLocalWindowCommandId);
|
| + *tab_items = &local_tab_navigation_items_;
|
| + return command_id - kFirstLocalTabCommandId;
|
| +}
|
| +
|
| +void RecentTabsSubMenuModel::ClearLocalEntries() {
|
| + // Remove local items (recent tabs and windows) from model.
|
| + while (last_local_model_index_ >= 0)
|
| + RemoveItemAt(last_local_model_index_--);
|
| +
|
| + // Cancel asynchronous FaviconService::GetFaviconImageForURL() tasks of all
|
| + // local tabs.
|
| + local_tab_cancelable_task_tracker_.TryCancelAll();
|
| +
|
| + // Remove all local tab navigation items.
|
| + local_tab_navigation_items_.clear();
|
| +
|
| + // Remove all local window items.
|
| + local_window_items_.clear();
|
| +}
|
| +
|
| browser_sync::SessionModelAssociator*
|
| RecentTabsSubMenuModel::GetModelAssociator() {
|
| if (!associator_) {
|
| @@ -588,3 +676,33 @@ browser_sync::SessionModelAssociator*
|
| }
|
| return associator_;
|
| }
|
| +
|
| +void RecentTabsSubMenuModel::TabRestoreServiceChanged(
|
| + TabRestoreService* service) {
|
| + ui::MenuModelDelegate* menu_model_delegate = GetMenuModelDelegate();
|
| + if (menu_model_delegate) {
|
| + menu_model_delegate->PrepareForChange();
|
| +
|
| + // Notify delegate to remove all local entries from the menu; do so in
|
| + // decreasing order so that indexes of remaining items don't change.
|
| + for (int i = last_local_model_index_; i >=0; --i)
|
| + menu_model_delegate->OnItemRemoved(i);
|
| + }
|
| +
|
| + ClearLocalEntries();
|
| +
|
| + BuildLocalEntries();
|
| +
|
| + if (menu_model_delegate) {
|
| + // Notify delegate to add the new local entries to the menu.
|
| + for (int i = 0; i <= last_local_model_index_; ++i)
|
| + menu_model_delegate->OnItemAdded(i);
|
| +
|
| + menu_model_delegate->ChangesDone();
|
| + }
|
| +}
|
| +
|
| +void RecentTabsSubMenuModel::TabRestoreServiceDestroyed(
|
| + TabRestoreService* service) {
|
| + TabRestoreServiceChanged(service);
|
| +}
|
|
|