Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / sessions / session_restore.cc
blob82d6432b38bc273c043928e2093f387a7f7fa0f1
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/scoped_ptr.h"
18 #include "base/memory/scoped_vector.h"
19 #include "base/metrics/histogram.h"
20 #include "base/run_loop.h"
21 #include "base/stl_util.h"
22 #include "base/task/cancelable_task_tracker.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/search/search.h"
27 #include "chrome/browser/sessions/session_restore_delegate.h"
28 #include "chrome/browser/sessions/session_service.h"
29 #include "chrome/browser/sessions/session_service_factory.h"
30 #include "chrome/browser/sessions/session_service_utils.h"
31 #include "chrome/browser/sessions/tab_loader.h"
32 #include "chrome/browser/ui/browser.h"
33 #include "chrome/browser/ui/browser_finder.h"
34 #include "chrome/browser/ui/browser_navigator.h"
35 #include "chrome/browser/ui/browser_tabrestore.h"
36 #include "chrome/browser/ui/browser_tabstrip.h"
37 #include "chrome/browser/ui/browser_window.h"
38 #include "chrome/browser/ui/tabs/tab_strip_model.h"
39 #include "chrome/common/extensions/extension_metrics.h"
40 #include "chrome/common/url_constants.h"
41 #include "components/sessions/session_types.h"
42 #include "content/public/browser/child_process_security_policy.h"
43 #include "content/public/browser/dom_storage_context.h"
44 #include "content/public/browser/navigation_controller.h"
45 #include "content/public/browser/notification_registrar.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/render_process_host.h"
48 #include "content/public/browser/render_widget_host.h"
49 #include "content/public/browser/render_widget_host_view.h"
50 #include "content/public/browser/session_storage_namespace.h"
51 #include "content/public/browser/storage_partition.h"
52 #include "content/public/browser/web_contents.h"
53 #include "content/public/common/page_state.h"
54 #include "extensions/browser/extension_registry.h"
55 #include "extensions/common/extension_set.h"
57 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/chromeos/boot_times_recorder.h"
59 #endif
61 using content::NavigationController;
62 using content::RenderWidgetHost;
63 using content::WebContents;
64 using RestoredTab = SessionRestoreDelegate::RestoredTab;
66 namespace {
68 class SessionRestoreImpl;
70 // Pointers to SessionRestoreImpls which are currently restoring the session.
71 std::set<SessionRestoreImpl*>* active_session_restorers = nullptr;
73 // SessionRestoreImpl ---------------------------------------------------------
75 // SessionRestoreImpl is responsible for fetching the set of tabs to create
76 // from SessionService. SessionRestoreImpl deletes itself when done.
78 class SessionRestoreImpl : public content::NotificationObserver {
79 public:
80 SessionRestoreImpl(Profile* profile,
81 Browser* browser,
82 chrome::HostDesktopType host_desktop_type,
83 bool synchronous,
84 bool clobber_existing_tab,
85 bool always_create_tabbed_browser,
86 const std::vector<GURL>& urls_to_open,
87 SessionRestore::CallbackList* callbacks)
88 : profile_(profile),
89 browser_(browser),
90 host_desktop_type_(host_desktop_type),
91 synchronous_(synchronous),
92 clobber_existing_tab_(clobber_existing_tab),
93 always_create_tabbed_browser_(always_create_tabbed_browser),
94 urls_to_open_(urls_to_open),
95 active_window_id_(0),
96 restore_started_(base::TimeTicks::Now()),
97 on_session_restored_callbacks_(callbacks) {
98 // For sanity's sake, if |browser| is non-null: force |host_desktop_type| to
99 // be the same as |browser|'s desktop type.
100 DCHECK(!browser || browser->host_desktop_type() == host_desktop_type);
102 if (active_session_restorers == nullptr)
103 active_session_restorers = new std::set<SessionRestoreImpl*>();
105 // Only one SessionRestoreImpl should be operating on the profile at the
106 // same time.
107 std::set<SessionRestoreImpl*>::const_iterator it;
108 for (it = active_session_restorers->begin();
109 it != active_session_restorers->end(); ++it) {
110 if ((*it)->profile_ == profile)
111 break;
113 DCHECK(it == active_session_restorers->end());
115 active_session_restorers->insert(this);
117 // When asynchronous its possible for there to be no windows. To make sure
118 // Chrome doesn't prematurely exit AddRef the process. We'll release in the
119 // destructor when restore is done.
120 g_browser_process->AddRefModule();
123 bool synchronous() const { return synchronous_; }
125 Browser* Restore() {
126 SessionService* session_service =
127 SessionServiceFactory::GetForProfile(profile_);
128 DCHECK(session_service);
129 session_service->GetLastSession(
130 base::Bind(&SessionRestoreImpl::OnGotSession, base::Unretained(this)),
131 &cancelable_task_tracker_);
133 if (synchronous_) {
135 base::MessageLoop::ScopedNestableTaskAllower allow(
136 base::MessageLoop::current());
137 base::RunLoop loop;
138 quit_closure_for_sync_restore_ = loop.QuitClosure();
139 loop.Run();
140 quit_closure_for_sync_restore_ = base::Closure();
142 Browser* browser =
143 ProcessSessionWindowsAndNotify(&windows_, active_window_id_);
144 delete this;
145 return browser;
148 if (browser_) {
149 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
150 content::Source<Browser>(browser_));
153 return browser_;
156 // Restore window(s) from a foreign session. Returns newly created Browsers.
157 std::vector<Browser*> RestoreForeignSession(
158 std::vector<const sessions::SessionWindow*>::const_iterator begin,
159 std::vector<const sessions::SessionWindow*>::const_iterator end) {
160 std::vector<Browser*> browsers;
161 std::vector<RestoredTab> created_contents;
162 // Create a browser instance to put the restored tabs in.
163 for (std::vector<const sessions::SessionWindow*>::const_iterator i = begin;
164 i != end; ++i) {
165 Browser* browser =
166 CreateRestoredBrowser(BrowserTypeForWindowType((*i)->type),
167 (*i)->bounds, (*i)->show_state, (*i)->app_name);
168 browsers.push_back(browser);
170 // Restore and show the browser.
171 const int initial_tab_count = 0;
172 int selected_tab_index =
173 std::max(0, std::min((*i)->selected_tab_index,
174 static_cast<int>((*i)->tabs.size()) - 1));
175 RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
176 selected_tab_index, &created_contents);
177 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
180 // Always create in a new window.
181 FinishedTabCreation(true, true, created_contents);
183 on_session_restored_callbacks_->Notify(
184 static_cast<int>(created_contents.size()));
186 return browsers;
189 // Restore a single tab from a foreign session.
190 // Opens in the tab in the last active browser, unless disposition is
191 // NEW_WINDOW, in which case the tab will be opened in a new browser. Returns
192 // the WebContents of the restored tab.
193 WebContents* RestoreForeignTab(const sessions::SessionTab& tab,
194 WindowOpenDisposition disposition) {
195 DCHECK(!tab.navigations.empty());
196 int selected_index = tab.current_navigation_index;
197 selected_index = std::max(
199 std::min(selected_index, static_cast<int>(tab.navigations.size() - 1)));
201 bool use_new_window = disposition == NEW_WINDOW;
203 Browser* browser =
204 use_new_window
205 ? new Browser(Browser::CreateParams(profile_, host_desktop_type_))
206 : browser_;
208 RecordAppLaunchForTab(browser, tab, selected_index);
210 WebContents* web_contents;
211 if (disposition == CURRENT_TAB) {
212 DCHECK(!use_new_window);
213 web_contents = chrome::ReplaceRestoredTab(
214 browser, tab.navigations, selected_index, true, tab.extension_app_id,
215 nullptr, tab.user_agent_override);
216 } else {
217 int tab_index =
218 use_new_window ? 0 : browser->tab_strip_model()->active_index() + 1;
219 web_contents = chrome::AddRestoredTab(
220 browser, tab.navigations, tab_index, selected_index,
221 tab.extension_app_id,
222 disposition == NEW_FOREGROUND_TAB, // selected
223 tab.pinned, true, nullptr, tab.user_agent_override);
224 // Start loading the tab immediately.
225 web_contents->GetController().LoadIfNecessary();
228 if (use_new_window) {
229 browser->tab_strip_model()->ActivateTabAt(0, true);
230 browser->window()->Show();
232 NotifySessionServiceOfRestoredTabs(browser,
233 browser->tab_strip_model()->count());
235 // Since FinishedTabCreation() is not called here, |this| will leak if we
236 // are not in sychronous mode.
237 DCHECK(synchronous_);
239 on_session_restored_callbacks_->Notify(1);
241 return web_contents;
244 ~SessionRestoreImpl() override {
245 STLDeleteElements(&windows_);
247 active_session_restorers->erase(this);
248 if (active_session_restorers->empty()) {
249 delete active_session_restorers;
250 active_session_restorers = nullptr;
253 g_browser_process->ReleaseModule();
256 void Observe(int type,
257 const content::NotificationSource& source,
258 const content::NotificationDetails& details) override {
259 switch (type) {
260 case chrome::NOTIFICATION_BROWSER_CLOSED:
261 delete this;
262 return;
264 default:
265 NOTREACHED();
266 break;
270 Profile* profile() { return profile_; }
272 private:
273 // Invoked when done with creating all the tabs/browsers.
275 // |created_tabbed_browser| indicates whether a tabbed browser was created,
276 // or we used an existing tabbed browser.
278 // If successful, this begins loading tabs and deletes itself when all tabs
279 // have been loaded.
281 // Returns the Browser that was created, if any.
282 Browser* FinishedTabCreation(
283 bool succeeded,
284 bool created_tabbed_browser,
285 const std::vector<RestoredTab>& contents_created) {
286 Browser* browser = nullptr;
287 if (!created_tabbed_browser && always_create_tabbed_browser_) {
288 browser =
289 new Browser(Browser::CreateParams(profile_, host_desktop_type_));
290 if (urls_to_open_.empty()) {
291 // No tab browsers were created and no URLs were supplied on the command
292 // line. Open the new tab page.
293 urls_to_open_.push_back(GURL(chrome::kChromeUINewTabURL));
295 AppendURLsToBrowser(browser, urls_to_open_);
296 browser->window()->Show();
299 if (succeeded) {
300 // Start Loading tabs.
301 SessionRestoreDelegate::RestoreTabs(contents_created, restore_started_);
304 if (!synchronous_) {
305 // If we're not synchronous we need to delete ourself.
306 // NOTE: we must use DeleteLater here as most likely we're in a callback
307 // from the history service which doesn't deal well with deleting the
308 // object it is notifying.
309 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
311 // The delete may take a while and at this point we no longer care about
312 // if the browser is deleted. Don't listen to anything. This avoid a
313 // possible double delete too (if browser is closed before DeleteSoon() is
314 // processed).
315 registrar_.RemoveAll();
318 #if defined(OS_CHROMEOS)
319 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker("SessionRestore-End",
320 false);
321 #endif
322 return browser;
325 void OnGotSession(ScopedVector<sessions::SessionWindow> windows,
326 SessionID::id_type active_window_id) {
327 #if defined(OS_CHROMEOS)
328 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
329 "SessionRestore-GotSession", false);
330 #endif
331 if (synchronous_) {
332 // See comment above windows_ as to why we don't process immediately.
333 windows_.swap(windows.get());
334 active_window_id_ = active_window_id;
335 CHECK(!quit_closure_for_sync_restore_.is_null());
336 quit_closure_for_sync_restore_.Run();
337 return;
340 ProcessSessionWindowsAndNotify(&windows.get(), active_window_id);
343 Browser* ProcessSessionWindowsAndNotify(
344 std::vector<sessions::SessionWindow*>* windows,
345 SessionID::id_type active_window_id) {
346 std::vector<RestoredTab> contents;
347 Browser* result =
348 ProcessSessionWindows(windows, active_window_id, &contents);
349 on_session_restored_callbacks_->Notify(static_cast<int>(contents.size()));
350 return result;
353 Browser* ProcessSessionWindows(std::vector<sessions::SessionWindow*>* windows,
354 SessionID::id_type active_window_id,
355 std::vector<RestoredTab>* created_contents) {
356 DVLOG(1) << "ProcessSessionWindows " << windows->size();
358 if (windows->empty()) {
359 // Restore was unsuccessful. The DOM storage system can also delete its
360 // data, since no session restore will happen at a later point in time.
361 content::BrowserContext::GetDefaultStoragePartition(profile_)
362 ->GetDOMStorageContext()
363 ->StartScavengingUnusedSessionStorage();
364 return FinishedTabCreation(false, false, *created_contents);
367 #if defined(OS_CHROMEOS)
368 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
369 "SessionRestore-CreatingTabs-Start", false);
370 #endif
372 // After the for loop this contains the last TABBED_BROWSER. Is null if no
373 // tabbed browsers exist.
374 Browser* last_browser = nullptr;
375 bool has_tabbed_browser = false;
377 // After the for loop, this contains the browser to activate, if one of the
378 // windows has the same id as specified in active_window_id.
379 Browser* browser_to_activate = nullptr;
381 // Determine if there is a visible window.
382 bool has_visible_browser = false;
383 for (std::vector<sessions::SessionWindow*>::iterator i = windows->begin();
384 i != windows->end(); ++i) {
385 if ((*i)->show_state != ui::SHOW_STATE_MINIMIZED)
386 has_visible_browser = true;
389 for (std::vector<sessions::SessionWindow*>::iterator i = windows->begin();
390 i != windows->end(); ++i) {
391 Browser* browser = nullptr;
392 if (!has_tabbed_browser &&
393 (*i)->type == sessions::SessionWindow::TYPE_TABBED)
394 has_tabbed_browser = true;
395 if (i == windows->begin() &&
396 (*i)->type == sessions::SessionWindow::TYPE_TABBED && browser_ &&
397 browser_->is_type_tabbed() &&
398 !browser_->profile()->IsOffTheRecord()) {
399 // The first set of tabs is added to the existing browser.
400 browser = browser_;
401 } else {
402 #if defined(OS_CHROMEOS)
403 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
404 "SessionRestore-CreateRestoredBrowser-Start", false);
405 #endif
406 // Show the first window if none are visible.
407 ui::WindowShowState show_state = (*i)->show_state;
408 if (!has_visible_browser) {
409 show_state = ui::SHOW_STATE_NORMAL;
410 has_visible_browser = true;
412 browser =
413 CreateRestoredBrowser(BrowserTypeForWindowType((*i)->type),
414 (*i)->bounds, show_state, (*i)->app_name);
415 #if defined(OS_CHROMEOS)
416 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
417 "SessionRestore-CreateRestoredBrowser-End", false);
418 #endif
420 if ((*i)->type == sessions::SessionWindow::TYPE_TABBED)
421 last_browser = browser;
422 WebContents* active_tab =
423 browser->tab_strip_model()->GetActiveWebContents();
424 int initial_tab_count = browser->tab_strip_model()->count();
425 bool close_active_tab =
426 clobber_existing_tab_ && i == windows->begin() &&
427 (*i)->type == sessions::SessionWindow::TYPE_TABBED && active_tab &&
428 browser == browser_ && (*i)->tabs.size() > 0;
429 if (close_active_tab)
430 --initial_tab_count;
431 int selected_tab_index =
432 initial_tab_count > 0
433 ? browser->tab_strip_model()->active_index()
434 : std::max(0, std::min((*i)->selected_tab_index,
435 static_cast<int>((*i)->tabs.size()) - 1));
436 if ((*i)->window_id.id() == active_window_id)
437 browser_to_activate = browser;
439 RestoreTabsToBrowser(*(*i), browser, initial_tab_count,
440 selected_tab_index, created_contents);
441 NotifySessionServiceOfRestoredTabs(browser, initial_tab_count);
442 // This needs to be done after restore because closing the last tab will
443 // close the whole window.
444 if (close_active_tab)
445 chrome::CloseWebContents(browser, active_tab, true);
448 if (browser_to_activate && browser_to_activate->is_type_tabbed())
449 last_browser = browser_to_activate;
451 if (last_browser && !urls_to_open_.empty())
452 AppendURLsToBrowser(last_browser, urls_to_open_);
453 #if defined(OS_CHROMEOS)
454 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
455 "SessionRestore-CreatingTabs-End", false);
456 #endif
457 if (browser_to_activate)
458 browser_to_activate->window()->Activate();
460 // If last_browser is NULL and urls_to_open_ is non-empty,
461 // FinishedTabCreation will create a new TabbedBrowser and add the urls to
462 // it.
463 Browser* finished_browser =
464 FinishedTabCreation(true, has_tabbed_browser, *created_contents);
465 if (finished_browser)
466 last_browser = finished_browser;
468 // sessionStorages needed for the session restore have now been recreated
469 // by RestoreTab. Now it's safe for the DOM storage system to start
470 // deleting leftover data.
471 content::BrowserContext::GetDefaultStoragePartition(profile_)
472 ->GetDOMStorageContext()
473 ->StartScavengingUnusedSessionStorage();
474 return last_browser;
477 // Record an app launch event (if appropriate) for a tab which is about to
478 // be restored. Callers should ensure that selected_index is within the
479 // bounds of tab.navigations before calling.
480 void RecordAppLaunchForTab(Browser* browser,
481 const sessions::SessionTab& tab,
482 int selected_index) {
483 DCHECK(selected_index >= 0 &&
484 selected_index < static_cast<int>(tab.navigations.size()));
485 GURL url = tab.navigations[selected_index].virtual_url();
486 const extensions::Extension* extension =
487 extensions::ExtensionRegistry::Get(profile())
488 ->enabled_extensions()
489 .GetAppByURL(url);
490 if (extension) {
491 extensions::RecordAppLaunchType(
492 extension_misc::APP_LAUNCH_SESSION_RESTORE, extension->GetType());
496 // Adds the tabs from |window| to |browser|. Normal tabs go after the existing
497 // tabs but pinned tabs will be pushed in front.
498 // If there are no existing tabs, the tab at |selected_tab_index| will be
499 // selected. Otherwise, the tab selection will remain untouched.
500 void RestoreTabsToBrowser(const sessions::SessionWindow& window,
501 Browser* browser,
502 int initial_tab_count,
503 int selected_tab_index,
504 std::vector<RestoredTab>* created_contents) {
505 DVLOG(1) << "RestoreTabsToBrowser " << window.tabs.size();
506 DCHECK(!window.tabs.empty());
507 if (initial_tab_count == 0) {
508 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
509 const sessions::SessionTab& tab = *(window.tabs[i]);
511 // Loads are scheduled for each restored tab unless the tab is going to
512 // be selected as ShowBrowser() will load the selected tab.
513 bool is_selected_tab = (i == selected_tab_index);
514 WebContents* contents = RestoreTab(tab, i, browser, is_selected_tab);
516 // RestoreTab can return nullptr if |tab| doesn't have valid data.
517 if (!contents)
518 continue;
520 RestoredTab restored_tab;
521 restored_tab.contents = contents;
522 restored_tab.is_active = is_selected_tab;
523 created_contents->push_back(restored_tab);
525 // If this isn't the selected tab, there's nothing else to do.
526 if (!is_selected_tab)
527 continue;
529 ShowBrowser(browser, browser->tab_strip_model()->GetIndexOfWebContents(
530 contents));
531 // TODO(sky): remove. For debugging 368236.
532 CHECK_EQ(browser->tab_strip_model()->GetActiveWebContents(), contents);
534 } else {
535 // If the browser already has tabs, we want to restore the new ones after
536 // the existing ones. E.g. this happens in Win8 Metro where we merge
537 // windows or when launching a hosted app from the app launcher.
538 int tab_index_offset = initial_tab_count;
539 for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
540 const sessions::SessionTab& tab = *(window.tabs[i]);
541 // Always schedule loads as we will not be calling ShowBrowser().
542 WebContents* contents =
543 RestoreTab(tab, tab_index_offset + i, browser, false);
544 if (contents) {
545 RestoredTab restored_tab;
546 restored_tab.contents = contents;
547 restored_tab.is_active = false;
548 created_contents->push_back(restored_tab);
554 // |tab_index| is ignored for pinned tabs which will always be pushed behind
555 // the last existing pinned tab.
556 // |tab_loader_| will schedule this tab for loading if |is_selected_tab| is
557 // false.
558 WebContents* RestoreTab(const sessions::SessionTab& tab,
559 const int tab_index,
560 Browser* browser,
561 bool is_selected_tab) {
562 // It's possible (particularly for foreign sessions) to receive a tab
563 // without valid navigations. In that case, just skip it.
564 // See crbug.com/154129.
565 if (tab.navigations.empty())
566 return nullptr;
567 int selected_index = tab.current_navigation_index;
568 selected_index = std::max(
570 std::min(selected_index, static_cast<int>(tab.navigations.size() - 1)));
572 RecordAppLaunchForTab(browser, tab, selected_index);
574 // Associate sessionStorage (if any) to the restored tab.
575 scoped_refptr<content::SessionStorageNamespace> session_storage_namespace;
576 if (!tab.session_storage_persistent_id.empty()) {
577 session_storage_namespace =
578 content::BrowserContext::GetDefaultStoragePartition(profile_)
579 ->GetDOMStorageContext()
580 ->RecreateSessionStorage(tab.session_storage_persistent_id);
583 WebContents* web_contents = chrome::AddRestoredTab(
584 browser, tab.navigations, tab_index, selected_index,
585 tab.extension_app_id,
586 false, // select
587 tab.pinned, true, session_storage_namespace.get(),
588 tab.user_agent_override);
589 // Regression check: check that the tab didn't start loading right away. The
590 // focused tab will be loaded by Browser, and TabLoader will load the rest.
591 DCHECK(web_contents->GetController().NeedsReload());
593 return web_contents;
596 Browser* CreateRestoredBrowser(Browser::Type type,
597 gfx::Rect bounds,
598 ui::WindowShowState show_state,
599 const std::string& app_name) {
600 Browser::CreateParams params(type, profile_, host_desktop_type_);
601 if (!app_name.empty()) {
602 const bool trusted_source = true; // We only store trusted app windows.
603 params = Browser::CreateParams::CreateForApp(
604 app_name, trusted_source, bounds, profile_, host_desktop_type_);
605 } else {
606 params.initial_bounds = bounds;
608 params.initial_show_state = show_state;
609 params.is_session_restore = true;
610 return new Browser(params);
613 void ShowBrowser(Browser* browser, int selected_tab_index) {
614 DCHECK(browser);
615 DCHECK(browser->tab_strip_model()->count());
616 browser->tab_strip_model()->ActivateTabAt(selected_tab_index, true);
618 if (browser_ == browser)
619 return;
621 browser->window()->Show();
622 browser->set_is_session_restore(false);
624 // TODO(jcampan): http://crbug.com/8123 we should not need to set the
625 // initial focus explicitly.
626 browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus();
629 // Appends the urls in |urls| to |browser|.
630 void AppendURLsToBrowser(Browser* browser, const std::vector<GURL>& urls) {
631 for (size_t i = 0; i < urls.size(); ++i) {
632 int add_types = TabStripModel::ADD_FORCE_INDEX;
633 if (i == 0)
634 add_types |= TabStripModel::ADD_ACTIVE;
635 chrome::NavigateParams params(browser, urls[i],
636 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
637 params.disposition = i == 0 ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
638 params.tabstrip_add_types = add_types;
639 chrome::Navigate(&params);
643 // Invokes TabRestored on the SessionService for all tabs in browser after
644 // initial_count.
645 void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) {
646 SessionService* session_service =
647 SessionServiceFactory::GetForProfile(profile_);
648 if (!session_service)
649 return;
650 TabStripModel* tab_strip = browser->tab_strip_model();
651 for (int i = initial_count; i < tab_strip->count(); ++i)
652 session_service->TabRestored(tab_strip->GetWebContentsAt(i),
653 tab_strip->IsTabPinned(i));
656 // The profile to create the sessions for.
657 Profile* profile_;
659 // The first browser to restore to, may be null.
660 Browser* browser_;
662 // The desktop on which all new browsers should be created (browser_, if it is
663 // not NULL, must be of this desktop type as well).
664 chrome::HostDesktopType host_desktop_type_;
666 // Whether or not restore is synchronous.
667 const bool synchronous_;
669 // The quit-closure to terminate the nested message-loop started for
670 // synchronous session-restore.
671 base::Closure quit_closure_for_sync_restore_;
673 // See description of CLOBBER_CURRENT_TAB.
674 const bool clobber_existing_tab_;
676 // If true and there is an error or there are no windows to restore, we
677 // create a tabbed browser anyway. This is used on startup to make sure at
678 // at least one window is created.
679 const bool always_create_tabbed_browser_;
681 // Set of URLs to open in addition to those restored from the session.
682 std::vector<GURL> urls_to_open_;
684 // Used to get the session.
685 base::CancelableTaskTracker cancelable_task_tracker_;
687 // Responsible for loading the tabs.
688 scoped_refptr<TabLoader> tab_loader_;
690 // When synchronous we run a nested message loop. To avoid creating windows
691 // from the nested message loop (which can make exiting the nested message
692 // loop take a while) we cache the SessionWindows here and create the actual
693 // windows when the nested message loop exits.
694 std::vector<sessions::SessionWindow*> windows_;
695 SessionID::id_type active_window_id_;
697 content::NotificationRegistrar registrar_;
699 // The time we started the restore.
700 base::TimeTicks restore_started_;
702 // List of callbacks for session restore notification.
703 SessionRestore::CallbackList* on_session_restored_callbacks_;
705 DISALLOW_COPY_AND_ASSIGN(SessionRestoreImpl);
708 } // namespace
710 // SessionRestore -------------------------------------------------------------
712 // static
713 Browser* SessionRestore::RestoreSession(
714 Profile* profile,
715 Browser* browser,
716 chrome::HostDesktopType host_desktop_type,
717 uint32 behavior,
718 const std::vector<GURL>& urls_to_open) {
719 #if defined(OS_CHROMEOS)
720 chromeos::BootTimesRecorder::Get()->AddLoginTimeMarker(
721 "SessionRestore-Start", false);
722 #endif
723 DCHECK(profile);
724 // Always restore from the original profile (incognito profiles have no
725 // session service).
726 profile = profile->GetOriginalProfile();
727 if (!SessionServiceFactory::GetForProfile(profile)) {
728 NOTREACHED();
729 return nullptr;
731 profile->set_restored_last_session(true);
732 // SessionRestoreImpl takes care of deleting itself when done.
733 SessionRestoreImpl* restorer = new SessionRestoreImpl(
734 profile, browser, host_desktop_type, (behavior & SYNCHRONOUS) != 0,
735 (behavior & CLOBBER_CURRENT_TAB) != 0,
736 (behavior & ALWAYS_CREATE_TABBED_BROWSER) != 0,
737 urls_to_open,
738 SessionRestore::on_session_restored_callbacks());
739 return restorer->Restore();
742 // static
743 void SessionRestore::RestoreSessionAfterCrash(Browser* browser) {
744 uint32 behavior = 0;
745 if (browser->tab_strip_model()->count() == 1) {
746 const content::WebContents* active_tab =
747 browser->tab_strip_model()->GetWebContentsAt(0);
748 if (active_tab->GetURL() == GURL(chrome::kChromeUINewTabURL) ||
749 chrome::IsInstantNTP(active_tab)) {
750 // There is only one tab and its the new tab page, make session restore
751 // clobber it.
752 behavior = SessionRestore::CLOBBER_CURRENT_TAB;
755 SessionRestore::RestoreSession(browser->profile(), browser,
756 browser->host_desktop_type(), behavior,
757 std::vector<GURL>());
760 // static
761 std::vector<Browser*> SessionRestore::RestoreForeignSessionWindows(
762 Profile* profile,
763 chrome::HostDesktopType host_desktop_type,
764 std::vector<const sessions::SessionWindow*>::const_iterator begin,
765 std::vector<const sessions::SessionWindow*>::const_iterator end) {
766 std::vector<GURL> gurls;
767 SessionRestoreImpl restorer(profile, static_cast<Browser*>(nullptr),
768 host_desktop_type, true, false, true, gurls,
769 on_session_restored_callbacks());
770 return restorer.RestoreForeignSession(begin, end);
773 // static
774 WebContents* SessionRestore::RestoreForeignSessionTab(
775 content::WebContents* source_web_contents,
776 const sessions::SessionTab& tab,
777 WindowOpenDisposition disposition) {
778 Browser* browser = chrome::FindBrowserWithWebContents(source_web_contents);
779 Profile* profile = browser->profile();
780 std::vector<GURL> gurls;
781 SessionRestoreImpl restorer(profile, browser, browser->host_desktop_type(),
782 true, false, false, gurls,
783 on_session_restored_callbacks());
784 return restorer.RestoreForeignTab(tab, disposition);
787 // static
788 bool SessionRestore::IsRestoring(const Profile* profile) {
789 if (active_session_restorers == nullptr)
790 return false;
791 for (std::set<SessionRestoreImpl*>::const_iterator it =
792 active_session_restorers->begin();
793 it != active_session_restorers->end(); ++it) {
794 if ((*it)->profile() == profile)
795 return true;
797 return false;
800 // static
801 bool SessionRestore::IsRestoringSynchronously() {
802 if (!active_session_restorers)
803 return false;
804 for (std::set<SessionRestoreImpl*>::const_iterator it =
805 active_session_restorers->begin();
806 it != active_session_restorers->end(); ++it) {
807 if ((*it)->synchronous())
808 return true;
810 return false;
813 // static
814 SessionRestore::CallbackSubscription
815 SessionRestore::RegisterOnSessionRestoredCallback(
816 const base::Callback<void(int)>& callback) {
817 return on_session_restored_callbacks()->Add(callback);
820 // static
821 base::CallbackList<void(int)>*
822 SessionRestore::on_session_restored_callbacks_ = nullptr;