| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sessions/core/tab_restore_service_helper.h" | 5 #include "components/sessions/core/tab_restore_service_helper.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <iterator> | 10 #include <iterator> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" |
| 13 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 15 #include "components/sessions/core/live_tab.h" | 16 #include "components/sessions/core/live_tab.h" |
| 16 #include "components/sessions/core/live_tab_context.h" | 17 #include "components/sessions/core/live_tab_context.h" |
| 17 #include "components/sessions/core/serialized_navigation_entry.h" | 18 #include "components/sessions/core/serialized_navigation_entry.h" |
| 18 #include "components/sessions/core/session_types.h" | 19 #include "components/sessions/core/session_types.h" |
| 19 #include "components/sessions/core/tab_restore_service_client.h" | 20 #include "components/sessions/core/tab_restore_service_client.h" |
| 20 #include "components/sessions/core/tab_restore_service_observer.h" | 21 #include "components/sessions/core/tab_restore_service_observer.h" |
| 21 | 22 |
| 22 namespace sessions { | 23 namespace sessions { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 45 observer_(observer), | 46 observer_(observer), |
| 46 client_(client), | 47 client_(client), |
| 47 restoring_(false), | 48 restoring_(false), |
| 48 time_factory_(time_factory) { | 49 time_factory_(time_factory) { |
| 49 DCHECK(tab_restore_service_); | 50 DCHECK(tab_restore_service_); |
| 50 } | 51 } |
| 51 | 52 |
| 52 TabRestoreServiceHelper::~TabRestoreServiceHelper() { | 53 TabRestoreServiceHelper::~TabRestoreServiceHelper() { |
| 53 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 54 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
| 54 TabRestoreServiceDestroyed(tab_restore_service_)); | 55 TabRestoreServiceDestroyed(tab_restore_service_)); |
| 55 STLDeleteElements(&entries_); | |
| 56 } | 56 } |
| 57 | 57 |
| 58 void TabRestoreServiceHelper::AddObserver( | 58 void TabRestoreServiceHelper::AddObserver( |
| 59 TabRestoreServiceObserver* observer) { | 59 TabRestoreServiceObserver* observer) { |
| 60 observer_list_.AddObserver(observer); | 60 observer_list_.AddObserver(observer); |
| 61 } | 61 } |
| 62 | 62 |
| 63 void TabRestoreServiceHelper::RemoveObserver( | 63 void TabRestoreServiceHelper::RemoveObserver( |
| 64 TabRestoreServiceObserver* observer) { | 64 TabRestoreServiceObserver* observer) { |
| 65 observer_list_.RemoveObserver(observer); | 65 observer_list_.RemoveObserver(observer); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, | 68 void TabRestoreServiceHelper::CreateHistoricalTab(LiveTab* live_tab, |
| 69 int index) { | 69 size_t index) { |
| 70 if (restoring_) | 70 if (restoring_) |
| 71 return; | 71 return; |
| 72 | 72 |
| 73 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); | 73 LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab); |
| 74 if (closing_contexts_.find(context) != closing_contexts_.end()) | 74 if (closing_contexts_.find(context) != closing_contexts_.end()) |
| 75 return; | 75 return; |
| 76 | 76 |
| 77 std::unique_ptr<Tab> local_tab(new Tab()); | 77 auto local_tab = base::MakeUnique<Tab>(); |
| 78 PopulateTab(local_tab.get(), index, context, live_tab); | 78 PopulateTab(local_tab.get(), index, context, live_tab); |
| 79 if (local_tab->navigations.empty()) | 79 if (local_tab->navigations.empty()) |
| 80 return; | 80 return; |
| 81 | 81 |
| 82 AddEntry(local_tab.release(), true, true); | 82 AddEntry(std::move(local_tab), true, true); |
| 83 } | 83 } |
| 84 | 84 |
| 85 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { | 85 void TabRestoreServiceHelper::BrowserClosing(LiveTabContext* context) { |
| 86 closing_contexts_.insert(context); | 86 closing_contexts_.insert(context); |
| 87 | 87 |
| 88 std::unique_ptr<Window> window(new Window()); | 88 auto window = base::MakeUnique<Window>(); |
| 89 window->selected_tab_index = context->GetSelectedIndex(); | 89 window->selected_tab_index = context->GetSelectedIndex(); |
| 90 window->timestamp = TimeNow(); | 90 window->timestamp = TimeNow(); |
| 91 window->app_name = context->GetAppName(); | 91 window->app_name = context->GetAppName(); |
| 92 | 92 |
| 93 // Don't use std::vector::resize() because it will push copies of an empty tab | |
| 94 // into the vector, which will give all tabs in a window the same ID. | |
| 95 for (int i = 0; i < context->GetTabCount(); ++i) { | |
| 96 window->tabs.push_back(Tab()); | |
| 97 } | |
| 98 size_t entry_index = 0; | |
| 99 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { | 93 for (int tab_index = 0; tab_index < context->GetTabCount(); ++tab_index) { |
| 100 PopulateTab(&(window->tabs[entry_index]), tab_index, context, | 94 auto tab = base::MakeUnique<Tab>(); |
| 95 PopulateTab(tab.get(), tab_index, context, |
| 101 context->GetLiveTabAt(tab_index)); | 96 context->GetLiveTabAt(tab_index)); |
| 102 if (window->tabs[entry_index].navigations.empty()) { | 97 if (!tab->navigations.empty()) { |
| 103 window->tabs.erase(window->tabs.begin() + entry_index); | 98 tab->browser_id = context->GetSessionID().id(); |
| 104 } else { | 99 window->tabs.push_back(std::move(tab)); |
| 105 window->tabs[entry_index].browser_id = context->GetSessionID().id(); | |
| 106 entry_index++; | |
| 107 } | 100 } |
| 108 } | 101 } |
| 109 if (window->tabs.size() == 1 && window->app_name.empty()) { | 102 if (window->tabs.size() == 1 && window->app_name.empty()) { |
| 110 // Short-circuit creating a Window if only 1 tab was present. This fixes | 103 // Short-circuit creating a Window if only 1 tab was present. This fixes |
| 111 // http://crbug.com/56744. Copy the Tab because it's owned by an object on | 104 // http://crbug.com/56744. |
| 112 // the stack. | 105 AddEntry(std::move(window->tabs[0]), true, true); |
| 113 AddEntry(new Tab(window->tabs[0]), true, true); | |
| 114 } else if (!window->tabs.empty()) { | 106 } else if (!window->tabs.empty()) { |
| 115 window->selected_tab_index = | 107 window->selected_tab_index = |
| 116 std::min(static_cast<int>(window->tabs.size() - 1), | 108 std::min(window->tabs.size() - 1, window->selected_tab_index); |
| 117 window->selected_tab_index); | 109 AddEntry(std::move(window), true, true); |
| 118 AddEntry(window.release(), true, true); | |
| 119 } | 110 } |
| 120 } | 111 } |
| 121 | 112 |
| 122 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { | 113 void TabRestoreServiceHelper::BrowserClosed(LiveTabContext* context) { |
| 123 closing_contexts_.erase(context); | 114 closing_contexts_.erase(context); |
| 124 } | 115 } |
| 125 | 116 |
| 126 void TabRestoreServiceHelper::ClearEntries() { | 117 void TabRestoreServiceHelper::ClearEntries() { |
| 127 if (observer_) | 118 if (observer_) |
| 128 observer_->OnClearEntries(); | 119 observer_->OnClearEntries(); |
| 129 STLDeleteElements(&entries_); | 120 entries_.clear(); |
| 130 NotifyTabsChanged(); | 121 NotifyTabsChanged(); |
| 131 } | 122 } |
| 132 | 123 |
| 133 const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const { | 124 const TabRestoreService::Entries& TabRestoreServiceHelper::entries() const { |
| 134 return entries_; | 125 return entries_; |
| 135 } | 126 } |
| 136 | 127 |
| 137 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry( | 128 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreMostRecentEntry( |
| 138 LiveTabContext* context) { | 129 LiveTabContext* context) { |
| 139 if (entries_.empty()) | 130 if (entries_.empty()) |
| 140 return std::vector<LiveTab*>(); | 131 return std::vector<LiveTab*>(); |
| 141 return RestoreEntryById(context, entries_.front()->id, UNKNOWN); | 132 return RestoreEntryById(context, entries_.front()->id, UNKNOWN); |
| 142 } | 133 } |
| 143 | 134 |
| 144 TabRestoreService::Tab* TabRestoreServiceHelper::RemoveTabEntryById( | 135 std::unique_ptr<TabRestoreService::Tab> |
| 145 SessionID::id_type id) { | 136 TabRestoreServiceHelper::RemoveTabEntryById(SessionID::id_type id) { |
| 146 Entries::iterator it = GetEntryIteratorById(id); | 137 auto it = GetEntryIteratorById(id); |
| 147 if (it == entries_.end()) | 138 if (it == entries_.end()) |
| 148 return nullptr; | 139 return nullptr; |
| 149 | 140 |
| 150 Entry* entry = *it; | 141 if ((*it)->type() != TabRestoreService::TAB) |
| 151 if (entry->type != TabRestoreService::TAB) | |
| 152 return nullptr; | 142 return nullptr; |
| 153 | 143 |
| 154 Tab* tab = static_cast<Tab*>(entry); | 144 auto tab = std::unique_ptr<Tab>(static_cast<Tab*>(it->release())); |
| 155 entries_.erase(it); | 145 entries_.erase(it); |
| 156 return tab; | 146 return tab; |
| 157 } | 147 } |
| 158 | 148 |
| 159 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( | 149 std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById( |
| 160 LiveTabContext* context, | 150 LiveTabContext* context, |
| 161 SessionID::id_type id, | 151 SessionID::id_type id, |
| 162 WindowOpenDisposition disposition) { | 152 WindowOpenDisposition disposition) { |
| 163 Entries::iterator entry_iterator = GetEntryIteratorById(id); | 153 Entries::iterator entry_iterator = GetEntryIteratorById(id); |
| 164 if (entry_iterator == entries_.end()) { | 154 if (entry_iterator == entries_.end()) { |
| 165 // Don't hoark here, we allow an invalid id. | 155 // Don't hoark here, we allow an invalid id. |
| 166 return std::vector<LiveTab*>(); | 156 return std::vector<LiveTab*>(); |
| 167 } | 157 } |
| 168 | 158 |
| 169 if (observer_) | 159 if (observer_) |
| 170 observer_->OnRestoreEntryById(id, entry_iterator); | 160 observer_->OnRestoreEntryById(id, entry_iterator); |
| 171 restoring_ = true; | 161 restoring_ = true; |
| 172 Entry* entry = *entry_iterator; | 162 auto &entry = **entry_iterator; |
| 173 | 163 |
| 174 // If the entry's ID does not match the ID that is being restored, then the | 164 // If the entry's ID does not match the ID that is being restored, then the |
| 175 // entry is a window from which a single tab will be restored. | 165 // entry is a window from which a single tab will be restored. |
| 176 bool restoring_tab_in_window = entry->id != id; | 166 bool restoring_tab_in_window = entry.id != id; |
| 177 | |
| 178 if (!restoring_tab_in_window) { | |
| 179 entries_.erase(entry_iterator); | |
| 180 entry_iterator = entries_.end(); | |
| 181 } | |
| 182 | 167 |
| 183 // |context| will be NULL in cases where one isn't already available (eg, | 168 // |context| will be NULL in cases where one isn't already available (eg, |
| 184 // when invoked on Mac OS X with no windows open). In this case, create a | 169 // when invoked on Mac OS X with no windows open). In this case, create a |
| 185 // new browser into which we restore the tabs. | 170 // new browser into which we restore the tabs. |
| 186 std::vector<LiveTab*> live_tabs; | 171 std::vector<LiveTab*> live_tabs; |
| 187 if (entry->type == TabRestoreService::TAB) { | 172 switch (entry.type()) { |
| 188 Tab* tab = static_cast<Tab*>(entry); | 173 case TabRestoreService::TAB: { |
| 189 LiveTab* restored_tab = nullptr; | 174 auto& tab = static_cast<const Tab&>(entry); |
| 190 context = RestoreTab(*tab, context, disposition, &restored_tab); | 175 LiveTab* restored_tab = nullptr; |
| 191 live_tabs.push_back(restored_tab); | 176 context = RestoreTab(tab, context, disposition, &restored_tab); |
| 192 context->ShowBrowserWindow(); | 177 live_tabs.push_back(restored_tab); |
| 193 } else if (entry->type == TabRestoreService::WINDOW) { | 178 context->ShowBrowserWindow(); |
| 194 LiveTabContext* current_context = context; | 179 break; |
| 195 Window* window = static_cast<Window*>(entry); | 180 } |
| 181 case TabRestoreService::WINDOW: { |
| 182 LiveTabContext* current_context = context; |
| 183 auto& window = static_cast<Window&>(entry); |
| 196 | 184 |
| 197 // When restoring a window, either the entire window can be restored, or a | 185 // When restoring a window, either the entire window can be restored, or a |
| 198 // single tab within it. If the entry's ID matches the one to restore, then | 186 // single tab within it. If the entry's ID matches the one to restore, |
| 199 // the entire window will be restored. | 187 // then the entire window will be restored. |
| 200 if (!restoring_tab_in_window) { | 188 if (!restoring_tab_in_window) { |
| 201 context = client_->CreateLiveTabContext(window->app_name); | 189 context = client_->CreateLiveTabContext(window.app_name); |
| 202 for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) { | 190 for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { |
| 203 const Tab& tab = window->tabs[tab_i]; | 191 const Tab& tab = *window.tabs[tab_i]; |
| 204 LiveTab* restored_tab = context->AddRestoredTab( | 192 LiveTab* restored_tab = context->AddRestoredTab( |
| 205 tab.navigations, context->GetTabCount(), | 193 tab.navigations, context->GetTabCount(), |
| 206 tab.current_navigation_index, tab.extension_app_id, | 194 tab.current_navigation_index, tab.extension_app_id, |
| 207 static_cast<int>(tab_i) == window->selected_tab_index, tab.pinned, | 195 tab_i == window.selected_tab_index, tab.pinned, |
| 208 tab.from_last_session, tab.platform_data.get(), | 196 tab.from_last_session, tab.platform_data.get(), |
| 209 tab.user_agent_override); | 197 tab.user_agent_override); |
| 210 if (restored_tab) { | 198 if (restored_tab) { |
| 211 restored_tab->LoadIfNecessary(); | 199 restored_tab->LoadIfNecessary(); |
| 212 client_->OnTabRestored( | 200 client_->OnTabRestored( |
| 213 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 201 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
| 202 live_tabs.push_back(restored_tab); |
| 203 } |
| 204 } |
| 205 // All the window's tabs had the same former browser_id. |
| 206 if (auto browser_id = window.tabs[0]->browser_id) { |
| 207 UpdateTabBrowserIDs(browser_id, context->GetSessionID().id()); |
| 208 } |
| 209 } else { |
| 210 // Restore a single tab from the window. Find the tab that matches the |
| 211 // ID |
| 212 // in the window and restore it. |
| 213 for (auto tab_i = window.tabs.begin(); tab_i != window.tabs.end(); |
| 214 ++tab_i) { |
| 215 const Tab& tab = **tab_i; |
| 216 if (tab.id != id) |
| 217 continue; |
| 218 |
| 219 LiveTab* restored_tab = nullptr; |
| 220 context = RestoreTab(tab, context, disposition, &restored_tab); |
| 214 live_tabs.push_back(restored_tab); | 221 live_tabs.push_back(restored_tab); |
| 222 window.tabs.erase(tab_i); |
| 223 // If restoring the tab leaves the window with nothing else, delete it |
| 224 // as well. |
| 225 if (window.tabs.empty()) { |
| 226 entries_.erase(entry_iterator); |
| 227 } else { |
| 228 // Update the browser ID of the rest of the tabs in the window so if |
| 229 // any one is restored, it goes into the same window as the tab |
| 230 // being restored now. |
| 231 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
| 232 for (auto& tab_j : window.tabs) |
| 233 tab_j->browser_id = context->GetSessionID().id(); |
| 234 } |
| 235 break; |
| 215 } | 236 } |
| 216 } | 237 } |
| 217 // All the window's tabs had the same former browser_id. | 238 context->ShowBrowserWindow(); |
| 218 if (window->tabs[0].has_browser()) { | 239 |
| 219 UpdateTabBrowserIDs(window->tabs[0].browser_id, | 240 if (disposition == CURRENT_TAB && current_context && |
| 220 context->GetSessionID().id()); | 241 current_context->GetActiveLiveTab()) { |
| 242 current_context->CloseTab(); |
| 221 } | 243 } |
| 222 } else { | 244 break; |
| 223 // Restore a single tab from the window. Find the tab that matches the ID | |
| 224 // in the window and restore it. | |
| 225 for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); | |
| 226 tab_i != window->tabs.end(); ++tab_i) { | |
| 227 const Tab& tab = *tab_i; | |
| 228 if (tab.id != id) | |
| 229 continue; | |
| 230 | |
| 231 LiveTab* restored_tab = nullptr; | |
| 232 context = RestoreTab(tab, context, disposition, &restored_tab); | |
| 233 live_tabs.push_back(restored_tab); | |
| 234 window->tabs.erase(tab_i); | |
| 235 // If restoring the tab leaves the window with nothing else, delete it | |
| 236 // as well. | |
| 237 if (window->tabs.empty()) { | |
| 238 entries_.erase(entry_iterator); | |
| 239 delete entry; | |
| 240 } else { | |
| 241 // Update the browser ID of the rest of the tabs in the window so if | |
| 242 // any one is restored, it goes into the same window as the tab | |
| 243 // being restored now. | |
| 244 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | |
| 245 for (Tab& tab_j : window->tabs) | |
| 246 tab_j.browser_id = context->GetSessionID().id(); | |
| 247 } | |
| 248 break; | |
| 249 } | |
| 250 } | 245 } |
| 251 context->ShowBrowserWindow(); | |
| 252 | |
| 253 if (disposition == CURRENT_TAB && current_context && | |
| 254 current_context->GetActiveLiveTab()) { | |
| 255 current_context->CloseTab(); | |
| 256 } | |
| 257 } else { | |
| 258 NOTREACHED(); | |
| 259 } | 246 } |
| 260 | 247 |
| 261 if (!restoring_tab_in_window) { | 248 if (!restoring_tab_in_window) { |
| 262 delete entry; | 249 entries_.erase(entry_iterator); |
| 263 } | 250 } |
| 264 | 251 |
| 265 restoring_ = false; | 252 restoring_ = false; |
| 266 NotifyTabsChanged(); | 253 NotifyTabsChanged(); |
| 267 return live_tabs; | 254 return live_tabs; |
| 268 } | 255 } |
| 269 | 256 |
| 270 void TabRestoreServiceHelper::NotifyTabsChanged() { | 257 void TabRestoreServiceHelper::NotifyTabsChanged() { |
| 271 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 258 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
| 272 TabRestoreServiceChanged(tab_restore_service_)); | 259 TabRestoreServiceChanged(tab_restore_service_)); |
| 273 } | 260 } |
| 274 | 261 |
| 275 void TabRestoreServiceHelper::NotifyLoaded() { | 262 void TabRestoreServiceHelper::NotifyLoaded() { |
| 276 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 263 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
| 277 TabRestoreServiceLoaded(tab_restore_service_)); | 264 TabRestoreServiceLoaded(tab_restore_service_)); |
| 278 } | 265 } |
| 279 | 266 |
| 280 void TabRestoreServiceHelper::AddEntry(Entry* entry, | 267 void TabRestoreServiceHelper::AddEntry(std::unique_ptr<Entry> entry, |
| 281 bool notify, | 268 bool notify, |
| 282 bool to_front) { | 269 bool to_front) { |
| 283 if (!FilterEntry(entry) || (entries_.size() >= kMaxEntries && !to_front)) { | 270 if (!FilterEntry(*entry) || (entries_.size() >= kMaxEntries && !to_front)) { |
| 284 delete entry; | |
| 285 return; | 271 return; |
| 286 } | 272 } |
| 287 | 273 |
| 288 if (to_front) | 274 if (to_front) |
| 289 entries_.push_front(entry); | 275 entries_.push_front(std::move(entry)); |
| 290 else | 276 else |
| 291 entries_.push_back(entry); | 277 entries_.push_back(std::move(entry)); |
| 292 | 278 |
| 293 PruneEntries(); | 279 PruneEntries(); |
| 294 | 280 |
| 295 if (notify) | 281 if (notify) |
| 296 NotifyTabsChanged(); | 282 NotifyTabsChanged(); |
| 297 | 283 |
| 298 if (observer_) | 284 if (observer_) |
| 299 observer_->OnAddEntry(); | 285 observer_->OnAddEntry(); |
| 300 } | 286 } |
| 301 | 287 |
| 302 void TabRestoreServiceHelper::PruneEntries() { | 288 void TabRestoreServiceHelper::PruneEntries() { |
| 303 Entries new_entries; | 289 Entries new_entries; |
| 304 | 290 |
| 305 for (TabRestoreService::Entries::const_iterator iter = entries_.begin(); | 291 for (auto &entry : entries_) { |
| 306 iter != entries_.end(); ++iter) { | 292 if (FilterEntry(*entry) && new_entries.size() < kMaxEntries) { |
| 307 TabRestoreService::Entry* entry = *iter; | 293 new_entries.push_back(std::move(entry)); |
| 308 | |
| 309 if (FilterEntry(entry) && | |
| 310 new_entries.size() < kMaxEntries) { | |
| 311 new_entries.push_back(entry); | |
| 312 } else { | |
| 313 delete entry; | |
| 314 } | 294 } |
| 315 } | 295 } |
| 316 | 296 |
| 317 entries_ = new_entries; | 297 entries_ = std::move(new_entries); |
| 318 } | 298 } |
| 319 | 299 |
| 320 TabRestoreService::Entries::iterator | 300 TabRestoreService::Entries::iterator |
| 321 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { | 301 TabRestoreServiceHelper::GetEntryIteratorById(SessionID::id_type id) { |
| 322 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 302 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { |
| 323 if ((*i)->id == id) | 303 if ((*i)->id == id) |
| 324 return i; | 304 return i; |
| 325 | 305 |
| 326 // For Window entries, see if the ID matches a tab. If so, report the window | 306 // For Window entries, see if the ID matches a tab. If so, report the window |
| 327 // as the Entry. | 307 // as the Entry. |
| 328 if ((*i)->type == TabRestoreService::WINDOW) { | 308 if ((*i)->type() == TabRestoreService::WINDOW) { |
| 329 std::vector<Tab>& tabs = static_cast<Window*>(*i)->tabs; | 309 auto &window = static_cast<const Window&>(**i); |
| 330 for (std::vector<Tab>::iterator j = tabs.begin(); | 310 for (const auto &tab : window.tabs) { |
| 331 j != tabs.end(); ++j) { | 311 if (tab->id == id) { |
| 332 if ((*j).id == id) { | |
| 333 return i; | 312 return i; |
| 334 } | 313 } |
| 335 } | 314 } |
| 336 } | 315 } |
| 337 } | 316 } |
| 338 return entries_.end(); | 317 return entries_.end(); |
| 339 } | 318 } |
| 340 | 319 |
| 341 // static | 320 // static |
| 342 bool TabRestoreServiceHelper::ValidateEntry(Entry* entry) { | 321 bool TabRestoreServiceHelper::ValidateEntry(const Entry& entry) { |
| 343 if (entry->type == TabRestoreService::TAB) | 322 switch (entry.type()) { |
| 344 return ValidateTab(static_cast<Tab*>(entry)); | 323 case TabRestoreService::TAB: |
| 345 | 324 return ValidateTab(static_cast<const Tab&>(entry)); |
| 346 if (entry->type == TabRestoreService::WINDOW) | 325 case TabRestoreService::WINDOW: |
| 347 return ValidateWindow(static_cast<Window*>(entry)); | 326 return ValidateWindow(static_cast<const Window&>(entry)); |
| 348 | 327 } |
| 349 NOTREACHED(); | 328 NOTREACHED(); |
| 350 return false; | 329 return false; |
| 351 } | 330 } |
| 352 | 331 |
| 353 void TabRestoreServiceHelper::PopulateTab(Tab* tab, | 332 void TabRestoreServiceHelper::PopulateTab(Tab* tab, |
| 354 int index, | 333 size_t index, |
| 355 LiveTabContext* context, | 334 LiveTabContext* context, |
| 356 LiveTab* live_tab) { | 335 LiveTab* live_tab) { |
| 357 const int pending_index = live_tab->GetPendingEntryIndex(); | 336 const int pending_index = live_tab->GetPendingEntryIndex(); |
| 358 int entry_count = | 337 int entry_count = |
| 359 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); | 338 live_tab->IsInitialBlankNavigation() ? 0 : live_tab->GetEntryCount(); |
| 360 if (entry_count == 0 && pending_index == 0) | 339 if (entry_count == 0 && pending_index == 0) |
| 361 entry_count++; | 340 entry_count++; |
| 362 tab->navigations.resize(static_cast<int>(entry_count)); | 341 tab->navigations.resize(static_cast<int>(entry_count)); |
| 363 for (int i = 0; i < entry_count; ++i) { | 342 for (int i = 0; i < entry_count; ++i) { |
| 364 SerializedNavigationEntry entry = (i == pending_index) | 343 SerializedNavigationEntry entry = (i == pending_index) |
| 365 ? live_tab->GetPendingEntry() | 344 ? live_tab->GetPendingEntry() |
| 366 : live_tab->GetEntryAtIndex(i); | 345 : live_tab->GetEntryAtIndex(i); |
| 367 tab->navigations[i] = entry; | 346 tab->navigations[i] = entry; |
| 368 } | 347 } |
| 369 tab->timestamp = TimeNow(); | 348 tab->timestamp = TimeNow(); |
| 370 tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); | 349 tab->current_navigation_index = live_tab->GetCurrentEntryIndex(); |
| 371 if (tab->current_navigation_index == -1 && entry_count > 0) | |
| 372 tab->current_navigation_index = 0; | |
| 373 tab->tabstrip_index = index; | 350 tab->tabstrip_index = index; |
| 374 | 351 |
| 375 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); | 352 tab->extension_app_id = client_->GetExtensionAppIDForTab(live_tab); |
| 376 | 353 |
| 377 tab->user_agent_override = live_tab->GetUserAgentOverride(); | 354 tab->user_agent_override = live_tab->GetUserAgentOverride(); |
| 378 | 355 |
| 379 tab->platform_data = live_tab->GetPlatformSpecificTabData(); | 356 tab->platform_data = live_tab->GetPlatformSpecificTabData(); |
| 380 | 357 |
| 381 // Delegate may be NULL during unit tests. | 358 // Delegate may be NULL during unit tests. |
| 382 if (context) { | 359 if (context) { |
| 383 tab->browser_id = context->GetSessionID().id(); | 360 tab->browser_id = context->GetSessionID().id(); |
| 384 tab->pinned = context->IsTabPinned(tab->tabstrip_index); | 361 tab->pinned = context->IsTabPinned(tab->tabstrip_index); |
| 385 } | 362 } |
| 386 } | 363 } |
| 387 | 364 |
| 388 LiveTabContext* TabRestoreServiceHelper::RestoreTab( | 365 LiveTabContext* TabRestoreServiceHelper::RestoreTab( |
| 389 const Tab& tab, | 366 const Tab& tab, |
| 390 LiveTabContext* context, | 367 LiveTabContext* context, |
| 391 WindowOpenDisposition disposition, | 368 WindowOpenDisposition disposition, |
| 392 LiveTab** live_tab) { | 369 LiveTab** live_tab) { |
| 393 LiveTab* restored_tab; | 370 LiveTab* restored_tab; |
| 394 if (disposition == CURRENT_TAB && context) { | 371 if (disposition == CURRENT_TAB && context) { |
| 395 restored_tab = context->ReplaceRestoredTab( | 372 restored_tab = context->ReplaceRestoredTab( |
| 396 tab.navigations, tab.current_navigation_index, tab.from_last_session, | 373 tab.navigations, tab.current_navigation_index, tab.from_last_session, |
| 397 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); | 374 tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override); |
| 398 } else { | 375 } else { |
| 399 // We only respsect the tab's original browser if there's no disposition. | 376 // We only respsect the tab's original browser if there's no disposition. |
| 400 if (disposition == UNKNOWN && tab.has_browser()) { | 377 if (disposition == UNKNOWN && tab.browser_id) { |
| 401 context = client_->FindLiveTabContextWithID(tab.browser_id); | 378 context = client_->FindLiveTabContextWithID(tab.browser_id); |
| 402 } | 379 } |
| 403 | 380 |
| 404 int tab_index = -1; | 381 int tab_index = -1; |
| 405 | 382 |
| 406 // |context| will be NULL in cases where one isn't already available (eg, | 383 // |context| will be NULL in cases where one isn't already available (eg, |
| 407 // when invoked on Mac OS X with no windows open). In this case, create a | 384 // when invoked on Mac OS X with no windows open). In this case, create a |
| 408 // new browser into which we restore the tabs. | 385 // new browser into which we restore the tabs. |
| 409 if (context && disposition != NEW_WINDOW) { | 386 if (context && disposition != NEW_WINDOW) { |
| 410 tab_index = tab.tabstrip_index; | 387 tab_index = tab.tabstrip_index; |
| 411 } else { | 388 } else { |
| 412 context = client_->CreateLiveTabContext(std::string()); | 389 context = client_->CreateLiveTabContext(std::string()); |
| 413 if (tab.has_browser()) | 390 if (tab.browser_id) |
| 414 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); | 391 UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID().id()); |
| 415 } | 392 } |
| 416 | 393 |
| 417 // Place the tab at the end if the tab index is no longer valid or | 394 // Place the tab at the end if the tab index is no longer valid or |
| 418 // we were passed a specific disposition. | 395 // we were passed a specific disposition. |
| 419 if (tab_index < 0 || tab_index > context->GetTabCount() || | 396 if (tab_index < 0 || tab_index > context->GetTabCount() || |
| 420 disposition != UNKNOWN) { | 397 disposition != UNKNOWN) { |
| 421 tab_index = context->GetTabCount(); | 398 tab_index = context->GetTabCount(); |
| 422 } | 399 } |
| 423 | 400 |
| 424 restored_tab = context->AddRestoredTab( | 401 restored_tab = context->AddRestoredTab( |
| 425 tab.navigations, tab_index, tab.current_navigation_index, | 402 tab.navigations, tab_index, tab.current_navigation_index, |
| 426 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, | 403 tab.extension_app_id, disposition != NEW_BACKGROUND_TAB, tab.pinned, |
| 427 tab.from_last_session, tab.platform_data.get(), | 404 tab.from_last_session, tab.platform_data.get(), |
| 428 tab.user_agent_override); | 405 tab.user_agent_override); |
| 429 restored_tab->LoadIfNecessary(); | 406 restored_tab->LoadIfNecessary(); |
| 430 } | 407 } |
| 431 client_->OnTabRestored( | 408 client_->OnTabRestored( |
| 432 tab.navigations.at(tab.current_navigation_index).virtual_url()); | 409 tab.navigations.at(tab.current_navigation_index).virtual_url()); |
| 433 if (live_tab) | 410 if (live_tab) |
| 434 *live_tab = restored_tab; | 411 *live_tab = restored_tab; |
| 435 | 412 |
| 436 return context; | 413 return context; |
| 437 } | 414 } |
| 438 | 415 |
| 439 | 416 |
| 440 bool TabRestoreServiceHelper::ValidateTab(Tab* tab) { | 417 bool TabRestoreServiceHelper::ValidateTab(const Tab& tab) { |
| 441 if (tab->navigations.empty()) | 418 return !tab.navigations.empty() && |
| 419 tab.current_navigation_index < tab.navigations.size(); |
| 420 } |
| 421 |
| 422 bool TabRestoreServiceHelper::ValidateWindow(const Window& window) { |
| 423 if (window.selected_tab_index >= window.tabs.size()) { |
| 442 return false; | 424 return false; |
| 425 } |
| 443 | 426 |
| 444 tab->current_navigation_index = | 427 for (const auto &tab : window.tabs) { |
| 445 std::max(0, std::min(tab->current_navigation_index, | 428 if (!ValidateTab(*tab)) { |
| 446 static_cast<int>(tab->navigations.size()) - 1)); | 429 return false; |
| 430 } |
| 431 } |
| 447 | 432 |
| 448 return true; | 433 return true; |
| 449 } | 434 } |
| 450 | 435 |
| 451 bool TabRestoreServiceHelper::ValidateWindow(Window* window) { | 436 bool TabRestoreServiceHelper::IsTabInteresting(const Tab& tab) { |
| 452 window->selected_tab_index = | 437 if (tab.navigations.empty()) |
| 453 std::max(0, std::min(window->selected_tab_index, | |
| 454 static_cast<int>(window->tabs.size() - 1))); | |
| 455 | |
| 456 int i = 0; | |
| 457 for (std::vector<Tab>::iterator tab_i = window->tabs.begin(); | |
| 458 tab_i != window->tabs.end();) { | |
| 459 if (!ValidateTab(&(*tab_i))) { | |
| 460 tab_i = window->tabs.erase(tab_i); | |
| 461 if (i < window->selected_tab_index) | |
| 462 window->selected_tab_index--; | |
| 463 else if (i == window->selected_tab_index) | |
| 464 window->selected_tab_index = 0; | |
| 465 } else { | |
| 466 ++tab_i; | |
| 467 ++i; | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 if (window->tabs.empty()) | |
| 472 return false; | 438 return false; |
| 473 | 439 |
| 474 return true; | 440 if (tab.navigations.size() > 1) |
| 441 return true; |
| 442 |
| 443 return tab.pinned || |
| 444 tab.navigations.at(0).virtual_url() != client_->GetNewTabURL(); |
| 475 } | 445 } |
| 476 | 446 |
| 477 bool TabRestoreServiceHelper::IsTabInteresting(const Tab* tab) { | 447 bool TabRestoreServiceHelper::IsWindowInteresting(const Window& window) { |
| 478 if (tab->navigations.empty()) | 448 if (window.tabs.empty()) |
| 479 return false; | 449 return false; |
| 480 | 450 |
| 481 if (tab->navigations.size() > 1) | 451 if (window.tabs.size() > 1) |
| 482 return true; | 452 return true; |
| 483 | 453 |
| 484 return tab->pinned || | 454 return IsTabInteresting(*window.tabs[0]); |
| 485 tab->navigations.at(0).virtual_url() != client_->GetNewTabURL(); | |
| 486 } | 455 } |
| 487 | 456 |
| 488 bool TabRestoreServiceHelper::IsWindowInteresting(const Window* window) { | 457 bool TabRestoreServiceHelper::FilterEntry(const Entry& entry) { |
| 489 if (window->tabs.empty()) | |
| 490 return false; | |
| 491 | |
| 492 if (window->tabs.size() > 1) | |
| 493 return true; | |
| 494 | |
| 495 return IsTabInteresting(&window->tabs[0]); | |
| 496 } | |
| 497 | |
| 498 bool TabRestoreServiceHelper::FilterEntry(Entry* entry) { | |
| 499 if (!ValidateEntry(entry)) | 458 if (!ValidateEntry(entry)) |
| 500 return false; | 459 return false; |
| 501 | 460 |
| 502 if (entry->type == TabRestoreService::TAB) | 461 switch (entry.type()) { |
| 503 return IsTabInteresting(static_cast<Tab*>(entry)); | 462 case TabRestoreService::TAB: |
| 504 else if (entry->type == TabRestoreService::WINDOW) | 463 return IsTabInteresting(static_cast<const Tab&>(entry)); |
| 505 return IsWindowInteresting(static_cast<Window*>(entry)); | 464 case TabRestoreService::WINDOW: |
| 506 | 465 return IsWindowInteresting(static_cast<const Window&>(entry)); |
| 466 } |
| 507 NOTREACHED(); | 467 NOTREACHED(); |
| 508 return false; | 468 return false; |
| 509 } | 469 } |
| 510 | 470 |
| 511 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, | 471 void TabRestoreServiceHelper::UpdateTabBrowserIDs(SessionID::id_type old_id, |
| 512 SessionID::id_type new_id) { | 472 SessionID::id_type new_id) { |
| 513 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) { | 473 for (const auto &entry : entries_) { |
| 514 Entry* entry = *i; | 474 if (entry->type() == TabRestoreService::TAB) { |
| 515 if (entry->type == TabRestoreService::TAB) { | 475 auto &tab = static_cast<Tab&>(*entry); |
| 516 Tab* tab = static_cast<Tab*>(entry); | 476 if (tab.browser_id == old_id) |
| 517 if (tab->browser_id == old_id) | 477 tab.browser_id = new_id; |
| 518 tab->browser_id = new_id; | |
| 519 } | 478 } |
| 520 } | 479 } |
| 521 } | 480 } |
| 522 | 481 |
| 523 base::Time TabRestoreServiceHelper::TimeNow() const { | 482 base::Time TabRestoreServiceHelper::TimeNow() const { |
| 524 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); | 483 return time_factory_ ? time_factory_->TimeNow() : base::Time::Now(); |
| 525 } | 484 } |
| 526 | 485 |
| 527 } // namespace sessions | 486 } // namespace sessions |
| OLD | NEW |