ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / sessions / session_restore.cc
blob0c26a3e0d9e1573dc8fd80b4f34350eae84eae6e
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/sessions/session_restore.h"
7 #include <algorithm>
8 #include <list>
9 #include <set>
10 #include <string>
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/memory_pressure_listener.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/metrics/histogram.h"
21 #include "base/run_loop.h"
22 #include "base/stl_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/task/cancelable_task_tracker.h"
25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/chrome_notification_types.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_service_utils.h"
32 #include "chrome/browser/sessions/tab_loader_delegate.h"
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/browser/ui/browser_finder.h"
35 #include "chrome/browser/ui/browser_navigator.h"
36 #include "chrome/browser/ui/browser_tabrestore.h"
37 #include "chrome/browser/ui/browser_tabstrip.h"
38 #include "chrome/browser/ui/browser_window.h"
39 #include "chrome/browser/ui/tabs/tab_strip_model.h"
40 #include "chrome/common/extensions/extension_metrics.h"
41 #include "chrome/common/url_constants.h"
42 #include "components/sessions/session_types.h"
43 #include "content/public/browser/child_process_security_policy.h"
44 #include "content/public/browser/dom_storage_context.h"
45 #include "content/public/browser/navigation_controller.h"
46 #include "content/public/browser/notification_registrar.h"
47 #include "content/public/browser/notification_service.h"
48 #include "content/public/browser/render_process_host.h"
49 #include "content/public/browser/render_widget_host.h"
50 #include "content/public/browser/render_widget_host_view.h"
51 #include "content/public/browser/session_storage_namespace.h"
52 #include "content/public/browser/storage_partition.h"
53 #include "content/public/browser/web_contents.h"
54 #include "content/public/common/page_state.h"
55 #include "extensions/browser/extension_registry.h"
56 #include "extensions/common/extension_set.h"
58 #if defined(OS_CHROMEOS)
59 #include "chrome/browser/chromeos/boot_times_recorder.h"
60 #endif
62 using content::NavigationController;
63 using content::RenderWidgetHost;
64 using content::WebContents;
66 namespace {
68 class SessionRestoreImpl;
69 class TabLoader;
71 TabLoader* shared_tab_loader = NULL;
73 // Pointers to SessionRestoreImpls which are currently restoring the session.
74 std::set<SessionRestoreImpl*>* active_session_restorers = NULL;
76 // TabLoader ------------------------------------------------------------------
78 // TabLoader is responsible for loading tabs after session restore has finished
79 // creating all the tabs. Tabs are loaded after a previously tab finishes
80 // loading or a timeout is reached. If the timeout is reached before a tab
81 // finishes loading the timeout delay is doubled.
83 // TabLoader keeps a reference to itself when it's loading. When it has finished
84 // loading, it drops the reference. If another profile is restored while the
85 // TabLoader is loading, it will schedule its tabs to get loaded by the same
86 // TabLoader. When doing the scheduling, it holds a reference to the TabLoader.
88 // This is not part of SessionRestoreImpl so that synchronous destruction
89 // of SessionRestoreImpl doesn't have timing problems.
90 class TabLoader : public content::NotificationObserver,
91 public base::RefCounted<TabLoader>,
92 public TabLoaderCallback {
93 public:
94 // Retrieves a pointer to the TabLoader instance shared between profiles, or
95 // creates a new TabLoader if it doesn't exist. If a TabLoader is created, its
96 // starting timestamp is set to |restore_started|.
97 static TabLoader* GetTabLoader(base::TimeTicks restore_started);
99 // Schedules a tab for loading.
100 void ScheduleLoad(NavigationController* controller);
102 // Notifies the loader that a tab has been scheduled for loading through
103 // some other mechanism.
104 void TabIsLoading(NavigationController* controller);
106 // Invokes |LoadNextTab| to load a tab.
108 // This must be invoked once to start loading.
109 void StartLoading();
111 // TabLoaderCallback:
112 void SetTabLoadingEnabled(bool enable_tab_loading) override;
114 void set_on_session_restored_callbacks(
115 SessionRestore::CallbackList* callbacks) {
116 on_session_restored_callbacks_ = callbacks;
119 private:
120 friend class base::RefCounted<TabLoader>;
122 typedef std::set<NavigationController*> TabsLoading;
123 typedef std::list<NavigationController*> TabsToLoad;
124 typedef std::set<RenderWidgetHost*> RenderWidgetHostSet;
126 explicit TabLoader(base::TimeTicks restore_started);
127 ~TabLoader() override;
129 // Loads the next tab. If there are no more tabs to load this deletes itself,
130 // otherwise |force_load_timer_| is restarted.
131 void LoadNextTab();
133 // Starts a timer to load load the next tab once expired before the current
134 // tab loading is finished.
135 void StartTimer();
137 // NotificationObserver method. Removes the specified tab and loads the next
138 // tab.
139 void Observe(int type,
140 const content::NotificationSource& source,
141 const content::NotificationDetails& details) override;
143 // Removes the listeners from the specified tab and removes the tab from
144 // the set of tabs to load and list of tabs we're waiting to get a load
145 // from.
146 void RemoveTab(NavigationController* tab);
148 // Invoked from |force_load_timer_|. Doubles |force_load_delay_multiplier_|
149 // and invokes |LoadNextTab| to load the next tab
150 void ForceLoadTimerFired();
152 // Returns the RenderWidgetHost associated with a tab if there is one,
153 // NULL otherwise.
154 static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab);
156 // Register for necessary notifications on a tab navigation controller.
157 void RegisterForNotifications(NavigationController* controller);
159 // Called when a tab goes away or a load completes.
160 void HandleTabClosedOrLoaded(NavigationController* controller);
162 // TODO(sky): remove. For debugging 368236.
163 void CheckNotObserving(NavigationController* controller);
165 // React to memory pressure by stopping to load any more tabs.
166 void OnMemoryPressure(
167 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
169 scoped_ptr<TabLoaderDelegate> delegate_;
171 // Listens for system under memory pressure notifications and stops loading
172 // of tabs when we start running out of memory.
173 base::MemoryPressureListener memory_pressure_listener_;
175 content::NotificationRegistrar registrar_;
177 // The delay timer multiplier. See class description for details.
178 size_t force_load_delay_multiplier_;
180 // True if the tab loading is enabled.
181 bool loading_enabled_;
183 // Have we recorded the times for a foreground tab load?
184 bool got_first_foreground_load_;
186 // Have we recorded the times for a foreground tab paint?
187 bool got_first_paint_;
189 // The set of tabs we've initiated loading on. This does NOT include the
190 // selected tabs.
191 TabsLoading tabs_loading_;
193 // The tabs we need to load.
194 TabsToLoad tabs_to_load_;
196 // The renderers we have started loading into.
197 RenderWidgetHostSet render_widget_hosts_loading_;
199 // The renderers we have loaded and are waiting on to paint.
200 RenderWidgetHostSet render_widget_hosts_to_paint_;
202 // The number of tabs that have been restored.
203 int tab_count_;
205 base::OneShotTimer<TabLoader> force_load_timer_;
207 // The time the restore process started.
208 base::TimeTicks restore_started_;
210 // Max number of tabs that were loaded in parallel (for metrics).
211 size_t max_parallel_tab_loads_;
213 // Callback list for sending a session restore notification.
214 SessionRestore::CallbackList* on_session_restored_callbacks_;
216 // For keeping TabLoader alive while it's loading even if no
217 // SessionRestoreImpls reference it.
218 scoped_refptr<TabLoader> this_retainer_;
220 DISALLOW_COPY_AND_ASSIGN(TabLoader);
223 // static
224 TabLoader* TabLoader::GetTabLoader(base::TimeTicks restore_started) {
225 if (!shared_tab_loader)
226 shared_tab_loader = new TabLoader(restore_started);
227 return shared_tab_loader;
230 void TabLoader::ScheduleLoad(NavigationController* controller) {
231 CheckNotObserving(controller);
232 DCHECK(controller);
233 DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) ==
234 tabs_to_load_.end());
235 tabs_to_load_.push_back(controller);
236 RegisterForNotifications(controller);
239 void TabLoader::TabIsLoading(NavigationController* controller) {
240 CheckNotObserving(controller);
241 DCHECK(controller);
242 DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) ==
243 tabs_loading_.end());
244 tabs_loading_.insert(controller);
245 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller);
246 DCHECK(render_widget_host);
247 render_widget_hosts_loading_.insert(render_widget_host);
248 RegisterForNotifications(controller);
251 void TabLoader::StartLoading() {
252 // When multiple profiles are using the same TabLoader, another profile might
253 // already have started loading. In that case, the tabs scheduled for loading
254 // by this profile are already in the loading queue, and they will get loaded
255 // eventually.
256 if (delegate_)
257 return;
259 registrar_.Add(
260 this,
261 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
262 content::NotificationService::AllSources());
263 this_retainer_ = this;
264 // Create a TabLoaderDelegate which will allow OS specific behavior for tab
265 // loading.
266 if (!delegate_) {
267 delegate_ = TabLoaderDelegate::Create(this);
268 // There is already at least one tab loading (the active tab). As such we
269 // only have to start the timeout timer here.
270 StartTimer();
274 void TabLoader::SetTabLoadingEnabled(bool enable_tab_loading) {
275 if (enable_tab_loading == loading_enabled_)
276 return;
277 loading_enabled_ = enable_tab_loading;
278 if (loading_enabled_)
279 LoadNextTab();
280 else
281 force_load_timer_.Stop();
284 TabLoader::TabLoader(base::TimeTicks restore_started)
285 : memory_pressure_listener_(
286 base::Bind(&TabLoader::OnMemoryPressure, base::Unretained(this))),
287 force_load_delay_multiplier_(1),
288 loading_enabled_(true),
289 got_first_foreground_load_(false),
290 got_first_paint_(false),
291 tab_count_(0),
292 restore_started_(restore_started),
293 max_parallel_tab_loads_(0),
294 on_session_restored_callbacks_(nullptr) {
297 TabLoader::~TabLoader() {
298 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
299 tabs_loading_.empty() && tabs_to_load_.empty());
300 shared_tab_loader = NULL;
303 void TabLoader::LoadNextTab() {
304 // LoadNextTab should only get called after we have started the tab
305 // loading.
306 CHECK(delegate_);
307 if (!tabs_to_load_.empty()) {
308 NavigationController* tab = tabs_to_load_.front();
309 DCHECK(tab);
310 tabs_loading_.insert(tab);
311 if (tabs_loading_.size() > max_parallel_tab_loads_)
312 max_parallel_tab_loads_ = tabs_loading_.size();
313 tabs_to_load_.pop_front();
314 tab->LoadIfNecessary();
315 content::WebContents* contents = tab->GetWebContents();
316 if (contents) {
317 Browser* browser = chrome::FindBrowserWithWebContents(contents);
318 if (browser &&
319 browser->tab_strip_model()->GetActiveWebContents() != contents) {
320 // By default tabs are marked as visible. As only the active tab is
321 // visible we need to explicitly tell non-active tabs they are hidden.
322 // Without this call non-active tabs are not marked as backgrounded.
324 // NOTE: We need to do this here rather than when the tab is added to
325 // the Browser as at that time not everything has been created, so that
326 // the call would do nothing.
327 contents->WasHidden();
332 if (!tabs_to_load_.empty())
333 StartTimer();
335 // When the session restore is done synchronously, notification is sent from
336 // SessionRestoreImpl::Restore .
337 if (tabs_to_load_.empty() && !SessionRestore::IsRestoringSynchronously()) {
338 on_session_restored_callbacks_->Notify(tab_count_);
342 void TabLoader::StartTimer() {
343 force_load_timer_.Stop();
344 force_load_timer_.Start(FROM_HERE,
345 delegate_->GetTimeoutBeforeLoadingNextTab() *
346 force_load_delay_multiplier_,
347 this, &TabLoader::ForceLoadTimerFired);
350 void TabLoader::Observe(int type,
351 const content::NotificationSource& source,
352 const content::NotificationDetails& details) {
353 switch (type) {
354 case content::NOTIFICATION_LOAD_START: {
355 // Add this render_widget_host to the set of those we're waiting for
356 // paints on. We want to only record stats for paints that occur after
357 // a load has finished.
358 NavigationController* tab =
359 content::Source<NavigationController>(source).ptr();
360 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
361 DCHECK(render_widget_host);
362 render_widget_hosts_loading_.insert(render_widget_host);
363 break;
365 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
366 WebContents* web_contents = content::Source<WebContents>(source).ptr();
367 if (!got_first_paint_) {
368 RenderWidgetHost* render_widget_host =
369 GetRenderWidgetHost(&web_contents->GetController());
370 render_widget_hosts_loading_.erase(render_widget_host);
372 HandleTabClosedOrLoaded(&web_contents->GetController());
373 break;
375 case content::NOTIFICATION_LOAD_STOP: {
376 NavigationController* tab =
377 content::Source<NavigationController>(source).ptr();
378 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab);
379 render_widget_hosts_to_paint_.insert(render_widget_host);
380 HandleTabClosedOrLoaded(tab);
381 if (!got_first_foreground_load_ && render_widget_host &&
382 render_widget_host->GetView() &&
383 render_widget_host->GetView()->IsShowing()) {
384 got_first_foreground_load_ = true;
385 base::TimeDelta time_to_load =
386 base::TimeTicks::Now() - restore_started_;
387 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstLoaded",
388 time_to_load,
389 base::TimeDelta::FromMilliseconds(10),
390 base::TimeDelta::FromSeconds(100),
391 100);
392 // Record a time for the number of tabs, to help track down
393 // contention.
394 std::string time_for_count = base::StringPrintf(
395 "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_);
396 base::HistogramBase* counter_for_count =
397 base::Histogram::FactoryTimeGet(
398 time_for_count,
399 base::TimeDelta::FromMilliseconds(10),
400 base::TimeDelta::FromSeconds(100),
401 100,
402 base::Histogram::kUmaTargetedHistogramFlag);
403 counter_for_count->AddTime(time_to_load);
405 break;
407 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: {
408 RenderWidgetHost* render_widget_host =
409 content::Source<RenderWidgetHost>(source).ptr();
410 if (!got_first_paint_ && render_widget_host->GetView() &&
411 render_widget_host->GetView()->IsShowing()) {
412 if (render_widget_hosts_to_paint_.find(render_widget_host) !=
413 render_widget_hosts_to_paint_.end()) {
414 // Got a paint for one of our renderers, so record time.
415 got_first_paint_ = true;
416 base::TimeDelta time_to_paint =
417 base::TimeTicks::Now() - restore_started_;
418 UMA_HISTOGRAM_CUSTOM_TIMES("SessionRestore.ForegroundTabFirstPaint",
419 time_to_paint,
420 base::TimeDelta::FromMilliseconds(10),
421 base::TimeDelta::FromSeconds(100),
422 100);
423 // Record a time for the number of tabs, to help track down
424 // contention.
425 std::string time_for_count = base::StringPrintf(
426 "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_);
427 base::HistogramBase* counter_for_count =
428 base::Histogram::FactoryTimeGet(
429 time_for_count,
430 base::TimeDelta::FromMilliseconds(10),
431 base::TimeDelta::FromSeconds(100),
432 100,
433 base::Histogram::kUmaTargetedHistogramFlag);
434 counter_for_count->AddTime(time_to_paint);
435 } else if (render_widget_hosts_loading_.find(render_widget_host) ==
436 render_widget_hosts_loading_.end()) {
437 // If this is a host for a tab we're not loading some other tab
438 // has rendered and there's no point tracking the time. This could
439 // happen because the user opened a different tab or restored tabs
440 // to an already existing browser and an existing tab painted.
441 got_first_paint_ = true;
444 break;
446 default:
447 NOTREACHED() << "Unknown notification received:" << type;
449 // Delete ourselves when we're not waiting for any more notifications. If this
450 // was not the last reference, a SessionRestoreImpl holding a reference will
451 // eventually call StartLoading (which assigns this_retainer_), or drop the
452 // reference without initiating a load.
453 if ((got_first_paint_ || render_widget_hosts_to_paint_.empty()) &&
454 tabs_loading_.empty() && tabs_to_load_.empty())
455 this_retainer_ = NULL;
458 void TabLoader::RemoveTab(NavigationController* tab) {
459 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
460 content::Source<WebContents>(tab->GetWebContents()));
461 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP,
462 content::Source<NavigationController>(tab));
463 registrar_.Remove(this, content::NOTIFICATION_LOAD_START,
464 content::Source<NavigationController>(tab));
466 TabsLoading::iterator i = tabs_loading_.find(tab);
467 if (i != tabs_loading_.end())
468 tabs_loading_.erase(i);
470 TabsToLoad::iterator j =
471 find(tabs_to_load_.begin(), tabs_to_load_.end(), tab);
472 if (j != tabs_to_load_.end())
473 tabs_to_load_.erase(j);
476 void TabLoader::ForceLoadTimerFired() {
477 force_load_delay_multiplier_ *= 2;
478 LoadNextTab();
481 RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) {
482 WebContents* web_contents = tab->GetWebContents();
483 if (web_contents) {
484 content::RenderWidgetHostView* render_widget_host_view =
485 web_contents->GetRenderWidgetHostView();
486 if (render_widget_host_view)
487 return render_widget_host_view->GetRenderWidgetHost();
489 return NULL;
492 void TabLoader::RegisterForNotifications(NavigationController* controller) {
493 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
494 content::Source<WebContents>(controller->GetWebContents()));
495 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
496 content::Source<NavigationController>(controller));
497 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
498 content::Source<NavigationController>(controller));
499 ++tab_count_;
502 void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) {
503 RemoveTab(tab);
504 if (delegate_ && loading_enabled_)
505 LoadNextTab();
506 if (tabs_loading_.empty() && tabs_to_load_.empty()) {
507 base::TimeDelta time_to_load =
508 base::TimeTicks::Now() - restore_started_;
509 UMA_HISTOGRAM_CUSTOM_TIMES(
510 "SessionRestore.AllTabsLoaded",
511 time_to_load,
512 base::TimeDelta::FromMilliseconds(10),
513 base::TimeDelta::FromSeconds(100),
514 100);
515 // Record a time for the number of tabs, to help track down contention.
516 std::string time_for_count =
517 base::StringPrintf("SessionRestore.AllTabsLoaded_%d", tab_count_);
518 base::HistogramBase* counter_for_count =
519 base::Histogram::FactoryTimeGet(
520 time_for_count,
521 base::TimeDelta::FromMilliseconds(10),
522 base::TimeDelta::FromSeconds(100),
523 100,
524 base::Histogram::kUmaTargetedHistogramFlag);
525 counter_for_count->AddTime(time_to_load);
527 UMA_HISTOGRAM_COUNTS_100("SessionRestore.ParallelTabLoads",
528 max_parallel_tab_loads_);
532 void TabLoader::CheckNotObserving(NavigationController* controller) {
533 const bool in_tabs_to_load =
534 find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) !=
535 tabs_to_load_.end();
536 const bool in_tabs_loading =
537 find(tabs_loading_.begin(), tabs_loading_.end(), controller) !=
538 tabs_loading_.end();
539 const bool observing =
540 registrar_.IsRegistered(
541 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
542 content::Source<WebContents>(controller->GetWebContents())) ||
543 registrar_.IsRegistered(
544 this, content::NOTIFICATION_LOAD_STOP,
545 content::Source<NavigationController>(controller)) ||
546 registrar_.IsRegistered(
547 this, content::NOTIFICATION_LOAD_START,
548 content::Source<NavigationController>(controller));
549 base::debug::Alias(&in_tabs_to_load);
550 base::debug::Alias(&in_tabs_loading);
551 base::debug::Alias(&observing);
552 CHECK(!in_tabs_to_load && !in_tabs_loading && !observing);
555 void TabLoader::OnMemoryPressure(
556 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
557 // When receiving a resource pressure level warning, we stop pre-loading more
558 // tabs since we are running in danger of loading more tabs by throwing out
559 // old ones.
560 if (tabs_to_load_.empty())
561 return;
562 // Stop the timer and suppress any tab loads while we clean the list.
563 SetTabLoadingEnabled(false);
564 while (!tabs_to_load_.empty()) {
565 NavigationController* controller = tabs_to_load_.front();
566 tabs_to_load_.pop_front();
567 RemoveTab(controller);
569 // By calling |LoadNextTab| explicitly, we make sure that the
570 // |NOTIFICATION_SESSION_RESTORE_DONE| event gets sent.
571 LoadNextTab();
574 // SessionRestoreImpl ---------------------------------------------------------
576 // SessionRestoreImpl is responsible for fetching the set of tabs to create
577 // from SessionService. SessionRestoreImpl deletes itself when done.
579 class SessionRestoreImpl : public content::NotificationObserver {
580 public:
581 SessionRestoreImpl(Profile* profile,
582 Browser* browser,
583 chrome::HostDesktopType host_desktop_type,
584 bool synchronous,
585 bool clobber_existing_tab,
586 bool always_create_tabbed_browser,
587 const std::vector<GURL>& urls_to_open,
588 SessionRestore::CallbackList* callbacks)
589 : profile_(profile),
590 browser_(browser),
591 host_desktop_type_(host_desktop_type),
592 synchronous_(synchronous),
593 clobber_existing_tab_(clobber_existing_tab),
594 always_create_tabbed_browser_(always_create_tabbed_browser),
595 urls_to_open_(urls_to_open),
596 active_window_id_(0),
597 restore_started_(base::TimeTicks::Now()),
598 browser_shown_(false),
599 on_session_restored_callbacks_(callbacks) {
600 // For sanity's sake, if |browser| is non-null: force |host_desktop_type| to
601 // be the same as |browser|'s desktop type.
602 DCHECK(!browser || browser->host_desktop_type() == host_desktop_type);
604 if (active_session_restorers == NULL)
605 active_session_restorers = new std::set<SessionRestoreImpl*>();
607 // Only one SessionRestoreImpl should be operating on the profile at the
608 // same time.
609 std::set<SessionRestoreImpl*>::const_iterator it;
610 for (it = active_session_restorers->begin();
611 it != active_session_restorers->end(); ++it) {
612 if ((*it)->profile_ == profile)
613 break;
615 DCHECK(it == active_session_restorers->end());
617 active_session_restorers->insert(this);
619 // When asynchronous its possible for there to be no windows. To make sure
620 // Chrome doesn't prematurely exit AddRef the process. We'll release in the
621 // destructor when restore is done.
622 g_browser_process->AddRefModule();
625 bool synchronous() const { return synchronous_; }
627 Browser* Restore() {
628 SessionService* session_service =
629 SessionServiceFactory::GetForProfile(profile_);
630 DCHECK(session_service);
631 session_service->GetLastSession(
632 base::Bind(&SessionRestoreImpl::OnGotSession, base::Unretained(this)),
633 &cancelable_task_tracker_);
635 if (synchronous_) {
637 base::MessageLoop::ScopedNestableTaskAllower allow(
638 base::MessageLoop::current());
639 base::RunLoop loop;
640 quit_closure_for_sync_restore_ = loop.QuitClosure();
641 loop.Run();
642 quit_closure_for_sync_restore_ = base::Closure();
644 // Count the total number of tabs in |windows_|.
645 int total_num_tabs = 0;
646 for (int i = 0; i < static_cast<int>(windows_.size()); ++i)
647 total_num_tabs += windows_[i]->tabs.size();
649 Browser* browser = ProcessSessionWindows(&windows_, active_window_id_);
650 on_session_restored_callbacks_->Notify(total_num_tabs);
651 delete this;
652 return browser;
655 if (browser_) {
656 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
657 content::Source<Browser>(browser_));
660 return browser_;
663 // Restore window(s) from a foreign session. Returns newly created Browsers.
664 std::vector<Browser*> RestoreForeignSession(
665 std::vector<const sessions::SessionWindow*>::const_iterator begin,
666 std::vector<const sessions::SessionWindow*>::const_iterator end) {
667 StartTabCreation();
668 std::vector<Browser*> browsers;
669 // Create a browser instance to put the restored tabs in.
670 for (std::vector<const sessions::SessionWindow*>::const_iterator i = begin;
671 i != end; ++i) {
672 Browser* browser = CreateRestoredBrowser(
673 BrowserTypeForWindowType((*i)->type),
674 (*i)->bounds,
675 (*i)->show_state,
676 (*i)->app_name);
677 browsers.push_back(browser);
679 // Restore and show the browser.
680 const int initial_tab_count = 0;
681 int selected_tab_index = std::max(
683 std::min((*i)->selected_tab_index,
684 static_cast<int>((*i)->tabs.size()) - 1));
685 RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
686 selected_tab_index);
687 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
690 // Always create in a new window
691 FinishedTabCreation(true, true);
692 return browsers;
695 // Restore a single tab from a foreign session.
696 // Opens in the tab in the last active browser, unless disposition is
697 // NEW_WINDOW, in which case the tab will be opened in a new browser. Returns
698 // the WebContents of the restored tab.
699 WebContents* RestoreForeignTab(const sessions::SessionTab& tab,
700 WindowOpenDisposition disposition) {
701 DCHECK(!tab.navigations.empty());
702 int selected_index = tab.current_navigation_index;
703 selected_index = std::max(
705 std::min(selected_index,
706 static_cast<int>(tab.navigations.size() - 1)));
708 bool use_new_window = disposition == NEW_WINDOW;
710 Browser* browser = use_new_window ?
711 new Browser(Browser::CreateParams(profile_, host_desktop_type_)) :
712 browser_;
714 RecordAppLaunchForTab(browser, tab, selected_index);
716 WebContents* web_contents;
717 if (disposition == CURRENT_TAB) {
718 DCHECK(!use_new_window);
719 web_contents = chrome::ReplaceRestoredTab(browser,
720 tab.navigations,
721 selected_index,
722 true,
723 tab.extension_app_id,
724 NULL,
725 tab.user_agent_override);
726 } else {
727 int tab_index =
728 use_new_window ? 0 : browser->tab_strip_model()->active_index() + 1;
729 web_contents = chrome::AddRestoredTab(
730 browser,
731 tab.navigations,
732 tab_index,
733 selected_index,
734 tab.extension_app_id,
735 disposition == NEW_FOREGROUND_TAB, // selected
736 tab.pinned,
737 true,
738 NULL,
739 tab.user_agent_override);
740 // Start loading the tab immediately.
741 web_contents->GetController().LoadIfNecessary();
744 if (use_new_window) {
745 browser->tab_strip_model()->ActivateTabAt(0, true);
746 browser->window()->Show();
748 NotifySessionServiceOfRestoredTabs(browser,
749 browser->tab_strip_model()->count());
751 // Since FinishedTabCreation() is not called here, |this| will leak if we
752 // are not in sychronous mode.
753 DCHECK(synchronous_);
754 return web_contents;
757 ~SessionRestoreImpl() override {
758 STLDeleteElements(&windows_);
760 active_session_restorers->erase(this);
761 if (active_session_restorers->empty()) {
762 delete active_session_restorers;
763 active_session_restorers = NULL;
766 g_browser_process->ReleaseModule();
769 void Observe(int type,
770 const content::NotificationSource& source,
771 const content::NotificationDetails& details) override {
772 switch (type) {
773 case chrome::NOTIFICATION_BROWSER_CLOSED:
774 delete this;
775 return;
777 default:
778 NOTREACHED();
779 break;
783 Profile* profile() { return profile_; }
785 private:
786 // Invoked when beginning to create new tabs. Resets the |tab_loader_|.
787 void StartTabCreation() {
788 tab_loader_ = TabLoader::GetTabLoader(restore_started_);
789 tab_loader_->set_on_session_restored_callbacks(
790 on_session_restored_callbacks_);
793 // Invoked when done with creating all the tabs/browsers.
795 // |created_tabbed_browser| indicates whether a tabbed browser was created,
796 // or we used an existing tabbed browser.
798 // If successful, this begins loading tabs and deletes itself when all tabs
799 // have been loaded.
801 // Returns the Browser that was created, if any.
802 Browser* FinishedTabCreation(bool succeeded, bool created_tabbed_browser) {
803 Browser* browser = NULL;
804 if (!created_tabbed_browser && always_create_tabbed_browser_) {
805 browser = new Browser(Browser::CreateParams(profile_,
806 host_desktop_type_));
807 if (urls_to_open_.empty()) {
808 // No tab browsers were created and no URLs were supplied on the command
809 // line. Open the new tab page.
810 urls_to_open_.push_back(GURL(chrome::kChromeUINewTabURL));
812 AppendURLsToBrowser(browser, urls_to_open_);
813 browser->window()->Show();
816 if (succeeded) {
817 DCHECK(tab_loader_.get());
818 // TabLoader deletes itself when done loading.
819 tab_loader_->StartLoading();
820 tab_loader_ = NULL;
823 if (!synchronous_) {
824 // If we're not synchronous we need to delete ourself.
825 // NOTE: we must use DeleteLater here as most likely we're in a callback
826 // from the history service which doesn't deal well with deleting the
827 // object it is notifying.
828 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
830 // The delete may take a while and at this point we no longer care about
831 // if the browser is deleted. Don't listen to anything. This avoid a
832 // possible double delete too (if browser is closed before DeleteSoon() is
833 // processed).
834 registrar_.RemoveAll();
837 #if defined(OS_CHROMEOS)
838 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
839 "SessionRestore-End", false);
840 #endif
841 return browser;
844 void OnGotSession(ScopedVector<sessions::SessionWindow> windows,
845 SessionID::id_type active_window_id) {
846 base::TimeDelta time_to_got_sessions =
847 base::TimeTicks::Now() - restore_started_;
848 UMA_HISTOGRAM_CUSTOM_TIMES(
849 "SessionRestore.TimeToGotSessions",
850 time_to_got_sessions,
851 base::TimeDelta::FromMilliseconds(10),
852 base::TimeDelta::FromSeconds(1000),
853 100);
854 #if defined(OS_CHROMEOS)
855 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
856 "SessionRestore-GotSession", false);
857 #endif
858 if (synchronous_) {
859 // See comment above windows_ as to why we don't process immediately.
860 windows_.swap(windows.get());
861 active_window_id_ = active_window_id;
862 CHECK(!quit_closure_for_sync_restore_.is_null());
863 quit_closure_for_sync_restore_.Run();
864 return;
867 ProcessSessionWindows(&windows.get(), active_window_id);
870 Browser* ProcessSessionWindows(std::vector<sessions::SessionWindow*>* windows,
871 SessionID::id_type active_window_id) {
872 DVLOG(1) << "ProcessSessionWindows " << windows->size();
873 base::TimeDelta time_to_process_sessions =
874 base::TimeTicks::Now() - restore_started_;
875 UMA_HISTOGRAM_CUSTOM_TIMES(
876 "SessionRestore.TimeToProcessSessions",
877 time_to_process_sessions,
878 base::TimeDelta::FromMilliseconds(10),
879 base::TimeDelta::FromSeconds(1000),
880 100);
882 if (windows->empty()) {
883 // Restore was unsuccessful. The DOM storage system can also delete its
884 // data, since no session restore will happen at a later point in time.
885 content::BrowserContext::GetDefaultStoragePartition(profile_)->
886 GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
887 return FinishedTabCreation(false, false);
890 #if defined(OS_CHROMEOS)
891 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
892 "SessionRestore-CreatingTabs-Start", false);
893 #endif
894 StartTabCreation();
896 // After the for loop this contains the last TABBED_BROWSER. Is null if no
897 // tabbed browsers exist.
898 Browser* last_browser = NULL;
899 bool has_tabbed_browser = false;
901 // After the for loop, this contains the browser to activate, if one of the
902 // windows has the same id as specified in active_window_id.
903 Browser* browser_to_activate = NULL;
905 // Determine if there is a visible window.
906 bool has_visible_browser = false;
907 for (std::vector<sessions::SessionWindow*>::iterator i = windows->begin();
908 i != windows->end(); ++i) {
909 if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED)
910 has_visible_browser = true;
913 for (std::vector<sessions::SessionWindow*>::iterator i = windows->begin();
914 i != windows->end(); ++i) {
915 Browser* browser = NULL;
916 if (!has_tabbed_browser && (*i)->type ==
917 sessions::SessionWindow::TYPE_TABBED)
918 has_tabbed_browser = true;
919 if (i == windows->begin() && (*i)->type ==
920 sessions::SessionWindow::TYPE_TABBED &&
921 browser_ && browser_->is_type_tabbed() &&
922 !browser_->profile()->IsOffTheRecord()) {
923 // The first set of tabs is added to the existing browser.
924 browser = browser_;
925 } else {
926 #if defined(OS_CHROMEOS)
927 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
928 "SessionRestore-CreateRestoredBrowser-Start", false);
929 #endif
930 // Show the first window if none are visible.
931 ui::WindowShowState show_state = (*i)->show_state;
932 if (!has_visible_browser) {
933 show_state = ui::SHOW_STATE_NORMAL;
934 has_visible_browser = true;
936 browser = CreateRestoredBrowser(
937 BrowserTypeForWindowType((*i)->type),
938 (*i)->bounds,
939 show_state,
940 (*i)->app_name);
941 #if defined(OS_CHROMEOS)
942 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
943 "SessionRestore-CreateRestoredBrowser-End", false);
944 #endif
946 if ((*i)->type == sessions::SessionWindow::TYPE_TABBED)
947 last_browser = browser;
948 WebContents* active_tab =
949 browser->tab_strip_model()->GetActiveWebContents();
950 int initial_tab_count = browser->tab_strip_model()->count();
951 bool close_active_tab = clobber_existing_tab_ &&
952 i == windows->begin() &&
953 (*i)->type ==
954 sessions::SessionWindow::TYPE_TABBED &&
955 active_tab && browser == browser_ &&
956 (*i)->tabs.size() > 0;
957 if (close_active_tab)
958 --initial_tab_count;
959 int selected_tab_index =
960 initial_tab_count > 0 ? browser->tab_strip_model()->active_index()
961 : std::max(0,
962 std::min((*i)->selected_tab_index,
963 static_cast<int>((*i)->tabs.size()) - 1));
964 if ((*i)->window_id.id() == active_window_id)
965 browser_to_activate = browser;
967 RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
968 selected_tab_index);
969 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
970 // This needs to be done after restore because closing the last tab will
971 // close the whole window.
972 if (close_active_tab)
973 chrome::CloseWebContents(browser, active_tab, true);
976 if (browser_to_activate && browser_to_activate->is_type_tabbed())
977 last_browser = browser_to_activate;
979 if (last_browser && !urls_to_open_.empty())
980 AppendURLsToBrowser(last_browser, urls_to_open_);
981 #if defined(OS_CHROMEOS)
982 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
983 "SessionRestore-CreatingTabs-End", false);
984 #endif
985 if (browser_to_activate)
986 browser_to_activate->window()->Activate();
988 // If last_browser is NULL and urls_to_open_ is non-empty,
989 // FinishedTabCreation will create a new TabbedBrowser and add the urls to
990 // it.
991 Browser* finished_browser = FinishedTabCreation(true, has_tabbed_browser);
992 if (finished_browser)
993 last_browser = finished_browser;
995 // sessionStorages needed for the session restore have now been recreated
996 // by RestoreTab. Now it's safe for the DOM storage system to start
997 // deleting leftover data.
998 content::BrowserContext::GetDefaultStoragePartition(profile_)->
999 GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
1000 return last_browser;
1003 // Record an app launch event (if appropriate) for a tab which is about to
1004 // be restored. Callers should ensure that selected_index is within the
1005 // bounds of tab.navigations before calling.
1006 void RecordAppLaunchForTab(Browser* browser,
1007 const sessions::SessionTab& tab,
1008 int selected_index) {
1009 DCHECK(selected_index >= 0 &&
1010 selected_index < static_cast<int>(tab.navigations.size()));
1011 GURL url = tab.navigations[selected_index].virtual_url();
1012 const extensions::Extension* extension =
1013 extensions::ExtensionRegistry::Get(profile())
1014 ->enabled_extensions().GetAppByURL(url);
1015 if (extension) {
1016 extensions::RecordAppLaunchType(
1017 extension_misc::APP_LAUNCH_SESSION_RESTORE,
1018 extension->GetType());
1022 // Adds the tabs from |window| to |browser|. Normal tabs go after the existing
1023 // tabs but pinned tabs will be pushed in front.
1024 // If there are no existing tabs, the tab at |selected_tab_index| will be
1025 // selected. Otherwise, the tab selection will remain untouched.
1026 void RestoreTabsToBrowser(const sessions::SessionWindow& window,
1027 Browser* browser,
1028 int initial_tab_count,
1029 int selected_tab_index) {
1030 DVLOG(1) << "RestoreTabsToBrowser " << window.tabs.size();
1031 DCHECK(!window.tabs.empty());
1032 if (initial_tab_count == 0) {
1033 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
1034 const sessions::SessionTab& tab = *(window.tabs[i]);
1036 // Loads are scheduled for each restored tab unless the tab is going to
1037 // be selected as ShowBrowser() will load the selected tab.
1038 bool is_selected_tab = (i == selected_tab_index);
1039 WebContents* restored_tab =
1040 RestoreTab(tab, i, browser, is_selected_tab);
1042 // RestoreTab can return NULL if |tab| doesn't have valid data.
1043 if (!restored_tab)
1044 continue;
1046 // If this isn't the selected tab, there's nothing else to do.
1047 if (!is_selected_tab)
1048 continue;
1050 ShowBrowser(
1051 browser,
1052 browser->tab_strip_model()->GetIndexOfWebContents(restored_tab));
1053 // TODO(sky): remove. For debugging 368236.
1054 CHECK_EQ(browser->tab_strip_model()->GetActiveWebContents(),
1055 restored_tab);
1056 tab_loader_->TabIsLoading(&browser->tab_strip_model()
1057 ->GetActiveWebContents()
1058 ->GetController());
1060 } else {
1061 // If the browser already has tabs, we want to restore the new ones after
1062 // the existing ones. E.g. this happens in Win8 Metro where we merge
1063 // windows or when launching a hosted app from the app launcher.
1064 int tab_index_offset = initial_tab_count;
1065 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
1066 const sessions::SessionTab& tab = *(window.tabs[i]);
1067 // Always schedule loads as we will not be calling ShowBrowser().
1068 RestoreTab(tab, tab_index_offset + i, browser, false);
1073 // |tab_index| is ignored for pinned tabs which will always be pushed behind
1074 // the last existing pinned tab.
1075 // |tab_loader_| will schedule this tab for loading if |is_selected_tab| is
1076 // false.
1077 WebContents* RestoreTab(const sessions::SessionTab& tab,
1078 const int tab_index,
1079 Browser* browser,
1080 bool is_selected_tab) {
1081 // It's possible (particularly for foreign sessions) to receive a tab
1082 // without valid navigations. In that case, just skip it.
1083 // See crbug.com/154129.
1084 if (tab.navigations.empty())
1085 return NULL;
1086 int selected_index = tab.current_navigation_index;
1087 selected_index = std::max(
1089 std::min(selected_index,
1090 static_cast<int>(tab.navigations.size() - 1)));
1092 RecordAppLaunchForTab(browser, tab, selected_index);
1094 // Associate sessionStorage (if any) to the restored tab.
1095 scoped_refptr<content::SessionStorageNamespace> session_storage_namespace;
1096 if (!tab.session_storage_persistent_id.empty()) {
1097 session_storage_namespace =
1098 content::BrowserContext::GetDefaultStoragePartition(profile_)->
1099 GetDOMStorageContext()->RecreateSessionStorage(
1100 tab.session_storage_persistent_id);
1103 WebContents* web_contents =
1104 chrome::AddRestoredTab(browser,
1105 tab.navigations,
1106 tab_index,
1107 selected_index,
1108 tab.extension_app_id,
1109 false, // select
1110 tab.pinned,
1111 true,
1112 session_storage_namespace.get(),
1113 tab.user_agent_override);
1114 // Regression check: check that the tab didn't start loading right away. The
1115 // focused tab will be loaded by Browser, and TabLoader will load the rest.
1116 DCHECK(web_contents->GetController().NeedsReload());
1118 if (!is_selected_tab)
1119 tab_loader_->ScheduleLoad(&web_contents->GetController());
1120 return web_contents;
1123 Browser* CreateRestoredBrowser(Browser::Type type,
1124 gfx::Rect bounds,
1125 ui::WindowShowState show_state,
1126 const std::string& app_name) {
1127 Browser::CreateParams params(type, profile_, host_desktop_type_);
1128 if (!app_name.empty()) {
1129 const bool trusted_source = true; // We only store trusted app windows.
1130 params = Browser::CreateParams::CreateForApp(app_name,
1131 trusted_source,
1132 bounds,
1133 profile_,
1134 host_desktop_type_);
1135 } else {
1136 params.initial_bounds = bounds;
1138 params.initial_show_state = show_state;
1139 params.is_session_restore = true;
1140 return new Browser(params);
1143 void ShowBrowser(Browser* browser, int selected_tab_index) {
1144 DCHECK(browser);
1145 DCHECK(browser->tab_strip_model()->count());
1146 browser->tab_strip_model()->ActivateTabAt(selected_tab_index, true);
1148 if (browser_ == browser)
1149 return;
1151 browser->window()->Show();
1152 browser->set_is_session_restore(false);
1154 // TODO(jcampan): http://crbug.com/8123 we should not need to set the
1155 // initial focus explicitly.
1156 browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus();
1158 if (!browser_shown_) {
1159 browser_shown_ = true;
1160 base::TimeDelta time_to_first_show =
1161 base::TimeTicks::Now() - restore_started_;
1162 UMA_HISTOGRAM_CUSTOM_TIMES(
1163 "SessionRestore.TimeToFirstShow",
1164 time_to_first_show,
1165 base::TimeDelta::FromMilliseconds(10),
1166 base::TimeDelta::FromSeconds(1000),
1167 100);
1171 // Appends the urls in |urls| to |browser|.
1172 void AppendURLsToBrowser(Browser* browser,
1173 const std::vector<GURL>& urls) {
1174 for (size_t i = 0; i < urls.size(); ++i) {
1175 int add_types = TabStripModel::ADD_FORCE_INDEX;
1176 if (i == 0)
1177 add_types |= TabStripModel::ADD_ACTIVE;
1178 chrome::NavigateParams params(browser, urls[i],
1179 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
1180 params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
1181 params.tabstrip_add_types = add_types;
1182 chrome::Navigate(&params);
1186 // Invokes TabRestored on the SessionService for all tabs in browser after
1187 // initial_count.
1188 void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) {
1189 SessionService* session_service =
1190 SessionServiceFactory::GetForProfile(profile_);
1191 if (!session_service)
1192 return;
1193 TabStripModel* tab_strip = browser->tab_strip_model();
1194 for (int i = initial_count; i < tab_strip->count(); ++i)
1195 session_service->TabRestored(tab_strip->GetWebContentsAt(i),
1196 tab_strip->IsTabPinned(i));
1199 // The profile to create the sessions for.
1200 Profile* profile_;
1202 // The first browser to restore to, may be null.
1203 Browser* browser_;
1205 // The desktop on which all new browsers should be created (browser_, if it is
1206 // not NULL, must be of this desktop type as well).
1207 chrome::HostDesktopType host_desktop_type_;
1209 // Whether or not restore is synchronous.
1210 const bool synchronous_;
1212 // The quit-closure to terminate the nested message-loop started for
1213 // synchronous session-restore.
1214 base::Closure quit_closure_for_sync_restore_;
1216 // See description of CLOBBER_CURRENT_TAB.
1217 const bool clobber_existing_tab_;
1219 // If true and there is an error or there are no windows to restore, we
1220 // create a tabbed browser anyway. This is used on startup to make sure at
1221 // at least one window is created.
1222 const bool always_create_tabbed_browser_;
1224 // Set of URLs to open in addition to those restored from the session.
1225 std::vector<GURL> urls_to_open_;
1227 // Used to get the session.
1228 base::CancelableTaskTracker cancelable_task_tracker_;
1230 // Responsible for loading the tabs.
1231 scoped_refptr<TabLoader> tab_loader_;
1233 // When synchronous we run a nested message loop. To avoid creating windows
1234 // from the nested message loop (which can make exiting the nested message
1235 // loop take a while) we cache the SessionWindows here and create the actual
1236 // windows when the nested message loop exits.
1237 std::vector<sessions::SessionWindow*> windows_;
1238 SessionID::id_type active_window_id_;
1240 content::NotificationRegistrar registrar_;
1242 // The time we started the restore.
1243 base::TimeTicks restore_started_;
1245 // Set to true after the first browser is shown.
1246 bool browser_shown_;
1248 // List of callbacks for session restore notification.
1249 SessionRestore::CallbackList* on_session_restored_callbacks_;
1251 DISALLOW_COPY_AND_ASSIGN(SessionRestoreImpl);
1254 } // namespace
1256 // SessionRestore -------------------------------------------------------------
1258 // static
1259 Browser* SessionRestore::RestoreSession(
1260 Profile* profile,
1261 Browser* browser,
1262 chrome::HostDesktopType host_desktop_type,
1263 uint32 behavior,
1264 const std::vector<GURL>& urls_to_open) {
1265 #if defined(OS_CHROMEOS)
1266 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
1267 "SessionRestore-Start", false);
1268 #endif
1269 DCHECK(profile);
1270 // Always restore from the original profile (incognito profiles have no
1271 // session service).
1272 profile = profile->GetOriginalProfile();
1273 if (!SessionServiceFactory::GetForProfile(profile)) {
1274 NOTREACHED();
1275 return NULL;
1277 profile->set_restored_last_session(true);
1278 // SessionRestoreImpl takes care of deleting itself when done.
1279 SessionRestoreImpl* restorer = new SessionRestoreImpl(
1280 profile, browser, host_desktop_type, (behavior & SYNCHRONOUS) != 0,
1281 (behavior & CLOBBER_CURRENT_TAB) != 0,
1282 (behavior & ALWAYS_CREATE_TABBED_BROWSER) != 0,
1283 urls_to_open,
1284 SessionRestore::on_session_restored_callbacks());
1285 return restorer->Restore();
1288 // static
1289 void SessionRestore::RestoreSessionAfterCrash(Browser* browser) {
1290 uint32 behavior = 0;
1291 if (browser->tab_strip_model()->count() == 1) {
1292 const content::WebContents* active_tab =
1293 browser->tab_strip_model()->GetWebContentsAt(0);
1294 if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
1295 chrome::IsInstantNTP(active_tab)) {
1296 // There is only one tab and its the new tab page, make session restore
1297 // clobber it.
1298 behavior = SessionRestore::CLOBBER_CURRENT_TAB;
1301 SessionRestore::RestoreSession(browser->profile(), browser,
1302 browser->host_desktop_type(), behavior,
1303 std::vector<GURL>());
1306 // static
1307 std::vector<Browser*> SessionRestore::RestoreForeignSessionWindows(
1308 Profile* profile,
1309 chrome::HostDesktopType host_desktop_type,
1310 std::vector<const sessions::SessionWindow*>::const_iterator begin,
1311 std::vector<const sessions::SessionWindow*>::const_iterator end) {
1312 std::vector<GURL> gurls;
1313 SessionRestoreImpl restorer(profile,
1314 static_cast<Browser*>(NULL), host_desktop_type, true, false, true, gurls,
1315 on_session_restored_callbacks());
1316 return restorer.RestoreForeignSession(begin, end);
1319 // static
1320 WebContents* SessionRestore::RestoreForeignSessionTab(
1321 content::WebContents* source_web_contents,
1322 const sessions::SessionTab& tab,
1323 WindowOpenDisposition disposition) {
1324 Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents);
1325 Profile* profile = browser->profile();
1326 std::vector<GURL> gurls;
1327 SessionRestoreImpl restorer(profile, browser, browser->host_desktop_type(),
1328 true, false, false, gurls,
1329 on_session_restored_callbacks());
1330 return restorer.RestoreForeignTab(tab, disposition);
1333 // static
1334 bool SessionRestore::IsRestoring(const Profile* profile) {
1335 if (active_session_restorers == NULL)
1336 return false;
1337 for (std::set<SessionRestoreImpl*>::const_iterator it =
1338 active_session_restorers->begin();
1339 it != active_session_restorers->end(); ++it) {
1340 if ((*it)->profile() == profile)
1341 return true;
1343 return false;
1346 // static
1347 bool SessionRestore::IsRestoringSynchronously() {
1348 if (!active_session_restorers)
1349 return false;
1350 for (std::set<SessionRestoreImpl*>::const_iterator it =
1351 active_session_restorers->begin();
1352 it != active_session_restorers->end(); ++it) {
1353 if ((*it)->synchronous())
1354 return true;
1356 return false;
1359 // static
1360 SessionRestore::CallbackSubscription
1361 SessionRestore::RegisterOnSessionRestoredCallback(
1362 const base::Callback<void(int)>& callback) {
1363 return on_session_restored_callbacks()->Add(callback);
1366 // static
1367 base::CallbackList<void(int)>*
1368 SessionRestore::on_session_restored_callbacks_ = nullptr;