Index: components/sessions/core/tab_restore_service_helper.cc |
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc |
index 73a4c72f6530d3dd4003e016178feb103c6fffc6..cc3f2ae80af6260108bdefebf3fcb4a74d5119bc 100644 |
--- a/components/sessions/core/tab_restore_service_helper.cc |
+++ b/components/sessions/core/tab_restore_service_helper.cc |
@@ -10,6 +10,7 @@ |
#include <iterator> |
#include "base/logging.h" |
+#include "base/memory/ptr_util.h" |
#include "base/metrics/histogram.h" |
#include "base/stl_util.h" |
#include "components/sessions/core/live_tab.h" |
@@ -52,7 +53,6 @@ TabRestoreServiceHelper::TabRestoreServiceHelper( |
TabRestoreServiceHelper::~TabRestoreServiceHelper() { |
FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
TabRestoreServiceDestroyed(tab_restore_service_)); |
- STLDeleteElements(&entries_); |
} |
void TabRestoreServiceHelper::AddObserver( |
@@ -74,48 +74,39 @@ void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, |
if (closing_contexts_.find(context) != closing_contexts_.end()) |
return; |
- std::unique_ptr<Tab> local_tab(new Tab()); |
+ auto local_tab = base::MakeUnique<Tab>(); |
PopulateTab(local_tab.get(), index, context, live_tab); |
if (local_tab->navigations.empty()) |
return; |
- AddEntry(local_tab.release(), true, true); |
+ AddEntry(std::move(local_tab), true, true); |
} |
void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { |
closing_contexts_.insert(context); |
- std::unique_ptr<Window> window(new Window()); |
+ auto window = base::MakeUnique<Window>(); |
window->selected_tab_index = context->GetSelectedIndex(); |
window->timestamp = TimeNow(); |
window->app_name = context->GetAppName(); |
- // Don't use std::vector::resize() because it will push copies of an empty tab |
- // into the vector, which will give all tabs in a window the same ID. |
- for (int i = 0; i < context->GetTabCount(); ++i) { |
- window->tabs.push_back(Tab()); |
- } |
- size_t entry_index = 0; |
for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { |
- PopulateTab(&(window->tabs[entry_index]), tab_index, context, |
+ auto tab = base::MakeUnique<Tab>(); |
+ PopulateTab(tab.get(), tab_index, context, |
context->GetLiveTabAt(tab_index)); |
- if (window->tabs[entry_index].navigations.empty()) { |
- window->tabs.erase(window->tabs.begin() + entry_index); |
- } else { |
- window->tabs[entry_index].browser_id = context->GetSessionID().id(); |
- entry_index++; |
+ if (!tab->navigations.empty()) { |
+ tab->browser_id = context->GetSessionID().id(); |
+ window->tabs.push_back(std::move(tab)); |
} |
} |
if (window->tabs.size() == 1 && window->app_name.empty()) { |
// Short-circuit creating a Window if only 1 tab was present. This fixes |
- // http://crbug.com/56744. Copy the Tab because it's owned by an object on |
- // the stack. |
- AddEntry(new Tab(window->tabs[0]), true, true); |
+ // http://crbug.com/56744. |
+ AddEntry(std::move(window->tabs[0]), true, true); |
} else if (!window->tabs.empty()) { |
- window->selected_tab_index = |
- std::min(static_cast<int>(window->tabs.size() - 1), |
- window->selected_tab_index); |
- AddEntry(window.release(), true, true); |
+ window->selected_tab_index = std::min( |
+ static_cast<int>(window->tabs.size() - 1), window->selected_tab_index); |
+ AddEntry(std::move(window), true, true); |
} |
} |
@@ -126,7 +117,7 @@ void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { |
void TabRestoreServiceHelper::ClearEntries() { |
if (observer_) |
observer_->OnClearEntries(); |
- STLDeleteElements(&entries_); |
+ entries_.clear(); |
NotifyTabsChanged(); |
} |
@@ -141,17 +132,16 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry( |
return RestoreEntryById(context, entries_.front()->id, UNKNOWN); |
} |
-TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById( |
- SessionID::id_type id) { |
- Entries::iterator it = GetEntryIteratorById(id); |
+std::unique_ptr<TabRestoreService::Tab> |
+TabRestoreServiceHelper::RemoveTabEntryById(SessionID::id_type id) { |
+ auto it = GetEntryIteratorById(id); |
if (it == entries_.end()) |
return nullptr; |
- Entry* entry = *it; |
- if (entry->type != TabRestoreService::TAB) |
+ if ((*it)->type != TabRestoreService::TAB) |
return nullptr; |
- Tab* tab = static_cast<Tab*>(entry); |
+ auto tab = std::unique_ptr<Tab>(static_cast<Tab*>(it->release())); |
entries_.erase(it); |
return tab; |
} |
@@ -169,97 +159,99 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( |
if (observer_) |
observer_->OnRestoreEntryById(id, entry_iterator); |
restoring_ = true; |
- Entry* entry = *entry_iterator; |
+ auto& entry = **entry_iterator; |
// If the entry's ID does not match the ID that is being restored, then the |
// entry is a window from which a single tab will be restored. |
- bool restoring_tab_in_window = entry->id != id; |
- |
- if (!restoring_tab_in_window) { |
- entries_.erase(entry_iterator); |
- entry_iterator = entries_.end(); |
- } |
+ bool restoring_tab_in_window = entry.id != id; |
// |context| will be NULL in cases where one isn't already available (eg, |
// when invoked on Mac OS X with no windows open). In this case, create a |
// new browser into which we restore the tabs. |
std::vector<LiveTab*> live_tabs; |
- if (entry->type == TabRestoreService::TAB) { |
- Tab* tab = static_cast<Tab*>(entry); |
- LiveTab* restored_tab = nullptr; |
- context = RestoreTab(*tab, context, disposition, &restored_tab); |
- live_tabs.push_back(restored_tab); |
- context->ShowBrowserWindow(); |
- } else if (entry->type == TabRestoreService::WINDOW) { |
- LiveTabContext* current_context = context; |
- Window* window = static_cast<Window*>(entry); |
- |
- // When restoring a window, either the entire window can be restored, or a |
- // single tab within it. If the entry's ID matches the one to restore, then |
- // the entire window will be restored. |
- if (!restoring_tab_in_window) { |
- context = client_->CreateLiveTabContext(window->app_name); |
- for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) { |
- const Tab& tab = window->tabs[tab_i]; |
- LiveTab* restored_tab = context->AddRestoredTab( |
- tab.navigations, context->GetTabCount(), |
- tab.current_navigation_index, tab.extension_app_id, |
- static_cast<int>(tab_i) == window->selected_tab_index, tab.pinned, |
- tab.from_last_session, tab.platform_data.get(), |
- tab.user_agent_override); |
- if (restored_tab) { |
- restored_tab->LoadIfNecessary(); |
- client_->OnTabRestored( |
- tab.navigations.at(tab.current_navigation_index).virtual_url()); |
- live_tabs.push_back(restored_tab); |
+ switch (entry.type) { |
+ case TabRestoreService::TAB: { |
+ auto& tab = static_cast<const Tab&>(entry); |
+ LiveTab* restored_tab = nullptr; |
+ context = RestoreTab(tab, context, disposition, &restored_tab); |
+ live_tabs.push_back(restored_tab); |
+ context->ShowBrowserWindow(); |
+ break; |
+ } |
+ case TabRestoreService::WINDOW: { |
+ LiveTabContext* current_context = context; |
+ auto& window = static_cast<Window&>(entry); |
+ |
+ // When restoring a window, either the entire window can be restored, or a |
+ // single tab within it. If the entry's ID matches the one to restore, |
+ // then the entire window will be restored. |
+ if (!restoring_tab_in_window) { |
+ context = client_->CreateLiveTabContext(window.app_name); |
+ for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { |
+ const Tab& tab = *window.tabs[tab_i]; |
+ LiveTab* restored_tab = context->AddRestoredTab( |
+ tab.navigations, context->GetTabCount(), |
+ tab.current_navigation_index, tab.extension_app_id, |
+ static_cast<int>(tab_i) == window.selected_tab_index, tab.pinned, |
+ tab.from_last_session, tab.platform_data.get(), |
+ tab.user_agent_override); |
+ if (restored_tab) { |
+ restored_tab->LoadIfNecessary(); |
+ client_->OnTabRestored( |
+ tab.navigations.at(tab.current_navigation_index).virtual_url()); |
+ live_tabs.push_back(restored_tab); |
+ } |
} |
- } |
- // All the window's tabs had the same former browser_id. |
- if (window->tabs[0].has_browser()) { |
- UpdateTabBrowserIDs(window->tabs[0].browser_id, |
- context->GetSessionID().id()); |
- } |
- } else { |
- // Restore a single tab from the window. Find the tab that matches the ID |
- // in the window and restore it. |
- for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); |
- tab_i != window->tabs.end(); ++tab_i) { |
- const Tab& tab = *tab_i; |
- if (tab.id != id) |
- continue; |
- |
- LiveTab* restored_tab = nullptr; |
- context = RestoreTab(tab, context, disposition, &restored_tab); |
- live_tabs.push_back(restored_tab); |
- window->tabs.erase(tab_i); |
- // If restoring the tab leaves the window with nothing else, delete it |
- // as well. |
- if (window->tabs.empty()) { |
- entries_.erase(entry_iterator); |
- delete entry; |
- } else { |
- // Update the browser ID of the rest of the tabs in the window so if |
- // any one is restored, it goes into the same window as the tab |
- // being restored now. |
- UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
- for (Tab& tab_j : window->tabs) |
- tab_j.browser_id = context->GetSessionID().id(); |
+ // All the window's tabs had the same former browser_id. |
+ if (auto browser_id = window.tabs[0]->browser_id) { |
+ UpdateTabBrowserIDs(browser_id, context->GetSessionID().id()); |
+ } |
+ } else { |
+ // Restore a single tab from the window. Find the tab that matches the |
+ // ID |
+ // in the window and restore it. |
+ for (auto tab_i = window.tabs.begin(); tab_i != window.tabs.end(); |
+ ++tab_i) { |
+ SessionID::id_type restored_tab_browser_id; |
+ { |
+ const Tab& tab = **tab_i; |
+ if (tab.id != id) |
+ continue; |
+ |
+ restored_tab_browser_id = tab.browser_id; |
+ LiveTab* restored_tab = nullptr; |
+ context = RestoreTab(tab, context, disposition, &restored_tab); |
+ live_tabs.push_back(restored_tab); |
+ window.tabs.erase(tab_i); |
+ } |
Sidney San Martín
2016/08/04 04:24:57
I had a use-after free here, so I'm using a block
|
+ // If restoring the tab leaves the window with nothing else, delete it |
+ // as well. |
+ if (window.tabs.empty()) { |
+ entries_.erase(entry_iterator); |
+ } else { |
+ // Update the browser ID of the rest of the tabs in the window so if |
+ // any one is restored, it goes into the same window as the tab |
+ // being restored now. |
+ UpdateTabBrowserIDs(restored_tab_browser_id, |
+ context->GetSessionID().id()); |
+ for (auto& tab_j : window.tabs) |
+ tab_j->browser_id = context->GetSessionID().id(); |
+ } |
+ break; |
} |
- break; |
} |
- } |
- context->ShowBrowserWindow(); |
+ context->ShowBrowserWindow(); |
- if (disposition == CURRENT_TAB && current_context && |
- current_context->GetActiveLiveTab()) { |
- current_context->CloseTab(); |
+ if (disposition == CURRENT_TAB && current_context && |
+ current_context->GetActiveLiveTab()) { |
+ current_context->CloseTab(); |
+ } |
+ break; |
} |
- } else { |
- NOTREACHED(); |
} |
if (!restoring_tab_in_window) { |
- delete entry; |
+ entries_.erase(entry_iterator); |
} |
restoring_ = false; |
@@ -277,18 +269,17 @@ void TabRestoreServiceHelper::NotifyLoaded() { |
TabRestoreServiceLoaded(tab_restore_service_)); |
} |
-void TabRestoreServiceHelper::AddEntry(Entry* entry, |
+void TabRestoreServiceHelper::AddEntry(std::unique_ptr<Entry> entry, |
bool notify, |
bool to_front) { |
- if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) { |
- delete entry; |
+ if (!FilterEntry(*entry) || (entries_.size() >= kMaxEntries && !to_front)) { |
return; |
} |
if (to_front) |
- entries_.push_front(entry); |
+ entries_.push_front(std::move(entry)); |
else |
- entries_.push_back(entry); |
+ entries_.push_back(std::move(entry)); |
PruneEntries(); |
@@ -302,19 +293,13 @@ void TabRestoreServiceHelper::AddEntry(Entry* entry, |
void TabRestoreServiceHelper::PruneEntries() { |
Entries new_entries; |
- for (TabRestoreService::Entries::const_iterator iter = entries_.begin(); |
- iter != entries_.end(); ++iter) { |
- TabRestoreService::Entry* entry = *iter; |
- |
- if (FilterEntry(entry) && |
- new_entries.size() < kMaxEntries) { |
- new_entries.push_back(entry); |
- } else { |
- delete entry; |
+ for (auto& entry : entries_) { |
+ if (FilterEntry(*entry) && new_entries.size() < kMaxEntries) { |
+ new_entries.push_back(std::move(entry)); |
} |
} |
- entries_ = new_entries; |
+ entries_ = std::move(new_entries); |
} |
TabRestoreService::Entries::iterator |
@@ -326,10 +311,9 @@ TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { |
// For Window entries, see if the ID matches a tab. If so, report the window |
// as the Entry. |
if ((*i)->type == TabRestoreService::WINDOW) { |
- std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs; |
- for (std::vector<Tab>::iterator j = tabs.begin(); |
- j != tabs.end(); ++j) { |
- if ((*j).id == id) { |
+ auto& window = static_cast<const Window&>(**i); |
+ for (const auto& tab : window.tabs) { |
+ if (tab->id == id) { |
return i; |
} |
} |
@@ -339,13 +323,13 @@ TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { |
} |
// static |
-bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) { |
- if (entry->type == TabRestoreService::TAB) |
- return ValidateTab(static_cast<Tab*>(entry)); |
- |
- if (entry->type == TabRestoreService::WINDOW) |
- return ValidateWindow(static_cast<Window*>(entry)); |
- |
+bool TabRestoreServiceHelper::ValidateEntry(const Entry& entry) { |
+ switch (entry.type) { |
+ case TabRestoreService::TAB: |
+ return ValidateTab(static_cast<const Tab&>(entry)); |
+ case TabRestoreService::WINDOW: |
+ return ValidateWindow(static_cast<const Window&>(entry)); |
+ } |
NOTREACHED(); |
return false; |
} |
@@ -368,8 +352,6 @@ void TabRestoreServiceHelper::PopulateTab(Tab* tab, |
} |
tab->timestamp = TimeNow(); |
tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); |
- if (tab->current_navigation_index == -1 && entry_count > 0) |
- tab->current_navigation_index = 0; |
tab->tabstrip_index = index; |
tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); |
@@ -397,7 +379,7 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); |
} else { |
// We only respsect the tab's original browser if there's no disposition. |
- if (disposition == UNKNOWN && tab.has_browser()) { |
+ if (disposition == UNKNOWN && tab.browser_id) { |
context = client_->FindLiveTabContextWithID(tab.browser_id); |
} |
@@ -410,7 +392,7 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
tab_index = tab.tabstrip_index; |
} else { |
context = client_->CreateLiveTabContext(std::string()); |
- if (tab.has_browser()) |
+ if (tab.browser_id) |
UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
} |
@@ -436,86 +418,68 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
return context; |
} |
+bool TabRestoreServiceHelper::ValidateTab(const Tab& tab) { |
+ return !tab.navigations.empty() && |
+ static_cast<size_t>(tab.current_navigation_index) < |
+ tab.navigations.size(); |
+} |
-bool TabRestoreServiceHelper::ValidateTab(Tab* tab) { |
- if (tab->navigations.empty()) |
+bool TabRestoreServiceHelper::ValidateWindow(const Window& window) { |
+ if (static_cast<size_t>(window.selected_tab_index) >= window.tabs.size()) { |
return false; |
+ } |
- tab->current_navigation_index = |
- std::max(0, std::min(tab->current_navigation_index, |
- static_cast<int>(tab->navigations.size()) - 1)); |
- |
- return true; |
-} |
- |
-bool TabRestoreServiceHelper::ValidateWindow(Window* window) { |
- window->selected_tab_index = |
- std::max(0, std::min(window->selected_tab_index, |
- static_cast<int>(window->tabs.size() - 1))); |
- |
- int i = 0; |
- for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); |
- tab_i != window->tabs.end();) { |
- if (!ValidateTab(&(*tab_i))) { |
- tab_i = window->tabs.erase(tab_i); |
- if (i < window->selected_tab_index) |
- window->selected_tab_index--; |
- else if (i == window->selected_tab_index) |
- window->selected_tab_index = 0; |
- } else { |
- ++tab_i; |
- ++i; |
+ for (const auto& tab : window.tabs) { |
+ if (!ValidateTab(*tab)) { |
+ return false; |
} |
} |
- if (window->tabs.empty()) |
- return false; |
- |
return true; |
} |
-bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) { |
- if (tab->navigations.empty()) |
+bool TabRestoreServiceHelper::IsTabInteresting(const Tab& tab) { |
+ if (tab.navigations.empty()) |
return false; |
- if (tab->navigations.size() > 1) |
+ if (tab.navigations.size() > 1) |
return true; |
- return tab->pinned || |
- tab->navigations.at(0).virtual_url() != client_->GetNewTabURL(); |
+ return tab.pinned || |
+ tab.navigations.at(0).virtual_url() != client_->GetNewTabURL(); |
} |
-bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) { |
- if (window->tabs.empty()) |
+bool TabRestoreServiceHelper::IsWindowInteresting(const Window& window) { |
+ if (window.tabs.empty()) |
return false; |
- if (window->tabs.size() > 1) |
+ if (window.tabs.size() > 1) |
return true; |
- return IsTabInteresting(&window->tabs[0]); |
+ return IsTabInteresting(*window.tabs[0]); |
} |
-bool TabRestoreServiceHelper::FilterEntry(Entry* entry) { |
+bool TabRestoreServiceHelper::FilterEntry(const Entry& entry) { |
if (!ValidateEntry(entry)) |
return false; |
- if (entry->type == TabRestoreService::TAB) |
- return IsTabInteresting(static_cast<Tab*>(entry)); |
- else if (entry->type == TabRestoreService::WINDOW) |
- return IsWindowInteresting(static_cast<Window*>(entry)); |
- |
+ switch (entry.type) { |
+ case TabRestoreService::TAB: |
+ return IsTabInteresting(static_cast<const Tab&>(entry)); |
+ case TabRestoreService::WINDOW: |
+ return IsWindowInteresting(static_cast<const Window&>(entry)); |
+ } |
NOTREACHED(); |
return false; |
} |
void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, |
SessionID::id_type new_id) { |
- for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { |
- Entry* entry = *i; |
+ for (const auto& entry : entries_) { |
if (entry->type == TabRestoreService::TAB) { |
- Tab* tab = static_cast<Tab*>(entry); |
- if (tab->browser_id == old_id) |
- tab->browser_id = new_id; |
+ auto& tab = static_cast<Tab&>(*entry); |
+ if (tab.browser_id == old_id) |
+ tab.browser_id = new_id; |
} |
} |
} |