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"
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"
62 using content::NavigationController
;
63 using content::RenderWidgetHost
;
64 using content::WebContents
;
68 class SessionRestoreImpl
;
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
{
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.
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
;
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.
133 // Starts a timer to load load the next tab once expired before the current
134 // tab loading is finished.
137 // NotificationObserver method. Removes the specified tab and loads the next
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
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,
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
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.
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
);
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
);
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
);
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
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
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.
274 void TabLoader::SetTabLoadingEnabled(bool enable_tab_loading
) {
275 if (enable_tab_loading
== loading_enabled_
)
277 loading_enabled_
= enable_tab_loading
;
278 if (loading_enabled_
)
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),
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
307 if (!tabs_to_load_
.empty()) {
308 NavigationController
* tab
= tabs_to_load_
.front();
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();
317 Browser
* browser
= chrome::FindBrowserWithWebContents(contents
);
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())
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
) {
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
);
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());
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",
389 base::TimeDelta::FromMilliseconds(10),
390 base::TimeDelta::FromSeconds(100),
392 // Record a time for the number of tabs, to help track down
394 std::string time_for_count
= base::StringPrintf(
395 "SessionRestore.ForegroundTabFirstLoaded_%d", tab_count_
);
396 base::HistogramBase
* counter_for_count
=
397 base::Histogram::FactoryTimeGet(
399 base::TimeDelta::FromMilliseconds(10),
400 base::TimeDelta::FromSeconds(100),
402 base::Histogram::kUmaTargetedHistogramFlag
);
403 counter_for_count
->AddTime(time_to_load
);
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",
420 base::TimeDelta::FromMilliseconds(10),
421 base::TimeDelta::FromSeconds(100),
423 // Record a time for the number of tabs, to help track down
425 std::string time_for_count
= base::StringPrintf(
426 "SessionRestore.ForegroundTabFirstPaint_%d", tab_count_
);
427 base::HistogramBase
* counter_for_count
=
428 base::Histogram::FactoryTimeGet(
430 base::TimeDelta::FromMilliseconds(10),
431 base::TimeDelta::FromSeconds(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;
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;
481 RenderWidgetHost
* TabLoader::GetRenderWidgetHost(NavigationController
* tab
) {
482 WebContents
* web_contents
= tab
->GetWebContents();
484 content::RenderWidgetHostView
* render_widget_host_view
=
485 web_contents
->GetRenderWidgetHostView();
486 if (render_widget_host_view
)
487 return render_widget_host_view
->GetRenderWidgetHost();
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
));
502 void TabLoader::HandleTabClosedOrLoaded(NavigationController
* tab
) {
504 if (delegate_
&& loading_enabled_
)
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",
512 base::TimeDelta::FromMilliseconds(10),
513 base::TimeDelta::FromSeconds(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(
521 base::TimeDelta::FromMilliseconds(10),
522 base::TimeDelta::FromSeconds(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
) !=
536 const bool in_tabs_loading
=
537 find(tabs_loading_
.begin(), tabs_loading_
.end(), controller
) !=
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
560 if (tabs_to_load_
.empty())
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.
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
{
581 SessionRestoreImpl(Profile
* profile
,
583 chrome::HostDesktopType host_desktop_type
,
585 bool clobber_existing_tab
,
586 bool always_create_tabbed_browser
,
587 const std::vector
<GURL
>& urls_to_open
,
588 SessionRestore::CallbackList
* callbacks
)
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
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
)
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_
; }
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_
);
637 base::MessageLoop::ScopedNestableTaskAllower
allow(
638 base::MessageLoop::current());
640 quit_closure_for_sync_restore_
= loop
.QuitClosure();
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
);
656 registrar_
.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED
,
657 content::Source
<Browser
>(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
) {
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
;
672 Browser
* browser
= CreateRestoredBrowser(
673 BrowserTypeForWindowType((*i
)->type
),
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
,
687 NotifySessionServiceOfRestoredTabs(browser
, initial_tab_count
);
690 // Always create in a new window
691 FinishedTabCreation(true, true);
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_
)) :
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
,
723 tab
.extension_app_id
,
725 tab
.user_agent_override
);
728 use_new_window
? 0 : browser
->tab_strip_model()->active_index() + 1;
729 web_contents
= chrome::AddRestoredTab(
734 tab
.extension_app_id
,
735 disposition
== NEW_FOREGROUND_TAB
, // selected
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_
);
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
{
773 case chrome::NOTIFICATION_BROWSER_CLOSED
:
783 Profile
* profile() { return profile_
; }
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
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();
817 DCHECK(tab_loader_
.get());
818 // TabLoader deletes itself when done loading.
819 tab_loader_
->StartLoading();
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
834 registrar_
.RemoveAll();
837 #if defined(OS_CHROMEOS)
838 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
839 "SessionRestore-End", false);
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),
854 #if defined(OS_CHROMEOS)
855 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
856 "SessionRestore-GotSession", false);
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();
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),
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);
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.
926 #if defined(OS_CHROMEOS)
927 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
928 "SessionRestore-CreateRestoredBrowser-Start", false);
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
),
941 #if defined(OS_CHROMEOS)
942 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
943 "SessionRestore-CreateRestoredBrowser-End", false);
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() &&
954 sessions::SessionWindow::TYPE_TABBED
&&
955 active_tab
&& browser
== browser_
&&
956 (*i
)->tabs
.size() > 0;
957 if (close_active_tab
)
959 int selected_tab_index
=
960 initial_tab_count
> 0 ? browser
->tab_strip_model()->active_index()
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
,
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);
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
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
);
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
,
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.
1046 // If this isn't the selected tab, there's nothing else to do.
1047 if (!is_selected_tab
)
1052 browser
->tab_strip_model()->GetIndexOfWebContents(restored_tab
));
1053 // TODO(sky): remove. For debugging 368236.
1054 CHECK_EQ(browser
->tab_strip_model()->GetActiveWebContents(),
1056 tab_loader_
->TabIsLoading(&browser
->tab_strip_model()
1057 ->GetActiveWebContents()
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
1077 WebContents
* RestoreTab(const sessions::SessionTab
& tab
,
1078 const int tab_index
,
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())
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
,
1108 tab
.extension_app_id
,
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
,
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
,
1134 host_desktop_type_
);
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
) {
1145 DCHECK(browser
->tab_strip_model()->count());
1146 browser
->tab_strip_model()->ActivateTabAt(selected_tab_index
, true);
1148 if (browser_
== browser
)
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",
1165 base::TimeDelta::FromMilliseconds(10),
1166 base::TimeDelta::FromSeconds(1000),
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
;
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(¶ms
);
1186 // Invokes TabRestored on the SessionService for all tabs in browser after
1188 void NotifySessionServiceOfRestoredTabs(Browser
* browser
, int initial_count
) {
1189 SessionService
* session_service
=
1190 SessionServiceFactory::GetForProfile(profile_
);
1191 if (!session_service
)
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.
1202 // The first browser to restore to, may be null.
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
);
1256 // SessionRestore -------------------------------------------------------------
1259 Browser
* SessionRestore::RestoreSession(
1262 chrome::HostDesktopType host_desktop_type
,
1264 const std::vector
<GURL
>& urls_to_open
) {
1265 #if defined(OS_CHROMEOS)
1266 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
1267 "SessionRestore-Start", false);
1270 // Always restore from the original profile (incognito profiles have no
1271 // session service).
1272 profile
= profile
->GetOriginalProfile();
1273 if (!SessionServiceFactory::GetForProfile(profile
)) {
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,
1284 SessionRestore::on_session_restored_callbacks());
1285 return restorer
->Restore();
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
1298 behavior
= SessionRestore::CLOBBER_CURRENT_TAB
;
1301 SessionRestore::RestoreSession(browser
->profile(), browser
,
1302 browser
->host_desktop_type(), behavior
,
1303 std::vector
<GURL
>());
1307 std::vector
<Browser
*> SessionRestore::RestoreForeignSessionWindows(
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
);
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
);
1334 bool SessionRestore::IsRestoring(const Profile
* profile
) {
1335 if (active_session_restorers
== NULL
)
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
)
1347 bool SessionRestore::IsRestoringSynchronously() {
1348 if (!active_session_restorers
)
1350 for (std::set
<SessionRestoreImpl
*>::const_iterator it
=
1351 active_session_restorers
->begin();
1352 it
!= active_session_restorers
->end(); ++it
) {
1353 if ((*it
)->synchronous())
1360 SessionRestore::CallbackSubscription
1361 SessionRestore::RegisterOnSessionRestoredCallback(
1362 const base::Callback
<void(int)>& callback
) {
1363 return on_session_restored_callbacks()->Add(callback
);
1367 base::CallbackList
<void(int)>*
1368 SessionRestore::on_session_restored_callbacks_
= nullptr;