1 // Copyright (c) 2011 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 <vector> 11 12 #include "base/callback.h" 13 #include "base/command_line.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/metrics/histogram.h" 16 #include "base/stl_util-inl.h" 17 #include "base/string_util.h" 18 #include "chrome/browser/extensions/extension_service.h" 19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/sessions/session_service.h" 21 #include "chrome/browser/sessions/session_types.h" 22 #include "chrome/browser/tabs/tab_strip_model.h" 23 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser_list.h" 25 #include "chrome/browser/ui/browser_navigator.h" 26 #include "chrome/browser/ui/browser_window.h" 27 #include "content/browser/renderer_host/render_widget_host.h" 28 #include "content/browser/renderer_host/render_widget_host_view.h" 29 #include "content/browser/tab_contents/navigation_controller.h" 30 #include "content/browser/tab_contents/tab_contents.h" 31 #include "content/browser/tab_contents/tab_contents_view.h" 32 #include "content/common/notification_registrar.h" 33 #include "content/common/notification_service.h" 34 35 #if defined(OS_CHROMEOS) 36 #include "chrome/browser/chromeos/boot_times_loader.h" 37 #include "chrome/browser/chromeos/network_state_notifier.h" 38 #endif 39 40 // Are we in the process of restoring? 41 static bool restoring = false; 42 43 namespace { 44 45 // TabLoader ------------------------------------------------------------------ 46 47 // Initial delay (see class decription for details). 48 static const int kInitialDelayTimerMS = 100; 49 50 // TabLoader is responsible for loading tabs after session restore creates 51 // tabs. New tabs are loaded after the current tab finishes loading, or a delay 52 // is reached (initially kInitialDelayTimerMS). If the delay is reached before 53 // a tab finishes loading a new tab is loaded and the time of the delay 54 // doubled. When all tabs are loading TabLoader deletes itself. 55 // 56 // This is not part of SessionRestoreImpl so that synchronous destruction 57 // of SessionRestoreImpl doesn't have timing problems. 58 class TabLoader : public NotificationObserver { 59 public: 60 explicit TabLoader(base::TimeTicks restore_started); 61 ~TabLoader(); 62 63 // Schedules a tab for loading. 64 void ScheduleLoad(NavigationController* controller); 65 66 // Notifies the loader that a tab has been scheduled for loading through 67 // some other mechanism. 68 void TabIsLoading(NavigationController* controller); 69 70 // Invokes |LoadNextTab| to load a tab. 71 // 72 // This must be invoked once to start loading. 73 void StartLoading(); 74 75 private: 76 typedef std::set<NavigationController*> TabsLoading; 77 typedef std::list<NavigationController*> TabsToLoad; 78 typedef std::set<RenderWidgetHost*> RenderWidgetHostSet; 79 80 // Loads the next tab. If there are no more tabs to load this deletes itself, 81 // otherwise |force_load_timer_| is restarted. 82 void LoadNextTab(); 83 84 // NotificationObserver method. Removes the specified tab and loads the next 85 // tab. 86 virtual void Observe(NotificationType type, 87 const NotificationSource& source, 88 const NotificationDetails& details); 89 90 // Removes the listeners from the specified tab and removes the tab from 91 // the set of tabs to load and list of tabs we're waiting to get a load 92 // from. 93 void RemoveTab(NavigationController* tab); 94 95 // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes 96 // |LoadNextTab| to load the next tab 97 void ForceLoadTimerFired(); 98 99 // Returns the RenderWidgetHost associated with a tab if there is one, 100 // NULL otherwise. 101 static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab); 102 103 // Register for necessary notificaitons on a tab navigation controller. 104 void RegisterForNotifications(NavigationController* controller); 105 106 // Called when a tab goes away or a load completes. 107 void HandleTabClosedOrLoaded(NavigationController* controller); 108 109 NotificationRegistrar registrar_; 110 111 // Current delay before a new tab is loaded. See class description for 112 // details. 113 int64 force_load_delay_; 114 115 // Has Load been invoked? 116 bool loading_; 117 118 // Have we recorded the times for a tab paint? 119 bool got_first_paint_; 120 121 // The set of tabs we've initiated loading on. This does NOT include the 122 // selected tabs. 123 TabsLoading tabs_loading_; 124 125 // The tabs we need to load. 126 TabsToLoad tabs_to_load_; 127 128 // The renderers we have started loading into. 129 RenderWidgetHostSet render_widget_hosts_loading_; 130 131 // The renderers we have loaded and are waiting on to paint. 132 RenderWidgetHostSet render_widget_hosts_to_paint_; 133 134 // The number of tabs that have been restored. 135 int tab_count_; 136 137 base::OneShotTimer<TabLoader> force_load_timer_; 138 139 // The time the restore process started. 140 base::TimeTicks restore_started_; 141 142 DISALLOW_COPY_AND_ASSIGN(TabLoader); 143 }; 144 145 TabLoader::TabLoader(base::TimeTicks restore_started) 146 : force_load_delay_(kInitialDelayTimerMS), 147 loading_(false), 148 got_first_paint_(false), 149 tab_count_(0), 150 restore_started_(restore_started) { 151 } 152 153 TabLoader::~TabLoader() { 154 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 155 tabs_loading_.empty() && tabs_to_load_.empty()); 156 } 157 158 void TabLoader::ScheduleLoad(NavigationController* controller) { 159 DCHECK(controller); 160 DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) == 161 tabs_to_load_.end()); 162 tabs_to_load_.push_back(controller); 163 RegisterForNotifications(controller); 164 } 165 166 void TabLoader::TabIsLoading(NavigationController* controller) { 167 DCHECK(controller); 168 DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) == 169 tabs_loading_.end()); 170 tabs_loading_.insert(controller); 171 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller); 172 DCHECK(render_widget_host); 173 render_widget_hosts_loading_.insert(render_widget_host); 174 RegisterForNotifications(controller); 175 } 176 177 void TabLoader::StartLoading() { 178 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DID_PAINT, 179 NotificationService::AllSources()); 180 #if defined(OS_CHROMEOS) 181 if (chromeos::NetworkStateNotifier::is_connected()) { 182 loading_ = true; 183 LoadNextTab(); 184 } else { 185 // Start listening to network state notification now. 186 registrar_.Add(this, NotificationType::NETWORK_STATE_CHANGED, 187 NotificationService::AllSources()); 188 } 189 #else 190 loading_ = true; 191 LoadNextTab(); 192 #endif 193 } 194 195 void TabLoader::LoadNextTab() { 196 if (!tabs_to_load_.empty()) { 197 NavigationController* tab = tabs_to_load_.front(); 198 DCHECK(tab); 199 tabs_loading_.insert(tab); 200 tabs_to_load_.pop_front(); 201 tab->LoadIfNecessary(); 202 if (tab->tab_contents()) { 203 int tab_index; 204 Browser* browser = Browser::GetBrowserForController(tab, &tab_index); 205 if (browser && browser->active_index() != tab_index) { 206 // By default tabs are marked as visible. As only the active tab is 207 // visible we need to explicitly tell non-active tabs they are hidden. 208 // Without this call non-active tabs are not marked as backgrounded. 209 // 210 // NOTE: We need to do this here rather than when the tab is added to 211 // the Browser as at that time not everything has been created, so that 212 // the call would do nothing. 213 tab->tab_contents()->WasHidden(); 214 } 215 } 216 } 217 218 if (!tabs_to_load_.empty()) { 219 force_load_timer_.Stop(); 220 // Each time we load a tab we also set a timer to force us to start loading 221 // the next tab if this one doesn't load quickly enough. 222 force_load_timer_.Start( 223 base::TimeDelta::FromMilliseconds(force_load_delay_), 224 this, &TabLoader::ForceLoadTimerFired); 225 } 226 } 227 228 void TabLoader::Observe(NotificationType type, 229 const NotificationSource& source, 230 const NotificationDetails& details) { 231 switch (type.value) { 232 #if defined(OS_CHROMEOS) 233 case NotificationType::NETWORK_STATE_CHANGED: { 234 chromeos::NetworkStateDetails* state_details = 235 Details<chromeos::NetworkStateDetails>(details).ptr(); 236 switch (state_details->state()) { 237 case chromeos::NetworkStateDetails::CONNECTED: 238 if (!loading_) { 239 loading_ = true; 240 LoadNextTab(); 241 } 242 // Start loading 243 break; 244 case chromeos::NetworkStateDetails::CONNECTING: 245 case chromeos::NetworkStateDetails::DISCONNECTED: 246 // Disconnected while loading. Set loading_ false so 247 // that it stops trying to load next tab. 248 loading_ = false; 249 break; 250 default: 251 NOTREACHED() << "Unknown nework state notification:" 252 << state_details->state(); 253 } 254 break; 255 } 256 #endif 257 case NotificationType::LOAD_START: { 258 // Add this render_widget_host to the set of those we're waiting for 259 // paints on. We want to only record stats for paints that occur after 260 // a load has finished. 261 NavigationController* tab = Source<NavigationController>(source).ptr(); 262 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); 263 DCHECK(render_widget_host); 264 render_widget_hosts_loading_.insert(render_widget_host); 265 break; 266 } 267 case NotificationType::TAB_CONTENTS_DESTROYED: { 268 TabContents* tab_contents = Source<TabContents>(source).ptr(); 269 if (!got_first_paint_) { 270 RenderWidgetHost* render_widget_host = 271 GetRenderWidgetHost(&tab_contents->controller()); 272 render_widget_hosts_loading_.erase(render_widget_host); 273 } 274 HandleTabClosedOrLoaded(&tab_contents->controller()); 275 break; 276 } 277 case NotificationType::LOAD_STOP: { 278 NavigationController* tab = Source<NavigationController>(source).ptr(); 279 render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab)); 280 HandleTabClosedOrLoaded(tab); 281 break; 282 } 283 case NotificationType::RENDER_WIDGET_HOST_DID_PAINT: { 284 if (!got_first_paint_) { 285 RenderWidgetHost* render_widget_host = 286 Source<RenderWidgetHost>(source).ptr(); 287 if (render_widget_hosts_to_paint_.find(render_widget_host) != 288 render_widget_hosts_to_paint_.end()) { 289 // Got a paint for one of our renderers, so record time. 290 got_first_paint_ = true; 291 base::TimeDelta time_to_paint = 292 base::TimeTicks::Now() - restore_started_; 293 UMA_HISTOGRAM_CUSTOM_TIMES( 294 "SessionRestore.FirstTabPainted", 295 time_to_paint, 296 base::TimeDelta::FromMilliseconds(10), 297 base::TimeDelta::FromSeconds(100), 298 100); 299 // Record a time for the number of tabs, to help track down 300 // contention. 301 std::string time_for_count = 302 StringPrintf("SessionRestore.FirstTabPainted_%d", tab_count_); 303 base::Histogram* counter_for_count = 304 base::Histogram::FactoryTimeGet( 305 time_for_count, 306 base::TimeDelta::FromMilliseconds(10), 307 base::TimeDelta::FromSeconds(100), 308 100, 309 base::Histogram::kUmaTargetedHistogramFlag); 310 counter_for_count->AddTime(time_to_paint); 311 } else if (render_widget_hosts_loading_.find(render_widget_host) == 312 render_widget_hosts_loading_.end()) { 313 // If this is a host for a tab we're not loading some other tab 314 // has rendered and there's no point tracking the time. This could 315 // happen because the user opened a different tab or restored tabs 316 // to an already existing browser and an existing tab painted. 317 got_first_paint_ = true; 318 } 319 } 320 break; 321 } 322 default: 323 NOTREACHED() << "Unknown notification received:" << type.value; 324 } 325 // Delete ourselves when we're not waiting for any more notifications. 326 if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && 327 tabs_loading_.empty() && tabs_to_load_.empty()) 328 delete this; 329 } 330 331 void TabLoader::RemoveTab(NavigationController* tab) { 332 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, 333 Source<TabContents>(tab->tab_contents())); 334 registrar_.Remove(this, NotificationType::LOAD_STOP, 335 Source<NavigationController>(tab)); 336 registrar_.Remove(this, NotificationType::LOAD_START, 337 Source<NavigationController>(tab)); 338 339 TabsLoading::iterator i = tabs_loading_.find(tab); 340 if (i != tabs_loading_.end()) 341 tabs_loading_.erase(i); 342 343 TabsToLoad::iterator j = 344 find(tabs_to_load_.begin(), tabs_to_load_.end(), tab); 345 if (j != tabs_to_load_.end()) 346 tabs_to_load_.erase(j); 347 } 348 349 void TabLoader::ForceLoadTimerFired() { 350 force_load_delay_ *= 2; 351 LoadNextTab(); 352 } 353 354 RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) { 355 TabContents* tab_contents = tab->tab_contents(); 356 if (tab_contents) { 357 RenderWidgetHostView* render_widget_host_view = 358 tab_contents->GetRenderWidgetHostView(); 359 if (render_widget_host_view) 360 return render_widget_host_view->GetRenderWidgetHost(); 361 } 362 return NULL; 363 } 364 365 void TabLoader::RegisterForNotifications(NavigationController* controller) { 366 registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, 367 Source<TabContents>(controller->tab_contents())); 368 registrar_.Add(this, NotificationType::LOAD_STOP, 369 Source<NavigationController>(controller)); 370 registrar_.Add(this, NotificationType::LOAD_START, 371 Source<NavigationController>(controller)); 372 ++tab_count_; 373 } 374 375 void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) { 376 RemoveTab(tab); 377 if (loading_) 378 LoadNextTab(); 379 if (tabs_loading_.empty() && tabs_to_load_.empty()) { 380 base::TimeDelta time_to_load = 381 base::TimeTicks::Now() - restore_started_; 382 UMA_HISTOGRAM_CUSTOM_TIMES( 383 "SessionRestore.AllTabsLoaded", 384 time_to_load, 385 base::TimeDelta::FromMilliseconds(10), 386 base::TimeDelta::FromSeconds(100), 387 100); 388 // Record a time for the number of tabs, to help track down contention. 389 std::string time_for_count = 390 StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_); 391 base::Histogram* counter_for_count = 392 base::Histogram::FactoryTimeGet( 393 time_for_count, 394 base::TimeDelta::FromMilliseconds(10), 395 base::TimeDelta::FromSeconds(100), 396 100, 397 base::Histogram::kUmaTargetedHistogramFlag); 398 counter_for_count->AddTime(time_to_load); 399 } 400 } 401 402 // SessionRestoreImpl --------------------------------------------------------- 403 404 // SessionRestoreImpl is responsible for fetching the set of tabs to create 405 // from SessionService. SessionRestoreImpl deletes itself when done. 406 407 class SessionRestoreImpl : public NotificationObserver { 408 public: 409 SessionRestoreImpl(Profile* profile, 410 Browser* browser, 411 bool synchronous, 412 bool clobber_existing_window, 413 bool always_create_tabbed_browser, 414 const std::vector<GURL>& urls_to_open) 415 : profile_(profile), 416 browser_(browser), 417 synchronous_(synchronous), 418 clobber_existing_window_(clobber_existing_window), 419 always_create_tabbed_browser_(always_create_tabbed_browser), 420 urls_to_open_(urls_to_open), 421 restore_started_(base::TimeTicks::Now()) { 422 } 423 424 Browser* Restore() { 425 SessionService* session_service = profile_->GetSessionService(); 426 DCHECK(session_service); 427 SessionService::SessionCallback* callback = 428 NewCallback(this, &SessionRestoreImpl::OnGotSession); 429 session_service->GetLastSession(&request_consumer_, callback); 430 431 if (synchronous_) { 432 bool old_state = MessageLoop::current()->NestableTasksAllowed(); 433 MessageLoop::current()->SetNestableTasksAllowed(true); 434 MessageLoop::current()->Run(); 435 MessageLoop::current()->SetNestableTasksAllowed(old_state); 436 Browser* browser = ProcessSessionWindows(&windows_); 437 delete this; 438 return browser; 439 } 440 441 if (browser_) { 442 registrar_.Add(this, NotificationType::BROWSER_CLOSED, 443 Source<Browser>(browser_)); 444 } 445 446 return browser_; 447 } 448 449 // Restore window(s) from a foreign session. 450 void RestoreForeignSession( 451 std::vector<SessionWindow*>::const_iterator begin, 452 std::vector<SessionWindow*>::const_iterator end) { 453 StartTabCreation(); 454 // Create a browser instance to put the restored tabs in. 455 for (std::vector<SessionWindow*>::const_iterator i = begin; 456 i != end; ++i) { 457 Browser* browser = CreateRestoredBrowser( 458 static_cast<Browser::Type>((*i)->type), 459 (*i)->bounds, 460 (*i)->is_maximized); 461 462 // Restore and show the browser. 463 const int initial_tab_count = browser->tab_count(); 464 int selected_tab_index = (*i)->selected_tab_index; 465 RestoreTabsToBrowser(*(*i), browser, selected_tab_index); 466 ShowBrowser(browser, initial_tab_count, selected_tab_index); 467 tab_loader_->TabIsLoading( 468 &browser->GetSelectedTabContents()->controller()); 469 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count); 470 } 471 472 // Always create in a new window 473 FinishedTabCreation(true, true); 474 } 475 476 // Restore a single tab from a foreign session. 477 // Note: we currently restore the tab to the last active browser. 478 void RestoreForeignTab(const SessionTab& tab) { 479 StartTabCreation(); 480 Browser* current_browser = 481 browser_ ? browser_ : BrowserList::GetLastActive(); 482 RestoreTab(tab, current_browser->tab_count(), current_browser, true); 483 NotifySessionServiceOfRestoredTabs(current_browser, 484 current_browser->tab_count()); 485 FinishedTabCreation(true, true); 486 } 487 488 ~SessionRestoreImpl() { 489 STLDeleteElements(&windows_); 490 restoring = false; 491 } 492 493 virtual void Observe(NotificationType type, 494 const NotificationSource& source, 495 const NotificationDetails& details) { 496 switch (type.value) { 497 case NotificationType::BROWSER_CLOSED: 498 delete this; 499 return; 500 501 default: 502 NOTREACHED(); 503 break; 504 } 505 } 506 507 private: 508 // Invoked when beginning to create new tabs. Resets the tab_loader_. 509 void StartTabCreation() { 510 tab_loader_.reset(new TabLoader(restore_started_)); 511 } 512 513 // Invoked when done with creating all the tabs/browsers. 514 // 515 // |created_tabbed_browser| indicates whether a tabbed browser was created, 516 // or we used an existing tabbed browser. 517 // 518 // If successful, this begins loading tabs and deletes itself when all tabs 519 // have been loaded. 520 // 521 // Returns the Browser that was created, if any. 522 Browser* FinishedTabCreation(bool succeeded, bool created_tabbed_browser) { 523 Browser* browser = NULL; 524 if (!created_tabbed_browser && always_create_tabbed_browser_) { 525 browser = Browser::Create(profile_); 526 if (urls_to_open_.empty()) { 527 // No tab browsers were created and no URLs were supplied on the command 528 // line. Add an empty URL, which is treated as opening the users home 529 // page. 530 urls_to_open_.push_back(GURL()); 531 } 532 AppendURLsToBrowser(browser, urls_to_open_); 533 browser->window()->Show(); 534 } 535 536 if (succeeded) { 537 DCHECK(tab_loader_.get()); 538 // TabLoader delets itself when done loading. 539 tab_loader_.release()->StartLoading(); 540 } 541 542 if (!synchronous_) { 543 // If we're not synchronous we need to delete ourself. 544 // NOTE: we must use DeleteLater here as most likely we're in a callback 545 // from the history service which doesn't deal well with deleting the 546 // object it is notifying. 547 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 548 } 549 550 return browser; 551 } 552 553 void OnGotSession(SessionService::Handle handle, 554 std::vector<SessionWindow*>* windows) { 555 if (synchronous_) { 556 // See comment above windows_ as to why we don't process immediately. 557 windows_.swap(*windows); 558 MessageLoop::current()->Quit(); 559 return; 560 } 561 562 ProcessSessionWindows(windows); 563 } 564 565 Browser* ProcessSessionWindows(std::vector<SessionWindow*>* windows) { 566 if (windows->empty()) { 567 // Restore was unsuccessful. 568 return FinishedTabCreation(false, false); 569 } 570 571 StartTabCreation(); 572 573 Browser* current_browser = 574 browser_ ? browser_ : BrowserList::GetLastActive(); 575 // After the for loop this contains the last TABBED_BROWSER. Is null if no 576 // tabbed browsers exist. 577 Browser* last_browser = NULL; 578 bool has_tabbed_browser = false; 579 for (std::vector<SessionWindow*>::iterator i = windows->begin(); 580 i != windows->end(); ++i) { 581 Browser* browser = NULL; 582 if (!has_tabbed_browser && (*i)->type == Browser::TYPE_NORMAL) 583 has_tabbed_browser = true; 584 if (i == windows->begin() && (*i)->type == Browser::TYPE_NORMAL && 585 !clobber_existing_window_) { 586 // If there is an open tabbed browser window, use it. Otherwise fall 587 // through and create a new one. 588 browser = current_browser; 589 if (browser && (browser->type() != Browser::TYPE_NORMAL || 590 browser->profile()->IsOffTheRecord())) { 591 browser = NULL; 592 } 593 } 594 if (!browser) { 595 browser = CreateRestoredBrowser( 596 static_cast<Browser::Type>((*i)->type), 597 (*i)->bounds, 598 (*i)->is_maximized); 599 } 600 if ((*i)->type == Browser::TYPE_NORMAL) 601 last_browser = browser; 602 const int initial_tab_count = browser->tab_count(); 603 int selected_tab_index = (*i)->selected_tab_index; 604 RestoreTabsToBrowser(*(*i), browser, selected_tab_index); 605 ShowBrowser(browser, initial_tab_count, selected_tab_index); 606 tab_loader_->TabIsLoading( 607 &browser->GetSelectedTabContents()->controller()); 608 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count); 609 } 610 611 // If we're restoring a session as the result of a crash and the session 612 // included at least one tabbed browser, then close the browser window 613 // that was opened when the user clicked to restore the session. 614 if (clobber_existing_window_ && current_browser && has_tabbed_browser && 615 current_browser->type() == Browser::TYPE_NORMAL) { 616 current_browser->CloseAllTabs(); 617 } 618 if (last_browser && !urls_to_open_.empty()) 619 AppendURLsToBrowser(last_browser, urls_to_open_); 620 // If last_browser is NULL and urls_to_open_ is non-empty, 621 // FinishedTabCreation will create a new TabbedBrowser and add the urls to 622 // it. 623 Browser* finished_browser = FinishedTabCreation(true, has_tabbed_browser); 624 if (finished_browser) 625 last_browser = finished_browser; 626 return last_browser; 627 } 628 629 void RestoreTabsToBrowser(const SessionWindow& window, 630 Browser* browser, 631 int selected_tab_index) { 632 DCHECK(!window.tabs.empty()); 633 for (std::vector<SessionTab*>::const_iterator i = window.tabs.begin(); 634 i != window.tabs.end(); ++i) { 635 const SessionTab& tab = *(*i); 636 const int tab_index = static_cast<int>(i - window.tabs.begin()); 637 // Don't schedule a load for the selected tab, as ShowBrowser() will 638 // already have done that. 639 RestoreTab(tab, tab_index, browser, tab_index != selected_tab_index); 640 } 641 } 642 643 void RestoreTab(const SessionTab& tab, 644 const int tab_index, 645 Browser* browser, 646 bool schedule_load) { 647 DCHECK(!tab.navigations.empty()); 648 int selected_index = tab.current_navigation_index; 649 selected_index = std::max( 650 0, 651 std::min(selected_index, 652 static_cast<int>(tab.navigations.size() - 1))); 653 654 // Record an app launch, if applicable. 655 GURL url = tab.navigations.at(tab.current_navigation_index).virtual_url(); 656 if ( 657 #if defined(OS_CHROMEOS) 658 browser->profile()->GetExtensionService() && 659 #endif 660 browser->profile()->GetExtensionService()->IsInstalledApp(url)) { 661 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppLaunchHistogram, 662 extension_misc::APP_LAUNCH_SESSION_RESTORE, 663 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); 664 } 665 666 TabContents* tab_contents = 667 browser->AddRestoredTab(tab.navigations, 668 tab_index, 669 selected_index, 670 tab.extension_app_id, 671 false, 672 tab.pinned, 673 true, 674 NULL); 675 if (schedule_load) 676 tab_loader_->ScheduleLoad(&tab_contents->controller()); 677 } 678 679 Browser* CreateRestoredBrowser(Browser::Type type, 680 gfx::Rect bounds, 681 bool is_maximized) { 682 Browser* browser = new Browser(type, profile_); 683 browser->set_override_bounds(bounds); 684 browser->set_maximized_state(is_maximized ? 685 Browser::MAXIMIZED_STATE_MAXIMIZED : 686 Browser::MAXIMIZED_STATE_UNMAXIMIZED); 687 browser->InitBrowserWindow(); 688 return browser; 689 } 690 691 void ShowBrowser(Browser* browser, 692 int initial_tab_count, 693 int selected_session_index) { 694 if (browser_ == browser) { 695 browser->ActivateTabAt(browser->tab_count() - 1, true); 696 return; 697 } 698 699 DCHECK(browser); 700 DCHECK(browser->tab_count()); 701 browser->ActivateTabAt( 702 std::min(initial_tab_count + std::max(0, selected_session_index), 703 browser->tab_count() - 1), true); 704 browser->window()->Show(); 705 // TODO(jcampan): http://crbug.com/8123 we should not need to set the 706 // initial focus explicitly. 707 browser->GetSelectedTabContents()->view()->SetInitialFocus(); 708 } 709 710 // Appends the urls in |urls| to |browser|. 711 void AppendURLsToBrowser(Browser* browser, 712 const std::vector<GURL>& urls) { 713 for (size_t i = 0; i < urls.size(); ++i) { 714 int add_types = TabStripModel::ADD_FORCE_INDEX; 715 if (i == 0) 716 add_types |= TabStripModel::ADD_ACTIVE; 717 int index = browser->GetIndexForInsertionDuringRestore(i); 718 browser::NavigateParams params(browser, urls[i], 719 PageTransition::START_PAGE); 720 params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB; 721 params.tabstrip_index = index; 722 params.tabstrip_add_types = add_types; 723 browser::Navigate(¶ms); 724 } 725 } 726 727 // Invokes TabRestored on the SessionService for all tabs in browser after 728 // initial_count. 729 void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) { 730 SessionService* session_service = profile_->GetSessionService(); 731 for (int i = initial_count; i < browser->tab_count(); ++i) 732 session_service->TabRestored(&browser->GetTabContentsAt(i)->controller(), 733 browser->tabstrip_model()->IsTabPinned(i)); 734 } 735 736 // The profile to create the sessions for. 737 Profile* profile_; 738 739 // The first browser to restore to, may be null. 740 Browser* browser_; 741 742 // Whether or not restore is synchronous. 743 const bool synchronous_; 744 745 // See description in RestoreSession (in .h). 746 const bool clobber_existing_window_; 747 748 // If true and there is an error or there are no windows to restore, we 749 // create a tabbed browser anyway. This is used on startup to make sure at 750 // at least one window is created. 751 const bool always_create_tabbed_browser_; 752 753 // Set of URLs to open in addition to those restored from the session. 754 std::vector<GURL> urls_to_open_; 755 756 // Used to get the session. 757 CancelableRequestConsumer request_consumer_; 758 759 // Responsible for loading the tabs. 760 scoped_ptr<TabLoader> tab_loader_; 761 762 // When synchronous we run a nested message loop. To avoid creating windows 763 // from the nested message loop (which can make exiting the nested message 764 // loop take a while) we cache the SessionWindows here and create the actual 765 // windows when the nested message loop exits. 766 std::vector<SessionWindow*> windows_; 767 768 NotificationRegistrar registrar_; 769 770 // The time we started the restore. 771 base::TimeTicks restore_started_; 772 }; 773 774 } // namespace 775 776 // SessionRestore ------------------------------------------------------------- 777 778 static Browser* Restore(Profile* profile, 779 Browser* browser, 780 bool synchronous, 781 bool clobber_existing_window, 782 bool always_create_tabbed_browser, 783 const std::vector<GURL>& urls_to_open) { 784 #if defined(OS_CHROMEOS) 785 chromeos::BootTimesLoader::Get()->AddLoginTimeMarker( 786 "SessionRestoreStarted", false); 787 #endif 788 DCHECK(profile); 789 // Always restore from the original profile (incognito profiles have no 790 // session service). 791 profile = profile->GetOriginalProfile(); 792 if (!profile->GetSessionService()) { 793 NOTREACHED(); 794 return NULL; 795 } 796 restoring = true; 797 profile->set_restored_last_session(true); 798 // SessionRestoreImpl takes care of deleting itself when done. 799 SessionRestoreImpl* restorer = 800 new SessionRestoreImpl(profile, browser, synchronous, 801 clobber_existing_window, 802 always_create_tabbed_browser, urls_to_open); 803 return restorer->Restore(); 804 } 805 806 // static 807 void SessionRestore::RestoreSession(Profile* profile, 808 Browser* browser, 809 bool clobber_existing_window, 810 bool always_create_tabbed_browser, 811 const std::vector<GURL>& urls_to_open) { 812 Restore(profile, browser, false, clobber_existing_window, 813 always_create_tabbed_browser, urls_to_open); 814 } 815 816 // static 817 void SessionRestore::RestoreForeignSessionWindows( 818 Profile* profile, 819 std::vector<SessionWindow*>::const_iterator begin, 820 std::vector<SessionWindow*>::const_iterator end) { 821 // Create a SessionRestore object to eventually restore the tabs. 822 std::vector<GURL> gurls; 823 SessionRestoreImpl restorer(profile, 824 static_cast<Browser*>(NULL), true, false, true, gurls); 825 restorer.RestoreForeignSession(begin, end); 826 } 827 828 // static 829 void SessionRestore::RestoreForeignSessionTab(Profile* profile, 830 const SessionTab& tab) { 831 // Create a SessionRestore object to eventually restore the tabs. 832 std::vector<GURL> gurls; 833 SessionRestoreImpl restorer(profile, 834 static_cast<Browser*>(NULL), true, false, true, gurls); 835 restorer.RestoreForeignTab(tab); 836 } 837 838 // static 839 Browser* SessionRestore::RestoreSessionSynchronously( 840 Profile* profile, 841 const std::vector<GURL>& urls_to_open) { 842 return Restore(profile, NULL, true, false, true, urls_to_open); 843 } 844 845 // static 846 bool SessionRestore::IsRestoring() { 847 return restoring; 848 } 849