OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/sessions/tab_restore_service.h" | 5 #include "chrome/browser/sessions/tab_restore_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <map> | 9 #include <map> |
10 | 10 |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/scoped_vector.h" | 13 #include "base/scoped_vector.h" |
14 #include "base/stl_util-inl.h" | 14 #include "base/stl_util-inl.h" |
15 #include "chrome/browser/browser_list.h" | |
16 #include "chrome/browser/browser_window.h" | 15 #include "chrome/browser/browser_window.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
18 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/sessions/session_service.h" | 18 #include "chrome/browser/sessions/session_service.h" |
20 #include "chrome/browser/sessions/session_command.h" | 19 #include "chrome/browser/sessions/session_command.h" |
21 #include "chrome/browser/sessions/session_types.h" | 20 #include "chrome/browser/sessions/session_types.h" |
22 #include "chrome/browser/sessions/tab_restore_service_observer.h" | 21 #include "chrome/browser/sessions/tab_restore_service_observer.h" |
23 #include "chrome/browser/tabs/tab_strip_model.h" | |
24 #include "chrome/common/extensions/extension.h" | 22 #include "chrome/common/extensions/extension.h" |
25 #include "chrome/common/extensions/extension_constants.h" | 23 #include "chrome/common/extensions/extension_constants.h" |
26 #include "content/browser/tab_contents/navigation_controller.h" | 24 #include "content/browser/tab_contents/navigation_controller.h" |
27 #include "content/browser/tab_contents/navigation_entry.h" | 25 #include "content/browser/tab_contents/navigation_entry.h" |
28 #include "content/browser/tab_contents/tab_contents.h" | 26 #include "content/browser/tab_contents/tab_contents.h" |
29 | 27 |
30 using base::Time; | 28 using base::Time; |
31 | 29 |
32 // TimeFactory----------------------------------------------------------------- | 30 // TimeFactory----------------------------------------------------------------- |
33 | 31 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // If the ID matches one of this window's tabs, remove it from the list. | 143 // If the ID matches one of this window's tabs, remove it from the list. |
146 if ((*j).id == id) { | 144 if ((*j).id == id) { |
147 window->tabs.erase(j); | 145 window->tabs.erase(j); |
148 return; | 146 return; |
149 } | 147 } |
150 } | 148 } |
151 } | 149 } |
152 } | 150 } |
153 } | 151 } |
154 | 152 |
155 void RecordAppLaunch(Browser* browser, const TabRestoreService::Tab& tab) { | 153 void RecordAppLaunch(TabRestoreServiceDelegate* browser, |
| 154 const TabRestoreService::Tab& tab) { |
156 GURL url = tab.navigations.at(tab.current_navigation_index).virtual_url(); | 155 GURL url = tab.navigations.at(tab.current_navigation_index).virtual_url(); |
157 Profile* profile = browser->profile(); | 156 Profile* profile = browser->profile(); |
158 DCHECK(profile->GetExtensionService()); | 157 DCHECK(profile->GetExtensionService()); |
159 if (!profile->GetExtensionService()->IsInstalledApp(url)) | 158 if (!profile->GetExtensionService()->IsInstalledApp(url)) |
160 return; | 159 return; |
161 | 160 |
162 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, | 161 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, |
163 extension_misc::APP_LAUNCH_NTP_RECENTLY_CLOSED, | 162 extension_misc::APP_LAUNCH_NTP_RECENTLY_CLOSED, |
164 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); | 163 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); |
165 } | 164 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 } | 210 } |
212 | 211 |
213 void TabRestoreService::RemoveObserver(TabRestoreServiceObserver* observer) { | 212 void TabRestoreService::RemoveObserver(TabRestoreServiceObserver* observer) { |
214 observer_list_.RemoveObserver(observer); | 213 observer_list_.RemoveObserver(observer); |
215 } | 214 } |
216 | 215 |
217 void TabRestoreService::CreateHistoricalTab(NavigationController* tab) { | 216 void TabRestoreService::CreateHistoricalTab(NavigationController* tab) { |
218 if (restoring_) | 217 if (restoring_) |
219 return; | 218 return; |
220 | 219 |
221 Browser* browser = Browser::GetBrowserForController(tab, NULL); | 220 TabRestoreServiceDelegate* browser = |
| 221 TabRestoreServiceDelegate::GetBrowserForController(tab, NULL); |
222 if (closing_browsers_.find(browser) != closing_browsers_.end()) | 222 if (closing_browsers_.find(browser) != closing_browsers_.end()) |
223 return; | 223 return; |
224 | 224 |
225 scoped_ptr<Tab> local_tab(new Tab()); | 225 scoped_ptr<Tab> local_tab(new Tab()); |
226 PopulateTab(local_tab.get(), browser, tab); | 226 PopulateTab(local_tab.get(), browser, tab); |
227 if (local_tab->navigations.empty()) | 227 if (local_tab->navigations.empty()) |
228 return; | 228 return; |
229 | 229 |
230 AddEntry(local_tab.release(), true, true); | 230 AddEntry(local_tab.release(), true, true); |
231 } | 231 } |
232 | 232 |
233 void TabRestoreService::BrowserClosing(Browser* browser) { | 233 void TabRestoreService::BrowserClosing(TabRestoreServiceDelegate* browser) { |
234 if (browser->type() != Browser::TYPE_NORMAL || | 234 if (!browser->IsNormalBrowser() || browser->tab_count() == 0) |
235 browser->tab_count() == 0) | |
236 return; | 235 return; |
237 | 236 |
238 closing_browsers_.insert(browser); | 237 closing_browsers_.insert(browser); |
239 | 238 |
240 scoped_ptr<Window> window(new Window()); | 239 scoped_ptr<Window> window(new Window()); |
241 window->selected_tab_index = browser->selected_index(); | 240 window->selected_tab_index = browser->selected_index(); |
242 window->timestamp = TimeNow(); | 241 window->timestamp = TimeNow(); |
243 // Don't use std::vector::resize() because it will push copies of an empty tab | 242 // Don't use std::vector::resize() because it will push copies of an empty tab |
244 // into the vector, which will give all tabs in a window the same ID. | 243 // into the vector, which will give all tabs in a window the same ID. |
245 for (int i = 0; i < browser->tab_count(); ++i) { | 244 for (int i = 0; i < browser->tab_count(); ++i) { |
(...skipping 17 matching lines...) Expand all Loading... |
263 // the stack. | 262 // the stack. |
264 AddEntry(new Tab(window->tabs[0]), true, true); | 263 AddEntry(new Tab(window->tabs[0]), true, true); |
265 } else if (!window->tabs.empty()) { | 264 } else if (!window->tabs.empty()) { |
266 window->selected_tab_index = | 265 window->selected_tab_index = |
267 std::min(static_cast<int>(window->tabs.size() - 1), | 266 std::min(static_cast<int>(window->tabs.size() - 1), |
268 window->selected_tab_index); | 267 window->selected_tab_index); |
269 AddEntry(window.release(), true, true); | 268 AddEntry(window.release(), true, true); |
270 } | 269 } |
271 } | 270 } |
272 | 271 |
273 void TabRestoreService::BrowserClosed(Browser* browser) { | 272 void TabRestoreService::BrowserClosed(TabRestoreServiceDelegate* browser) { |
274 closing_browsers_.erase(browser); | 273 closing_browsers_.erase(browser); |
275 } | 274 } |
276 | 275 |
277 void TabRestoreService::ClearEntries() { | 276 void TabRestoreService::ClearEntries() { |
278 // Mark all the tabs as closed so that we don't attempt to restore them. | 277 // Mark all the tabs as closed so that we don't attempt to restore them. |
279 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) | 278 for (Entries::iterator i = entries_.begin(); i != entries_.end(); ++i) |
280 ScheduleCommand(CreateRestoredEntryCommand((*i)->id)); | 279 ScheduleCommand(CreateRestoredEntryCommand((*i)->id)); |
281 | 280 |
282 entries_to_write_ = 0; | 281 entries_to_write_ = 0; |
283 | 282 |
284 // Schedule a pending reset so that we nuke the file on next write. | 283 // Schedule a pending reset so that we nuke the file on next write. |
285 set_pending_reset(true); | 284 set_pending_reset(true); |
286 | 285 |
287 // Schedule a command, otherwise if there are no pending commands Save does | 286 // Schedule a command, otherwise if there are no pending commands Save does |
288 // nothing. | 287 // nothing. |
289 ScheduleCommand(CreateRestoredEntryCommand(1)); | 288 ScheduleCommand(CreateRestoredEntryCommand(1)); |
290 | 289 |
291 STLDeleteElements(&entries_); | 290 STLDeleteElements(&entries_); |
292 NotifyTabsChanged(); | 291 NotifyTabsChanged(); |
293 } | 292 } |
294 | 293 |
295 const TabRestoreService::Entries& TabRestoreService::entries() const { | 294 const TabRestoreService::Entries& TabRestoreService::entries() const { |
296 return entries_; | 295 return entries_; |
297 } | 296 } |
298 | 297 |
299 void TabRestoreService::RestoreMostRecentEntry(Browser* browser) { | 298 void TabRestoreService::RestoreMostRecentEntry( |
| 299 TabRestoreServiceDelegate* browser) { |
300 if (entries_.empty()) | 300 if (entries_.empty()) |
301 return; | 301 return; |
302 | 302 |
303 RestoreEntryById(browser, entries_.front()->id, false); | 303 RestoreEntryById(browser, entries_.front()->id, false); |
304 } | 304 } |
305 | 305 |
306 void TabRestoreService::RestoreEntryById(Browser* browser, | 306 void TabRestoreService::RestoreEntryById(TabRestoreServiceDelegate* browser, |
307 SessionID::id_type id, | 307 SessionID::id_type id, |
308 bool replace_existing_tab) { | 308 bool replace_existing_tab) { |
309 Entries::iterator i = GetEntryIteratorById(id); | 309 Entries::iterator i = GetEntryIteratorById(id); |
310 if (i == entries_.end()) { | 310 if (i == entries_.end()) { |
311 // Don't hoark here, we allow an invalid id. | 311 // Don't hoark here, we allow an invalid id. |
312 return; | 312 return; |
313 } | 313 } |
314 | 314 |
315 size_t index = 0; | 315 size_t index = 0; |
316 for (Entries::iterator j = entries_.begin(); j != i && j != entries_.end(); | 316 for (Entries::iterator j = entries_.begin(); j != i && j != entries_.end(); |
(...skipping 16 matching lines...) Expand all Loading... |
333 } | 333 } |
334 | 334 |
335 // |browser| will be NULL in cases where one isn't already available (eg, | 335 // |browser| will be NULL in cases where one isn't already available (eg, |
336 // when invoked on Mac OS X with no windows open). In this case, create a | 336 // when invoked on Mac OS X with no windows open). In this case, create a |
337 // new browser into which we restore the tabs. | 337 // new browser into which we restore the tabs. |
338 if (entry->type == TAB) { | 338 if (entry->type == TAB) { |
339 Tab* tab = static_cast<Tab*>(entry); | 339 Tab* tab = static_cast<Tab*>(entry); |
340 browser = RestoreTab(*tab, browser, replace_existing_tab); | 340 browser = RestoreTab(*tab, browser, replace_existing_tab); |
341 browser->window()->Show(); | 341 browser->window()->Show(); |
342 } else if (entry->type == WINDOW) { | 342 } else if (entry->type == WINDOW) { |
343 Browser* current_browser = browser; | 343 TabRestoreServiceDelegate* current_browser = browser; |
344 Window* window = static_cast<Window*>(entry); | 344 Window* window = static_cast<Window*>(entry); |
345 | 345 |
346 // When restoring a window, either the entire window can be restored, or a | 346 // When restoring a window, either the entire window can be restored, or a |
347 // single tab within it. If the entry's ID matches the one to restore, then | 347 // single tab within it. If the entry's ID matches the one to restore, then |
348 // the entire window will be restored. | 348 // the entire window will be restored. |
349 if (!restoring_tab_in_window) { | 349 if (!restoring_tab_in_window) { |
350 browser = Browser::Create(profile()); | 350 browser = TabRestoreServiceDelegate::Create(profile()); |
351 for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) { | 351 for (size_t tab_i = 0; tab_i < window->tabs.size(); ++tab_i) { |
352 const Tab& tab = window->tabs[tab_i]; | 352 const Tab& tab = window->tabs[tab_i]; |
353 TabContents* restored_tab = | 353 TabContents* restored_tab = |
354 browser->AddRestoredTab(tab.navigations, browser->tab_count(), | 354 browser->AddRestoredTab(tab.navigations, browser->tab_count(), |
355 tab.current_navigation_index, | 355 tab.current_navigation_index, |
356 tab.extension_app_id, | 356 tab.extension_app_id, |
357 (static_cast<int>(tab_i) == | 357 (static_cast<int>(tab_i) == |
358 window->selected_tab_index), | 358 window->selected_tab_index), |
359 tab.pinned, tab.from_last_session, | 359 tab.pinned, tab.from_last_session, |
360 tab.session_storage_namespace); | 360 tab.session_storage_namespace); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 } | 469 } |
470 entries_written_++; | 470 entries_written_++; |
471 } | 471 } |
472 } | 472 } |
473 if (pending_reset()) | 473 if (pending_reset()) |
474 entries_written_ = 0; | 474 entries_written_ = 0; |
475 BaseSessionService::Save(); | 475 BaseSessionService::Save(); |
476 } | 476 } |
477 | 477 |
478 void TabRestoreService::PopulateTab(Tab* tab, | 478 void TabRestoreService::PopulateTab(Tab* tab, |
479 Browser* browser, | 479 TabRestoreServiceDelegate* browser, |
480 NavigationController* controller) { | 480 NavigationController* controller) { |
481 const int pending_index = controller->pending_entry_index(); | 481 const int pending_index = controller->pending_entry_index(); |
482 int entry_count = controller->entry_count(); | 482 int entry_count = controller->entry_count(); |
483 if (entry_count == 0 && pending_index == 0) | 483 if (entry_count == 0 && pending_index == 0) |
484 entry_count++; | 484 entry_count++; |
485 tab->navigations.resize(static_cast<int>(entry_count)); | 485 tab->navigations.resize(static_cast<int>(entry_count)); |
486 for (int i = 0; i < entry_count; ++i) { | 486 for (int i = 0; i < entry_count; ++i) { |
487 NavigationEntry* entry = (i == pending_index) ? | 487 NavigationEntry* entry = (i == pending_index) ? |
488 controller->pending_entry() : controller->GetEntryAtIndex(i); | 488 controller->pending_entry() : controller->GetEntryAtIndex(i); |
489 tab->navigations[i].SetFromNavigationEntry(*entry); | 489 tab->navigations[i].SetFromNavigationEntry(*entry); |
490 } | 490 } |
491 tab->timestamp = TimeNow(); | 491 tab->timestamp = TimeNow(); |
492 tab->current_navigation_index = controller->GetCurrentEntryIndex(); | 492 tab->current_navigation_index = controller->GetCurrentEntryIndex(); |
493 if (tab->current_navigation_index == -1 && entry_count > 0) | 493 if (tab->current_navigation_index == -1 && entry_count > 0) |
494 tab->current_navigation_index = 0; | 494 tab->current_navigation_index = 0; |
495 | 495 |
496 const Extension* extension = controller->tab_contents()->extension_app(); | 496 const Extension* extension = controller->tab_contents()->extension_app(); |
497 if (extension) | 497 if (extension) |
498 tab->extension_app_id = extension->id(); | 498 tab->extension_app_id = extension->id(); |
499 | 499 |
500 tab->session_storage_namespace = controller->session_storage_namespace(); | 500 tab->session_storage_namespace = controller->session_storage_namespace(); |
501 | 501 |
502 // Browser may be NULL during unit tests. | 502 // Browser may be NULL during unit tests. |
503 if (browser) { | 503 if (browser) { |
504 tab->browser_id = browser->session_id().id(); | 504 tab->browser_id = browser->session_id().id(); |
505 tab->tabstrip_index = | 505 tab->tabstrip_index = browser->GetIndexOfController(controller); |
506 browser->tabstrip_model()->GetIndexOfController(controller); | 506 tab->pinned = browser->IsTabPinned(tab->tabstrip_index); |
507 tab->pinned = browser->tabstrip_model()->IsTabPinned(tab->tabstrip_index); | |
508 } | 507 } |
509 } | 508 } |
510 | 509 |
511 void TabRestoreService::NotifyTabsChanged() { | 510 void TabRestoreService::NotifyTabsChanged() { |
512 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, | 511 FOR_EACH_OBSERVER(TabRestoreServiceObserver, observer_list_, |
513 TabRestoreServiceChanged(this)); | 512 TabRestoreServiceChanged(this)); |
514 } | 513 } |
515 | 514 |
516 void TabRestoreService::AddEntry(Entry* entry, bool notify, bool to_front) { | 515 void TabRestoreService::AddEntry(Entry* entry, bool notify, bool to_front) { |
517 if (to_front) | 516 if (to_front) |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 } | 871 } |
873 } | 872 } |
874 | 873 |
875 // If there was corruption some of the entries won't be valid. Prune any | 874 // If there was corruption some of the entries won't be valid. Prune any |
876 // entries with no navigations. | 875 // entries with no navigations. |
877 ValidateAndDeleteEmptyEntries(&(entries.get())); | 876 ValidateAndDeleteEmptyEntries(&(entries.get())); |
878 | 877 |
879 loaded_entries->swap(entries.get()); | 878 loaded_entries->swap(entries.get()); |
880 } | 879 } |
881 | 880 |
882 Browser* TabRestoreService::RestoreTab(const Tab& tab, | 881 TabRestoreServiceDelegate* TabRestoreService::RestoreTab(const Tab& tab, |
883 Browser* browser, | 882 TabRestoreServiceDelegate* browser, |
884 bool replace_existing_tab) { | 883 bool replace_existing_tab) { |
885 // |browser| will be NULL in cases where one isn't already available (eg, | 884 // |browser| will be NULL in cases where one isn't already available (eg, |
886 // when invoked on Mac OS X with no windows open). In this case, create a | 885 // when invoked on Mac OS X with no windows open). In this case, create a |
887 // new browser into which we restore the tabs. | 886 // new browser into which we restore the tabs. |
888 if (replace_existing_tab && browser) { | 887 if (replace_existing_tab && browser) { |
889 browser->ReplaceRestoredTab(tab.navigations, | 888 browser->ReplaceRestoredTab(tab.navigations, |
890 tab.current_navigation_index, | 889 tab.current_navigation_index, |
891 tab.from_last_session, | 890 tab.from_last_session, |
892 tab.extension_app_id, | 891 tab.extension_app_id, |
893 tab.session_storage_namespace); | 892 tab.session_storage_namespace); |
894 } else { | 893 } else { |
895 if (tab.has_browser()) | 894 if (tab.has_browser()) |
896 browser = BrowserList::FindBrowserWithID(tab.browser_id); | 895 browser = TabRestoreServiceDelegate::FindBrowserWithID(tab.browser_id); |
897 | 896 |
898 int tab_index = -1; | 897 int tab_index = -1; |
899 if (browser) { | 898 if (browser) { |
900 tab_index = tab.tabstrip_index; | 899 tab_index = tab.tabstrip_index; |
901 } else { | 900 } else { |
902 browser = Browser::Create(profile()); | 901 browser = TabRestoreServiceDelegate::Create(profile()); |
903 if (tab.has_browser()) { | 902 if (tab.has_browser()) { |
904 UpdateTabBrowserIDs(tab.browser_id, browser->session_id().id()); | 903 UpdateTabBrowserIDs(tab.browser_id, browser->session_id().id()); |
905 } | 904 } |
906 } | 905 } |
907 | 906 |
908 if (tab_index < 0 || tab_index > browser->tab_count()) { | 907 if (tab_index < 0 || tab_index > browser->tab_count()) { |
909 tab_index = browser->tab_count(); | 908 tab_index = browser->tab_count(); |
910 } | 909 } |
911 | 910 |
912 browser->AddRestoredTab(tab.navigations, | 911 browser->AddRestoredTab(tab.navigations, |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 // correctly write out the entries when Save is invoked (Save starts from | 1075 // correctly write out the entries when Save is invoked (Save starts from |
1077 // the front, not the end and we just added the entries to the end). | 1076 // the front, not the end and we just added the entries to the end). |
1078 entries_to_write_ = staging_entries_.size(); | 1077 entries_to_write_ = staging_entries_.size(); |
1079 | 1078 |
1080 PruneAndNotify(); | 1079 PruneAndNotify(); |
1081 } | 1080 } |
1082 | 1081 |
1083 Time TabRestoreService::TimeNow() const { | 1082 Time TabRestoreService::TimeNow() const { |
1084 return time_factory_ ? time_factory_->TimeNow() : Time::Now(); | 1083 return time_factory_ ? time_factory_->TimeNow() : Time::Now(); |
1085 } | 1084 } |
OLD | NEW |