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