1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/sessions/session_restore.h" 6 7 #include <algorithm> 8 #include <list> 9 #include <set> 10 #include <string> 11 12 #include "base/bind.h" 13 #include "base/bind_helpers.h" 14 #include "base/callback.h" 15 #include "base/command_line.h" 16 #include "base/debug/alias.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_vector.h" 19 #include "base/metrics/histogram.h" 20 #include "base/run_loop.h" 21 #include "base/stl_util.h" 22 #include "base/strings/stringprintf.h" 23 #include "base/task/cancelable_task_tracker.h" 24 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/chrome_notification_types.h" 26 #include "chrome/browser/performance_monitor/startup_timer.h" 27 #include "chrome/browser/profiles/profile.h" 28 #include "chrome/browser/search/search.h" 29 #include "chrome/browser/sessions/session_service.h" 30 #include "chrome/browser/sessions/session_service_factory.h" 31 #include "chrome/browser/sessions/session_types.h" 32 #include "chrome/browser/ui/browser.h" 33 #include "chrome/browser/ui/browser_finder.h" 34 #include "chrome/browser/ui/browser_navigator.h" 35 #include "chrome/browser/ui/browser_tabrestore.h" 36 #include "chrome/browser/ui/browser_tabstrip.h" 37 #include "chrome/browser/ui/browser_window.h" 38 #include "chrome/browser/ui/tabs/tab_strip_model.h" 39 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" 40 #include "chrome/common/url_constants.h" 41 #include "content/public/browser/child_process_security_policy.h" 42 #include "content/public/browser/dom_storage_context.h" 43 #include "content/public/browser/navigation_controller.h" 44 #include "content/public/browser/notification_registrar.h" 45 #include "content/public/browser/notification_service.h" 46 #include "content/public/browser/render_process_host.h" 47 #include "content/public/browser/render_widget_host.h" 48 #include "content/public/browser/render_widget_host_view.h" 49 #include "content/public/browser/session_storage_namespace.h" 50 #include "content/public/browser/storage_partition.h" 51 #include "content/public/browser/web_contents.h" 52 #include "extensions/browser/extension_registry.h" 53 #include "extensions/common/extension_set.h" 54 #include "net/base/network_change_notifier.h" 55 56 #if defined(OS_CHROMEOS) 57 #include "chrome/browser/chromeos/boot_times_loader.h" 58 #endif 59 60 using content::NavigationController; 61 using content::RenderWidgetHost; 62 using content::WebContents; 63 64 namespace { 65 66 class SessionRestoreImpl; 67 class TabLoader; 68 69 TabLoader* shared_tab_loader = NULL; 70 71 // Pointers to SessionRestoreImpls which are currently restoring the session. 72 std::set<SessionRestoreImpl*>* active_session_restorers = NULL; 73 74 // TabLoader ------------------------------------------------------------------ 75 76 // Initial delay (see class decription for details). 77 static const int kInitialDelayTimerMS = 100; 78 79 // TabLoader is responsible for loading tabs after session restore creates 80 // tabs. New tabs are loaded after the current tab finishes loading, or a delay 81 // is reached (initially kInitialDelayTimerMS). If the delay is reached before 82 // a tab finishes loading a new tab is loaded and the time of the delay 83 // doubled. 84 // 85 // TabLoader keeps a reference to itself when it's loading. When it has finished 86 // loading, it drops the reference. If another profile is restored while the 87 // TabLoader is loading, it will schedule its tabs to get loaded by the same 88 // TabLoader. When doing the scheduling, it holds a reference to the TabLoader. 89 // 90 // This is not part of SessionRestoreImpl so that synchronous destruction 91 // of SessionRestoreImpl doesn't have timing problems. 92 class TabLoader : public content::NotificationObserver, 93 public net::NetworkChangeNotifier::ConnectionTypeObserver, 94 public base::RefCounted<TabLoader> { 95 public: 96 // Retrieves a pointer to the TabLoader instance shared between profiles, or 97 // creates a new TabLoader if it doesn't exist. If a TabLoader is created, its 98 // starting timestamp is set to |restore_started|. 99 static TabLoader* GetTabLoader(base::TimeTicks restore_started); 100 101 // Schedules a tab for loading. 102 void ScheduleLoad(NavigationController* controller); 103 104 // Notifies the loader that a tab has been scheduled for loading through 105 // some other mechanism. 106 void TabIsLoading(NavigationController* controller); 107 108 // Invokes |LoadNextTab| to load a tab. 109 // 110 // This must be invoked once to start loading. 111 void StartLoading(); 112 113 private: 114 friend class base::RefCounted<TabLoader>; 115 116 typedef std::set<NavigationController*> TabsLoading; 117 typedef std::list<NavigationController*> TabsToLoad; 118 typedef std::set<RenderWidgetHost*> RenderWidgetHostSet; 119 120 explicit TabLoader(base::TimeTicks restore_started); 121 virtual ~TabLoader(); 122 123 // Loads the next tab. If there are no more tabs to load this deletes itself, 124 // otherwise |force_load_timer_| is restarted. 125 void LoadNextTab(); 126 127 // NotificationObserver method. Removes the specified tab and loads the next 128 // tab. 129 virtual void Observe(int type, 130 const content::NotificationSource& source, 131 const content::NotificationDetails& details) OVERRIDE; 132 133 // net::NetworkChangeNotifier::ConnectionTypeObserver overrides. 134 virtual void OnConnectionTypeChanged( 135 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE; 136 137 // Removes the listeners from the specified tab and removes the tab from 138 // the set of tabs to load and list of tabs we're waiting to get a load 139 // from. 140 void RemoveTab(NavigationController* tab); 141 142 // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes 143 // |LoadNextTab| to load the next tab 144 void ForceLoadTimerFired(); 145 146 // Returns the RenderWidgetHost associated with a tab if there is one, 147 // NULL otherwise. 148 static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab); 149 150 // Register for necessary notifications on a tab navigation controller. 151 void RegisterForNotifications(NavigationController* controller); 152 153 // Called when a tab goes away or a load completes. 154 void HandleTabClosedOrLoaded(NavigationController* controller); 155 156 // TODO(sky): remove. For debugging 368236. 157 void CheckNotObserving(NavigationController* controller); 158 159 content::NotificationRegistrar registrar_; 160 161 // Current delay before a new tab is loaded. See class description for 162 // details. 163 int64 force_load_delay_; 164 165 // Has Load been invoked? 166 bool loading_; 167 168 // Have we recorded the times for a tab paint? 169 bool got_first_paint_; 170 171 // The set of tabs we've initiated loading on. This does NOT include the 172 // selected tabs. 173 TabsLoading tabs_loading_; 174 175 // The tabs we need to load. 176 TabsToLoad tabs_to_load_; 177 178 // The renderers we have started loading into. 179 RenderWidgetHostSet render_widget_hosts_loading_; 180 181 // The renderers we have loaded and are waiting on to paint. 182 RenderWidgetHostSet render_widget_hosts_to_paint_; 183 184 // The number of tabs that have been restored. 185 int tab_count_; 186 187 base::OneShotTimer<TabLoader> force_load_timer_; 188 189 // The time the restore process started. 190 base::TimeTicks restore_started_; 191 192 // Max number of tabs that were loaded in parallel (for metrics). 193 size_t max_parallel_tab_loads_; 194 195 // For keeping TabLoader alive while it's loading even if no 196 // SessionRestoreImpls reference it. 197 scoped_refptr<TabLoader> this_retainer_; 198 199 DISALLOW_COPY_AND_ASSIGN(TabLoader); 200 }; 201 202 // static 203 TabLoader* TabLoader::GetTabLoader(base::TimeTicks restore_started) { 204 if (!shared_tab_loader) 205 shared_tab_loader = new TabLoader(restore_started); 206 return shared_tab_loader; 207 } 208 209 void TabLoader::ScheduleLoad(NavigationController* controller) { 210 CheckNotObserving(controller); 211 DCHECK(controller); 212 DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) == 213 tabs_to_load_.end()); 214 tabs_to_load_.push_back(controller); 215 RegisterForNotifications(controller); 216 } 217 218 void TabLoader::TabIsLoading(NavigationController* controller) { 219 CheckNotObserving(controller); 220 DCHECK(controller); 221 DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) == 222 tabs_loading_.end()); 223 tabs_loading_.insert(controller); 224 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller); 225 DCHECK(render_widget_host); 226 render_widget_hosts_loading_.insert(render_widget_host); 227 RegisterForNotifications(controller); 228 } 229 230 void TabLoader::StartLoading() { 231 // When multiple profiles are using the same TabLoader, another profile might 232 // already have started loading. In that case, the tabs scheduled for loading 233 // by this profile are already in the loading queue, and they will get loaded 234 // eventually. 235 if (loading_) 236 return; 237 registrar_.Add( 238 this, 239 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 240 content::NotificationService::AllSources()); 241 this_retainer_ = this; 242 #if defined(OS_CHROMEOS) 243 if (!net::NetworkChangeNotifier::IsOffline()) { 244 loading_ = true; 245 LoadNextTab(); 246 } else { 247 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); 248 } 249 #else 250 loading_ = true; 251 LoadNextTab(); 252 #endif 253 } 254 255 TabLoader::TabLoader(base::TimeTicks restore_started) 256 : force_load_delay_(kInitialDelayTimerMS), 257 loading_(false), 258 got_first_paint_(false), 259 tab_count_(0), 260 restore_started_(restore_started), 261 max_parallel_tab_loads_(0) { 262 } 263 264 TabLoader::~TabLoader() { 265 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 266 tabs_loading_.empty() && tabs_to_load_.empty()); 267 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); 268 shared_tab_loader = NULL; 269 } 270 271 void TabLoader::LoadNextTab() { 272 if (!tabs_to_load_.empty()) { 273 NavigationController* tab = tabs_to_load_.front(); 274 DCHECK(tab); 275 tabs_loading_.insert(tab); 276 if (tabs_loading_.size() > max_parallel_tab_loads_) 277 max_parallel_tab_loads_ = tabs_loading_.size(); 278 tabs_to_load_.pop_front(); 279 tab->LoadIfNecessary(); 280 content::WebContents* contents = tab->GetWebContents(); 281 if (contents) { 282 Browser* browser = chrome::FindBrowserWithWebContents(contents); 283 if (browser && 284 browser->tab_strip_model()->GetActiveWebContents() != contents) { 285 // By default tabs are marked as visible. As only the active tab is 286 // visible we need to explicitly tell non-active tabs they are hidden. 287 // Without this call non-active tabs are not marked as backgrounded. 288 // 289 // NOTE: We need to do this here rather than when the tab is added to 290 // the Browser as at that time not everything has been created, so that 291 // the call would do nothing. 292 contents->WasHidden(); 293 } 294 } 295 } 296 297 if (!tabs_to_load_.empty()) { 298 force_load_timer_.Stop(); 299 // Each time we load a tab we also set a timer to force us to start loading 300 // the next tab if this one doesn't load quickly enough. 301 force_load_timer_.Start(FROM_HERE, 302 base::TimeDelta::FromMilliseconds(force_load_delay_), 303 this, &TabLoader::ForceLoadTimerFired); 304 } 305 306 // When the session restore is done synchronously, notification is sent from 307 // SessionRestoreImpl::Restore . 308 if (tabs_to_load_.empty() && !SessionRestore::IsRestoringSynchronously()) { 309 content::NotificationService::current()->Notify( 310 chrome::NOTIFICATION_SESSION_RESTORE_DONE, 311 content::NotificationService::AllSources(), 312 content::NotificationService::NoDetails()); 313 } 314 } 315 316 void TabLoader::Observe(int type, 317 const content::NotificationSource& source, 318 const content::NotificationDetails& details) { 319 switch (type) { 320 case content::NOTIFICATION_LOAD_START: { 321 // Add this render_widget_host to the set of those we're waiting for 322 // paints on. We want to only record stats for paints that occur after 323 // a load has finished. 324 NavigationController* tab = 325 content::Source<NavigationController>(source).ptr(); 326 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); 327 DCHECK(render_widget_host); 328 render_widget_hosts_loading_.insert(render_widget_host); 329 break; 330 } 331 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 332 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 333 if (!got_first_paint_) { 334 RenderWidgetHost* render_widget_host = 335 GetRenderWidgetHost(&web_contents->GetController()); 336 render_widget_hosts_loading_.erase(render_widget_host); 337 } 338 HandleTabClosedOrLoaded(&web_contents->GetController()); 339 break; 340 } 341 case content::NOTIFICATION_LOAD_STOP: { 342 NavigationController* tab = 343 content::Source<NavigationController>(source).ptr(); 344 render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab)); 345 HandleTabClosedOrLoaded(tab); 346 break; 347 } 348 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: { 349 RenderWidgetHost* render_widget_host = 350 content::Source<RenderWidgetHost>(source).ptr(); 351 if (!got_first_paint_ && render_widget_host->GetView() && 352 render_widget_host->GetView()->IsShowing()) { 353 if (render_widget_hosts_to_paint_.find(render_widget_host) != 354 render_widget_hosts_to_paint_.end()) { 355 // Got a paint for one of our renderers, so record time. 356 got_first_paint_ = true; 357 base::TimeDelta time_to_paint = 358 base::TimeTicks::Now() - restore_started_; 359 UMA_HISTOGRAM_CUSTOM_TIMES( 360 "SessionRestore.FirstTabPainted", 361 time_to_paint, 362 base::TimeDelta::FromMilliseconds(10), 363 base::TimeDelta::FromSeconds(100), 364 100); 365 // Record a time for the number of tabs, to help track down 366 // contention. 367 std::string time_for_count = 368 base::StringPrintf("SessionRestore.FirstTabPainted_%d", 369 tab_count_); 370 base::HistogramBase* counter_for_count = 371 base::Histogram::FactoryTimeGet( 372 time_for_count, 373 base::TimeDelta::FromMilliseconds(10), 374 base::TimeDelta::FromSeconds(100), 375 100, 376 base::Histogram::kUmaTargetedHistogramFlag); 377 counter_for_count->AddTime(time_to_paint); 378 } else if (render_widget_hosts_loading_.find(render_widget_host) == 379 render_widget_hosts_loading_.end()) { 380 // If this is a host for a tab we're not loading some other tab 381 // has rendered and there's no point tracking the time. This could 382 // happen because the user opened a different tab or restored tabs 383 // to an already existing browser and an existing tab painted. 384 got_first_paint_ = true; 385 } 386 } 387 break; 388 } 389 default: 390 NOTREACHED() << "Unknown notification received:" << type; 391 } 392 // Delete ourselves when we're not waiting for any more notifications. If this 393 // was not the last reference, a SessionRestoreImpl holding a reference will 394 // eventually call StartLoading (which assigns this_retainer_), or drop the 395 // reference without initiating a load. 396 if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 397 tabs_loading_.empty() && tabs_to_load_.empty()) 398 this_retainer_ = NULL; 399 } 400 401 void TabLoader::OnConnectionTypeChanged( 402 net::NetworkChangeNotifier::ConnectionType type) { 403 if (type != net::NetworkChangeNotifier::CONNECTION_NONE) { 404 if (!loading_) { 405 loading_ = true; 406 LoadNextTab(); 407 } 408 } else { 409 loading_ = false; 410 } 411 } 412 413 void TabLoader::RemoveTab(NavigationController* tab) { 414 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 415 content::Source<WebContents>(tab->GetWebContents())); 416 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP, 417 content::Source<NavigationController>(tab)); 418 registrar_.Remove(this, content::NOTIFICATION_LOAD_START, 419 content::Source<NavigationController>(tab)); 420 421 TabsLoading::iterator i = tabs_loading_.find(tab); 422 if (i != tabs_loading_.end()) 423 tabs_loading_.erase(i); 424 425 TabsToLoad::iterator j = 426 find(tabs_to_load_.begin(), tabs_to_load_.end(), tab); 427 if (j != tabs_to_load_.end()) 428 tabs_to_load_.erase(j); 429 } 430 431 void TabLoader::ForceLoadTimerFired() { 432 force_load_delay_ *= 2; 433 LoadNextTab(); 434 } 435 436 RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) { 437 WebContents* web_contents = tab->GetWebContents(); 438 if (web_contents) { 439 content::RenderWidgetHostView* render_widget_host_view = 440 web_contents->GetRenderWidgetHostView(); 441 if (render_widget_host_view) 442 return render_widget_host_view->GetRenderWidgetHost(); 443 } 444 return NULL; 445 } 446 447 void TabLoader::RegisterForNotifications(NavigationController* controller) { 448 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 449 content::Source<WebContents>(controller->GetWebContents())); 450 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 451 content::Source<NavigationController>(controller)); 452 registrar_.Add(this, content::NOTIFICATION_LOAD_START, 453 content::Source<NavigationController>(controller)); 454 ++tab_count_; 455 } 456 457 void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) { 458 RemoveTab(tab); 459 if (loading_) 460 LoadNextTab(); 461 if (tabs_loading_.empty() && tabs_to_load_.empty()) { 462 base::TimeDelta time_to_load = 463 base::TimeTicks::Now() - restore_started_; 464 performance_monitor::StartupTimer::SetElapsedSessionRestoreTime( 465 time_to_load); 466 UMA_HISTOGRAM_CUSTOM_TIMES( 467 "SessionRestore.AllTabsLoaded", 468 time_to_load, 469 base::TimeDelta::FromMilliseconds(10), 470 base::TimeDelta::FromSeconds(100), 471 100); 472 // Record a time for the number of tabs, to help track down contention. 473 std::string time_for_count = 474 base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_); 475 base::HistogramBase* counter_for_count = 476 base::Histogram::FactoryTimeGet( 477 time_for_count, 478 base::TimeDelta::FromMilliseconds(10), 479 base::TimeDelta::FromSeconds(100), 480 100, 481 base::Histogram::kUmaTargetedHistogramFlag); 482 counter_for_count->AddTime(time_to_load); 483 484 UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads", 485 max_parallel_tab_loads_); 486 } 487 } 488 489 void TabLoader::CheckNotObserving(NavigationController* controller) { 490 const bool in_tabs_to_load = 491 find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) != 492 tabs_to_load_.end(); 493 const bool in_tabs_loading = 494 find(tabs_loading_.begin(), tabs_loading_.end(), controller) != 495 tabs_loading_.end(); 496 const bool observing = 497 registrar_.IsRegistered( 498 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 499 content::Source<WebContents>(controller->GetWebContents())) || 500 registrar_.IsRegistered( 501 this, content::NOTIFICATION_LOAD_STOP, 502 content::Source<NavigationController>(controller)) || 503 registrar_.IsRegistered( 504 this, content::NOTIFICATION_LOAD_START, 505 content::Source<NavigationController>(controller)); 506 base::debug::Alias(&in_tabs_to_load); 507 base::debug::Alias(&in_tabs_loading); 508 base::debug::Alias(&observing); 509 CHECK(!in_tabs_to_load && !in_tabs_loading && !observing); 510 } 511 512 // SessionRestoreImpl --------------------------------------------------------- 513 514 // SessionRestoreImpl is responsible for fetching the set of tabs to create 515 // from SessionService. SessionRestoreImpl deletes itself when done. 516 517 class SessionRestoreImpl : public content::NotificationObserver { 518 public: 519 SessionRestoreImpl(Profile* profile, 520 Browser* browser, 521 chrome::HostDesktopType host_desktop_type, 522 bool synchronous, 523 bool clobber_existing_tab, 524 bool always_create_tabbed_browser, 525 const std::vector<GURL>& urls_to_open) 526 : profile_(profile), 527 browser_(browser), 528 host_desktop_type_(host_desktop_type), 529 synchronous_(synchronous), 530 clobber_existing_tab_(clobber_existing_tab), 531 always_create_tabbed_browser_(always_create_tabbed_browser), 532 urls_to_open_(urls_to_open), 533 active_window_id_(0), 534 restore_started_(base::TimeTicks::Now()), 535 browser_shown_(false) { 536 // For sanity's sake, if |browser| is non-null: force |host_desktop_type| to 537 // be the same as |browser|'s desktop type. 538 DCHECK(!browser || browser->host_desktop_type() == host_desktop_type); 539 540 if (active_session_restorers == NULL) 541 active_session_restorers = new std::set<SessionRestoreImpl*>(); 542 543 // Only one SessionRestoreImpl should be operating on the profile at the 544 // same time. 545 std::set<SessionRestoreImpl*>::const_iterator it; 546 for (it = active_session_restorers->begin(); 547 it != active_session_restorers->end(); ++it) { 548 if ((*it)->profile_ == profile) 549 break; 550 } 551 DCHECK(it == active_session_restorers->end()); 552 553 active_session_restorers->insert(this); 554 555 // When asynchronous its possible for there to be no windows. To make sure 556 // Chrome doesn't prematurely exit AddRef the process. We'll release in the 557 // destructor when restore is done. 558 g_browser_process->AddRefModule(); 559 } 560 561 bool synchronous() const { return synchronous_; } 562 563 Browser* Restore() { 564 SessionService* session_service = 565 SessionServiceFactory::GetForProfile(profile_); 566 DCHECK(session_service); 567 session_service->GetLastSession( 568 base::Bind(&SessionRestoreImpl::OnGotSession, base::Unretained(this)), 569 &cancelable_task_tracker_); 570 571 if (synchronous_) { 572 { 573 base::MessageLoop::ScopedNestableTaskAllower allow( 574 base::MessageLoop::current()); 575 base::RunLoop loop; 576 quit_closure_for_sync_restore_ = loop.QuitClosure(); 577 loop.Run(); 578 quit_closure_for_sync_restore_ = base::Closure(); 579 } 580 Browser* browser = ProcessSessionWindows(&windows_, active_window_id_); 581 delete this; 582 content::NotificationService::current()->Notify( 583 chrome::NOTIFICATION_SESSION_RESTORE_DONE, 584 content::NotificationService::AllSources(), 585 content::NotificationService::NoDetails()); 586 return browser; 587 } 588 589 if (browser_) { 590 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, 591 content::Source<Browser>(browser_)); 592 } 593 594 return browser_; 595 } 596 597 // Restore window(s) from a foreign session. Returns newly created Browsers. 598 std::vector<Browser*> RestoreForeignSession( 599 std::vector<const SessionWindow*>::const_iterator begin, 600 std::vector<const SessionWindow*>::const_iterator end) { 601 StartTabCreation(); 602 std::vector<Browser*> browsers; 603 // Create a browser instance to put the restored tabs in. 604 for (std::vector<const SessionWindow*>::const_iterator i = begin; 605 i != end; ++i) { 606 Browser* browser = CreateRestoredBrowser( 607 static_cast<Browser::Type>((*i)->type), 608 (*i)->bounds, 609 (*i)->show_state, 610 (*i)->app_name); 611 browsers.push_back(browser); 612 613 // Restore and show the browser. 614 const int initial_tab_count = 0; 615 int selected_tab_index = std::max( 616 0, 617 std::min((*i)->selected_tab_index, 618 static_cast<int>((*i)->tabs.size()) - 1)); 619 RestoreTabsToBrowser(*(*i), browser, initial_tab_count, 620 selected_tab_index); 621 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count); 622 } 623 624 // Always create in a new window 625 FinishedTabCreation(true, true); 626 return browsers; 627 } 628 629 // Restore a single tab from a foreign session. 630 // Opens in the tab in the last active browser, unless disposition is 631 // NEW_WINDOW, in which case the tab will be opened in a new browser. Returns 632 // the WebContents of the restored tab. 633 WebContents* RestoreForeignTab(const SessionTab& tab, 634 WindowOpenDisposition disposition) { 635 DCHECK(!tab.navigations.empty()); 636 int selected_index = tab.current_navigation_index; 637 selected_index = std::max( 638 0, 639 std::min(selected_index, 640 static_cast<int>(tab.navigations.size() - 1))); 641 642 bool use_new_window = disposition == NEW_WINDOW; 643 644 Browser* browser = use_new_window ? 645 new Browser(Browser::CreateParams(profile_, host_desktop_type_)) : 646 browser_; 647 648 RecordAppLaunchForTab(browser, tab, selected_index); 649 650 WebContents* web_contents; 651 if (disposition == CURRENT_TAB) { 652 DCHECK(!use_new_window); 653 web_contents = chrome::ReplaceRestoredTab(browser, 654 tab.navigations, 655 selected_index, 656 true, 657 tab.extension_app_id, 658 NULL, 659 tab.user_agent_override); 660 } else { 661 int tab_index = 662 use_new_window ? 0 : browser->tab_strip_model()->active_index() + 1; 663 web_contents = chrome::AddRestoredTab( 664 browser, 665 tab.navigations, 666 tab_index, 667 selected_index, 668 tab.extension_app_id, 669 disposition == NEW_FOREGROUND_TAB, // selected 670 tab.pinned, 671 true, 672 NULL, 673 tab.user_agent_override); 674 // Start loading the tab immediately. 675 web_contents->GetController().LoadIfNecessary(); 676 } 677 678 if (use_new_window) { 679 browser->tab_strip_model()->ActivateTabAt(0, true); 680 browser->window()->Show(); 681 } 682 NotifySessionServiceOfRestoredTabs(browser, 683 browser->tab_strip_model()->count()); 684 685 // Since FinishedTabCreation() is not called here, |this| will leak if we 686 // are not in sychronous mode. 687 DCHECK(synchronous_); 688 return web_contents; 689 } 690 691 virtual ~SessionRestoreImpl() { 692 STLDeleteElements(&windows_); 693 694 active_session_restorers->erase(this); 695 if (active_session_restorers->empty()) { 696 delete active_session_restorers; 697 active_session_restorers = NULL; 698 } 699 700 g_browser_process->ReleaseModule(); 701 } 702 703 virtual void Observe(int type, 704 const content::NotificationSource& source, 705 const content::NotificationDetails& details) OVERRIDE { 706 switch (type) { 707 case chrome::NOTIFICATION_BROWSER_CLOSED: 708 delete this; 709 return; 710 711 default: 712 NOTREACHED(); 713 break; 714 } 715 } 716 717 Profile* profile() { return profile_; } 718 719 private: 720 // Invoked when beginning to create new tabs. Resets the tab_loader_. 721 void StartTabCreation() { 722 tab_loader_ = TabLoader::GetTabLoader(restore_started_); 723 } 724 725 // Invoked when done with creating all the tabs/browsers. 726 // 727 // |created_tabbed_browser| indicates whether a tabbed browser was created, 728 // or we used an existing tabbed browser. 729 // 730 // If successful, this begins loading tabs and deletes itself when all tabs 731 // have been loaded. 732 // 733 // Returns the Browser that was created, if any. 734 Browser* FinishedTabCreation(bool succeeded, bool created_tabbed_browser) { 735 Browser* browser = NULL; 736 if (!created_tabbed_browser && always_create_tabbed_browser_) { 737 browser = new Browser(Browser::CreateParams(profile_, 738 host_desktop_type_)); 739 if (urls_to_open_.empty()) { 740 // No tab browsers were created and no URLs were supplied on the command 741 // line. Open the new tab page. 742 urls_to_open_.push_back(GURL(chrome::kChromeUINewTabURL)); 743 } 744 AppendURLsToBrowser(browser, urls_to_open_); 745 browser->window()->Show(); 746 } 747 748 if (succeeded) { 749 DCHECK(tab_loader_.get()); 750 // TabLoader deletes itself when done loading. 751 tab_loader_->StartLoading(); 752 tab_loader_ = NULL; 753 } 754 755 if (!synchronous_) { 756 // If we're not synchronous we need to delete ourself. 757 // NOTE: we must use DeleteLater here as most likely we're in a callback 758 // from the history service which doesn't deal well with deleting the 759 // object it is notifying. 760 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 761 762 // The delete may take a while and at this point we no longer care about 763 // if the browser is deleted. Don't listen to anything. This avoid a 764 // possible double delete too (if browser is closed before DeleteSoon() is 765 // processed). 766 registrar_.RemoveAll(); 767 } 768 769 #if defined(OS_CHROMEOS) 770 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 771 "SessionRestore-End", false); 772 #endif 773 return browser; 774 } 775 776 void OnGotSession(ScopedVector<SessionWindow> windows, 777 SessionID::id_type active_window_id) { 778 base::TimeDelta time_to_got_sessions = 779 base::TimeTicks::Now() - restore_started_; 780 UMA_HISTOGRAM_CUSTOM_TIMES( 781 "SessionRestore.TimeToGotSessions", 782 time_to_got_sessions, 783 base::TimeDelta::FromMilliseconds(10), 784 base::TimeDelta::FromSeconds(1000), 785 100); 786 #if defined(OS_CHROMEOS) 787 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 788 "SessionRestore-GotSession", false); 789 #endif 790 if (synchronous_) { 791 // See comment above windows_ as to why we don't process immediately. 792 windows_.swap(windows.get()); 793 active_window_id_ = active_window_id; 794 CHECK(!quit_closure_for_sync_restore_.is_null()); 795 quit_closure_for_sync_restore_.Run(); 796 return; 797 } 798 799 ProcessSessionWindows(&windows.get(), active_window_id); 800 } 801 802 Browser* ProcessSessionWindows(std::vector<SessionWindow*>* windows, 803 SessionID::id_type active_window_id) { 804 VLOG(1) << "ProcessSessionWindows " << windows->size(); 805 base::TimeDelta time_to_process_sessions = 806 base::TimeTicks::Now() - restore_started_; 807 UMA_HISTOGRAM_CUSTOM_TIMES( 808 "SessionRestore.TimeToProcessSessions", 809 time_to_process_sessions, 810 base::TimeDelta::FromMilliseconds(10), 811 base::TimeDelta::FromSeconds(1000), 812 100); 813 814 if (windows->empty()) { 815 // Restore was unsuccessful. The DOM storage system can also delete its 816 // data, since no session restore will happen at a later point in time. 817 content::BrowserContext::GetDefaultStoragePartition(profile_)-> 818 GetDOMStorageContext()->StartScavengingUnusedSessionStorage(); 819 return FinishedTabCreation(false, false); 820 } 821 822 #if defined(OS_CHROMEOS) 823 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 824 "SessionRestore-CreatingTabs-Start", false); 825 #endif 826 StartTabCreation(); 827 828 // After the for loop this contains the last TABBED_BROWSER. Is null if no 829 // tabbed browsers exist. 830 Browser* last_browser = NULL; 831 bool has_tabbed_browser = false; 832 833 // After the for loop, this contains the browser to activate, if one of the 834 // windows has the same id as specified in active_window_id. 835 Browser* browser_to_activate = NULL; 836 #if defined(OS_WIN) 837 int selected_tab_to_activate = -1; 838 #endif 839 840 // Determine if there is a visible window. 841 bool has_visible_browser = false; 842 for (std::vector<SessionWindow*>::iterator i = windows->begin(); 843 i != windows->end(); ++i) { 844 if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED) 845 has_visible_browser = true; 846 } 847 848 for (std::vector<SessionWindow*>::iterator i = windows->begin(); 849 i != windows->end(); ++i) { 850 Browser* browser = NULL; 851 if (!has_tabbed_browser && (*i)->type == Browser::TYPE_TABBED) 852 has_tabbed_browser = true; 853 if (i == windows->begin() && (*i)->type == Browser::TYPE_TABBED && 854 browser_ && browser_->is_type_tabbed() && 855 !browser_->profile()->IsOffTheRecord()) { 856 // The first set of tabs is added to the existing browser. 857 browser = browser_; 858 } else { 859 #if defined(OS_CHROMEOS) 860 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 861 "SessionRestore-CreateRestoredBrowser-Start", false); 862 #endif 863 // Show the first window if none are visible. 864 ui::WindowShowState show_state = (*i)->show_state; 865 if (!has_visible_browser) { 866 show_state = ui::SHOW_STATE_NORMAL; 867 has_visible_browser = true; 868 } 869 browser = CreateRestoredBrowser( 870 static_cast<Browser::Type>((*i)->type), 871 (*i)->bounds, 872 show_state, 873 (*i)->app_name); 874 #if defined(OS_CHROMEOS) 875 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 876 "SessionRestore-CreateRestoredBrowser-End", false); 877 #endif 878 } 879 if ((*i)->type == Browser::TYPE_TABBED) 880 last_browser = browser; 881 WebContents* active_tab = 882 browser->tab_strip_model()->GetActiveWebContents(); 883 int initial_tab_count = browser->tab_strip_model()->count(); 884 bool close_active_tab = clobber_existing_tab_ && 885 i == windows->begin() && 886 (*i)->type == Browser::TYPE_TABBED && 887 active_tab && browser == browser_ && 888 (*i)->tabs.size() > 0; 889 if (close_active_tab) 890 --initial_tab_count; 891 int selected_tab_index = 892 initial_tab_count > 0 ? browser->tab_strip_model()->active_index() 893 : std::max(0, 894 std::min((*i)->selected_tab_index, 895 static_cast<int>((*i)->tabs.size()) - 1)); 896 if ((*i)->window_id.id() == active_window_id) { 897 browser_to_activate = browser; 898 #if defined(OS_WIN) 899 selected_tab_to_activate = selected_tab_index; 900 #endif 901 } 902 RestoreTabsToBrowser(*(*i), browser, initial_tab_count, 903 selected_tab_index); 904 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count); 905 // This needs to be done after restore because closing the last tab will 906 // close the whole window. 907 if (close_active_tab) 908 chrome::CloseWebContents(browser, active_tab, true); 909 #if defined(OS_WIN) 910 selected_tab_to_activate = -1; 911 #endif 912 } 913 914 if (browser_to_activate && browser_to_activate->is_type_tabbed()) 915 last_browser = browser_to_activate; 916 917 if (last_browser && !urls_to_open_.empty()) 918 AppendURLsToBrowser(last_browser, urls_to_open_); 919 #if defined(OS_CHROMEOS) 920 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 921 "SessionRestore-CreatingTabs-End", false); 922 #endif 923 if (browser_to_activate) 924 browser_to_activate->window()->Activate(); 925 926 // If last_browser is NULL and urls_to_open_ is non-empty, 927 // FinishedTabCreation will create a new TabbedBrowser and add the urls to 928 // it. 929 Browser* finished_browser = FinishedTabCreation(true, has_tabbed_browser); 930 if (finished_browser) 931 last_browser = finished_browser; 932 933 // sessionStorages needed for the session restore have now been recreated 934 // by RestoreTab. Now it's safe for the DOM storage system to start 935 // deleting leftover data. 936 content::BrowserContext::GetDefaultStoragePartition(profile_)-> 937 GetDOMStorageContext()->StartScavengingUnusedSessionStorage(); 938 return last_browser; 939 } 940 941 // Record an app launch event (if appropriate) for a tab which is about to 942 // be restored. Callers should ensure that selected_index is within the 943 // bounds of tab.navigations before calling. 944 void RecordAppLaunchForTab(Browser* browser, 945 const SessionTab& tab, 946 int selected_index) { 947 DCHECK(selected_index >= 0 && 948 selected_index < static_cast<int>(tab.navigations.size())); 949 GURL url = tab.navigations[selected_index].virtual_url(); 950 const extensions::Extension* extension = 951 extensions::ExtensionRegistry::Get(profile()) 952 ->enabled_extensions().GetAppByURL(url); 953 if (extension) { 954 CoreAppLauncherHandler::RecordAppLaunchType( 955 extension_misc::APP_LAUNCH_SESSION_RESTORE, 956 extension->GetType()); 957 } 958 } 959 960 // Adds the tabs from |window| to |browser|. Normal tabs go after the existing 961 // tabs but pinned tabs will be pushed in front. 962 // If there are no existing tabs, the tab at |selected_tab_index| will be 963 // selected. Otherwise, the tab selection will remain untouched. 964 void RestoreTabsToBrowser(const SessionWindow& window, 965 Browser* browser, 966 int initial_tab_count, 967 int selected_tab_index) { 968 VLOG(1) << "RestoreTabsToBrowser " << window.tabs.size(); 969 DCHECK(!window.tabs.empty()); 970 if (initial_tab_count == 0) { 971 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) { 972 const SessionTab& tab = *(window.tabs[i]); 973 974 // Loads are scheduled for each restored tab unless the tab is going to 975 // be selected as ShowBrowser() will load the selected tab. 976 bool is_not_selected_tab = (i != selected_tab_index); 977 WebContents* restored_tab = 978 RestoreTab(tab, i, browser, is_not_selected_tab); 979 980 // RestoreTab can return NULL if |tab| doesn't have valid data. 981 if (!restored_tab) 982 continue; 983 984 // If this isn't the selected tab, there's nothing else to do. 985 if (is_not_selected_tab) 986 continue; 987 988 ShowBrowser( 989 browser, 990 browser->tab_strip_model()->GetIndexOfWebContents(restored_tab)); 991 // TODO(sky): remove. For debugging 368236. 992 CHECK_EQ(browser->tab_strip_model()->GetActiveWebContents(), 993 restored_tab); 994 tab_loader_->TabIsLoading(&browser->tab_strip_model() 995 ->GetActiveWebContents() 996 ->GetController()); 997 } 998 } else { 999 // If the browser already has tabs, we want to restore the new ones after 1000 // the existing ones. E.g. this happens in Win8 Metro where we merge 1001 // windows or when launching a hosted app from the app launcher. 1002 int tab_index_offset = initial_tab_count; 1003 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) { 1004 const SessionTab& tab = *(window.tabs[i]); 1005 // Always schedule loads as we will not be calling ShowBrowser(). 1006 RestoreTab(tab, tab_index_offset + i, browser, true); 1007 } 1008 } 1009 } 1010 1011 // |tab_index| is ignored for pinned tabs which will always be pushed behind 1012 // the last existing pinned tab. 1013 // |schedule_load| will let |tab_loader_| know that it should schedule this 1014 // tab for loading. 1015 WebContents* RestoreTab(const SessionTab& tab, 1016 const int tab_index, 1017 Browser* browser, 1018 bool schedule_load) { 1019 // It's possible (particularly for foreign sessions) to receive a tab 1020 // without valid navigations. In that case, just skip it. 1021 // See crbug.com/154129. 1022 if (tab.navigations.empty()) 1023 return NULL; 1024 int selected_index = tab.current_navigation_index; 1025 selected_index = std::max( 1026 0, 1027 std::min(selected_index, 1028 static_cast<int>(tab.navigations.size() - 1))); 1029 1030 RecordAppLaunchForTab(browser, tab, selected_index); 1031 1032 // Associate sessionStorage (if any) to the restored tab. 1033 scoped_refptr<content::SessionStorageNamespace> session_storage_namespace; 1034 if (!tab.session_storage_persistent_id.empty()) { 1035 session_storage_namespace = 1036 content::BrowserContext::GetDefaultStoragePartition(profile_)-> 1037 GetDOMStorageContext()->RecreateSessionStorage( 1038 tab.session_storage_persistent_id); 1039 } 1040 1041 WebContents* web_contents = 1042 chrome::AddRestoredTab(browser, 1043 tab.navigations, 1044 tab_index, 1045 selected_index, 1046 tab.extension_app_id, 1047 false, // select 1048 tab.pinned, 1049 true, 1050 session_storage_namespace.get(), 1051 tab.user_agent_override); 1052 // Regression check: check that the tab didn't start loading right away. The 1053 // focused tab will be loaded by Browser, and TabLoader will load the rest. 1054 DCHECK(web_contents->GetController().NeedsReload()); 1055 1056 // Set up the file access rights for the selected navigation entry. 1057 const int id = web_contents->GetRenderProcessHost()->GetID(); 1058 const content::PageState& page_state = 1059 tab.navigations.at(selected_index).page_state(); 1060 const std::vector<base::FilePath>& file_paths = 1061 page_state.GetReferencedFiles(); 1062 for (std::vector<base::FilePath>::const_iterator file = file_paths.begin(); 1063 file != file_paths.end(); ++file) { 1064 content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(id, 1065 *file); 1066 } 1067 1068 if (schedule_load) 1069 tab_loader_->ScheduleLoad(&web_contents->GetController()); 1070 return web_contents; 1071 } 1072 1073 Browser* CreateRestoredBrowser(Browser::Type type, 1074 gfx::Rect bounds, 1075 ui::WindowShowState show_state, 1076 const std::string& app_name) { 1077 Browser::CreateParams params(type, profile_, host_desktop_type_); 1078 if (!app_name.empty()) { 1079 const bool trusted_source = true; // We only store trusted app windows. 1080 params = Browser::CreateParams::CreateForApp(app_name, 1081 trusted_source, 1082 bounds, 1083 profile_, 1084 host_desktop_type_); 1085 } else { 1086 params.initial_bounds = bounds; 1087 } 1088 params.initial_show_state = show_state; 1089 params.is_session_restore = true; 1090 return new Browser(params); 1091 } 1092 1093 void ShowBrowser(Browser* browser, int selected_tab_index) { 1094 DCHECK(browser); 1095 DCHECK(browser->tab_strip_model()->count()); 1096 browser->tab_strip_model()->ActivateTabAt(selected_tab_index, true); 1097 1098 if (browser_ == browser) 1099 return; 1100 1101 browser->window()->Show(); 1102 browser->set_is_session_restore(false); 1103 1104 // TODO(jcampan): http://crbug.com/8123 we should not need to set the 1105 // initial focus explicitly. 1106 browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus(); 1107 1108 if (!browser_shown_) { 1109 browser_shown_ = true; 1110 base::TimeDelta time_to_first_show = 1111 base::TimeTicks::Now() - restore_started_; 1112 UMA_HISTOGRAM_CUSTOM_TIMES( 1113 "SessionRestore.TimeToFirstShow", 1114 time_to_first_show, 1115 base::TimeDelta::FromMilliseconds(10), 1116 base::TimeDelta::FromSeconds(1000), 1117 100); 1118 } 1119 } 1120 1121 // Appends the urls in |urls| to |browser|. 1122 void AppendURLsToBrowser(Browser* browser, 1123 const std::vector<GURL>& urls) { 1124 for (size_t i = 0; i < urls.size(); ++i) { 1125 int add_types = TabStripModel::ADD_FORCE_INDEX; 1126 if (i == 0) 1127 add_types |= TabStripModel::ADD_ACTIVE; 1128 chrome::NavigateParams params(browser, urls[i], 1129 content::PAGE_TRANSITION_AUTO_TOPLEVEL); 1130 params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; 1131 params.tabstrip_add_types = add_types; 1132 chrome::Navigate(¶ms); 1133 } 1134 } 1135 1136 // Invokes TabRestored on the SessionService for all tabs in browser after 1137 // initial_count. 1138 void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) { 1139 SessionService* session_service = 1140 SessionServiceFactory::GetForProfile(profile_); 1141 if (!session_service) 1142 return; 1143 TabStripModel* tab_strip = browser->tab_strip_model(); 1144 for (int i = initial_count; i < tab_strip->count(); ++i) 1145 session_service->TabRestored(tab_strip->GetWebContentsAt(i), 1146 tab_strip->IsTabPinned(i)); 1147 } 1148 1149 // The profile to create the sessions for. 1150 Profile* profile_; 1151 1152 // The first browser to restore to, may be null. 1153 Browser* browser_; 1154 1155 // The desktop on which all new browsers should be created (browser_, if it is 1156 // not NULL, must be of this desktop type as well). 1157 chrome::HostDesktopType host_desktop_type_; 1158 1159 // Whether or not restore is synchronous. 1160 const bool synchronous_; 1161 1162 // The quit-closure to terminate the nested message-loop started for 1163 // synchronous session-restore. 1164 base::Closure quit_closure_for_sync_restore_; 1165 1166 // See description of CLOBBER_CURRENT_TAB. 1167 const bool clobber_existing_tab_; 1168 1169 // If true and there is an error or there are no windows to restore, we 1170 // create a tabbed browser anyway. This is used on startup to make sure at 1171 // at least one window is created. 1172 const bool always_create_tabbed_browser_; 1173 1174 // Set of URLs to open in addition to those restored from the session. 1175 std::vector<GURL> urls_to_open_; 1176 1177 // Used to get the session. 1178 base::CancelableTaskTracker cancelable_task_tracker_; 1179 1180 // Responsible for loading the tabs. 1181 scoped_refptr<TabLoader> tab_loader_; 1182 1183 // When synchronous we run a nested message loop. To avoid creating windows 1184 // from the nested message loop (which can make exiting the nested message 1185 // loop take a while) we cache the SessionWindows here and create the actual 1186 // windows when the nested message loop exits. 1187 std::vector<SessionWindow*> windows_; 1188 SessionID::id_type active_window_id_; 1189 1190 content::NotificationRegistrar registrar_; 1191 1192 // The time we started the restore. 1193 base::TimeTicks restore_started_; 1194 1195 // Set to true after the first browser is shown. 1196 bool browser_shown_; 1197 1198 DISALLOW_COPY_AND_ASSIGN(SessionRestoreImpl); 1199 }; 1200 1201 } // namespace 1202 1203 // SessionRestore ------------------------------------------------------------- 1204 1205 // static 1206 Browser* SessionRestore::RestoreSession( 1207 Profile* profile, 1208 Browser* browser, 1209 chrome::HostDesktopType host_desktop_type, 1210 uint32 behavior, 1211 const std::vector<GURL>& urls_to_open) { 1212 #if defined(OS_CHROMEOS) 1213 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 1214 "SessionRestore-Start", false); 1215 #endif 1216 DCHECK(profile); 1217 // Always restore from the original profile (incognito profiles have no 1218 // session service). 1219 profile = profile->GetOriginalProfile(); 1220 if (!SessionServiceFactory::GetForProfile(profile)) { 1221 NOTREACHED(); 1222 return NULL; 1223 } 1224 profile->set_restored_last_session(true); 1225 // SessionRestoreImpl takes care of deleting itself when done. 1226 SessionRestoreImpl* restorer = new SessionRestoreImpl( 1227 profile, browser, host_desktop_type, (behavior & SYNCHRONOUS) != 0, 1228 (behavior & CLOBBER_CURRENT_TAB) != 0, 1229 (behavior & ALWAYS_CREATE_TABBED_BROWSER) != 0, 1230 urls_to_open); 1231 return restorer->Restore(); 1232 } 1233 1234 // static 1235 void SessionRestore::RestoreSessionAfterCrash(Browser* browser) { 1236 uint32 behavior = 0; 1237 if (browser->tab_strip_model()->count() == 1) { 1238 const content::WebContents* active_tab = 1239 browser->tab_strip_model()->GetWebContentsAt(0); 1240 if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) || 1241 chrome::IsInstantNTP(active_tab)) { 1242 // There is only one tab and its the new tab page, make session restore 1243 // clobber it. 1244 behavior = SessionRestore::CLOBBER_CURRENT_TAB; 1245 } 1246 } 1247 SessionRestore::RestoreSession(browser->profile(), browser, 1248 browser->host_desktop_type(), behavior, 1249 std::vector<GURL>()); 1250 } 1251 1252 // static 1253 std::vector<Browser*> SessionRestore::RestoreForeignSessionWindows( 1254 Profile* profile, 1255 chrome::HostDesktopType host_desktop_type, 1256 std::vector<const SessionWindow*>::const_iterator begin, 1257 std::vector<const SessionWindow*>::const_iterator end) { 1258 std::vector<GURL> gurls; 1259 SessionRestoreImpl restorer(profile, 1260 static_cast<Browser*>(NULL), host_desktop_type, true, false, true, gurls); 1261 return restorer.RestoreForeignSession(begin, end); 1262 } 1263 1264 // static 1265 WebContents* SessionRestore::RestoreForeignSessionTab( 1266 content::WebContents* source_web_contents, 1267 const SessionTab& tab, 1268 WindowOpenDisposition disposition) { 1269 Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents); 1270 Profile* profile = browser->profile(); 1271 std::vector<GURL> gurls; 1272 SessionRestoreImpl restorer(profile, browser, browser->host_desktop_type(), 1273 true, false, false, gurls); 1274 return restorer.RestoreForeignTab(tab, disposition); 1275 } 1276 1277 // static 1278 bool SessionRestore::IsRestoring(const Profile* profile) { 1279 if (active_session_restorers == NULL) 1280 return false; 1281 for (std::set<SessionRestoreImpl*>::const_iterator it = 1282 active_session_restorers->begin(); 1283 it != active_session_restorers->end(); ++it) { 1284 if ((*it)->profile() == profile) 1285 return true; 1286 } 1287 return false; 1288 } 1289 1290 // static 1291 bool SessionRestore::IsRestoringSynchronously() { 1292 if (!active_session_restorers) 1293 return false; 1294 for (std::set<SessionRestoreImpl*>::const_iterator it = 1295 active_session_restorers->begin(); 1296 it != active_session_restorers->end(); ++it) { 1297 if ((*it)->synchronous()) 1298 return true; 1299 } 1300 return false; 1301 } 1302