browser_tabrestore.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/browser_tabrestore.h"
6
7#include "chrome/browser/extensions/tab_helper.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/sessions/session_service.h"
10#include "chrome/browser/sessions/session_service_factory.h"
11#include "chrome/browser/tab_contents/tab_util.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_window.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "content/public/browser/navigation_controller.h"
16#include "content/public/browser/navigation_entry.h"
17#include "content/public/browser/session_storage_namespace.h"
18#include "content/public/browser/web_contents.h"
19#include "content/public/browser/web_contents_view.h"
20
21using content::WebContents;
22using content::NavigationController;
23using content::NavigationEntry;
24using sessions::SerializedNavigationEntry;
25
26namespace chrome {
27
28namespace {
29
30NavigationController::RestoreType GetRestoreType(Browser* browser,
31                                                 bool from_last_session) {
32  if (!from_last_session)
33    return NavigationController::RESTORE_CURRENT_SESSION;
34  return browser->profile()->GetLastSessionExitType() == Profile::EXIT_CRASHED ?
35      NavigationController::RESTORE_LAST_SESSION_CRASHED :
36      NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY;
37}
38
39WebContents* CreateRestoredTab(
40    Browser* browser,
41    const std::vector<SerializedNavigationEntry>& navigations,
42    int selected_navigation,
43    const std::string& extension_app_id,
44    bool from_last_session,
45    content::SessionStorageNamespace* session_storage_namespace,
46    const std::string& user_agent_override) {
47  GURL restore_url = navigations.at(selected_navigation).virtual_url();
48  // TODO(ajwong): Remove the temporary session_storage_namespace_map when
49  // we teach session restore to understand that one tab can have multiple
50  // SessionStorageNamespace objects. Also remove the
51  // session_storage_namespace.h include since we only need that to assign
52  // into the map.
53  content::SessionStorageNamespaceMap session_storage_namespace_map;
54  session_storage_namespace_map[std::string()] = session_storage_namespace;
55  WebContents::CreateParams create_params(
56      browser->profile(),
57      tab_util::GetSiteInstanceForNewTab(browser->profile(), restore_url));
58  WebContents* base_web_contents =
59      browser->tab_strip_model()->GetActiveWebContents();
60  if (base_web_contents) {
61    create_params.initial_size =
62        base_web_contents->GetView()->GetContainerSize();
63  }
64  WebContents* web_contents = content::WebContents::CreateWithSessionStorage(
65      create_params,
66      session_storage_namespace_map);
67  extensions::TabHelper::CreateForWebContents(web_contents);
68  extensions::TabHelper::FromWebContents(web_contents)->
69      SetExtensionAppById(extension_app_id);
70  std::vector<NavigationEntry*> entries =
71      SerializedNavigationEntry::ToNavigationEntries(
72          navigations, browser->profile());
73  web_contents->SetUserAgentOverride(user_agent_override);
74  web_contents->GetController().Restore(
75      selected_navigation, GetRestoreType(browser, from_last_session),
76      &entries);
77  DCHECK_EQ(0u, entries.size());
78
79  return web_contents;
80}
81
82}  // namespace
83
84content::WebContents* AddRestoredTab(
85    Browser* browser,
86    const std::vector<SerializedNavigationEntry>& navigations,
87    int tab_index,
88    int selected_navigation,
89    const std::string& extension_app_id,
90    bool select,
91    bool pin,
92    bool from_last_session,
93    content::SessionStorageNamespace* session_storage_namespace,
94    const std::string& user_agent_override) {
95  WebContents* web_contents = CreateRestoredTab(browser,
96                                                navigations,
97                                                selected_navigation,
98                                                extension_app_id,
99                                                from_last_session,
100                                                session_storage_namespace,
101                                                user_agent_override);
102
103  int add_types = select ? TabStripModel::ADD_ACTIVE
104                         : TabStripModel::ADD_NONE;
105  if (pin) {
106    int first_mini_tab_idx =
107        browser->tab_strip_model()->IndexOfFirstNonMiniTab();
108    tab_index = std::min(tab_index, first_mini_tab_idx);
109    add_types |= TabStripModel::ADD_PINNED;
110  }
111  browser->tab_strip_model()->InsertWebContentsAt(tab_index, web_contents,
112                                                  add_types);
113  if (select) {
114    browser->window()->Activate();
115  } else {
116    // We set the size of the view here, before WebKit does its initial
117    // layout.  If we don't, the initial layout of background tabs will be
118    // performed with a view width of 0, which may cause script outputs and
119    // anchor link location calculations to be incorrect even after a new
120    // layout with proper view dimensions. TabStripModel::AddWebContents()
121    // contains similar logic.
122    web_contents->GetView()->SizeContents(
123        browser->window()->GetRestoredBounds().size());
124    web_contents->WasHidden();
125  }
126  SessionService* session_service =
127      SessionServiceFactory::GetForProfileIfExisting(browser->profile());
128  if (session_service)
129    session_service->TabRestored(web_contents, pin);
130  return web_contents;
131}
132
133void ReplaceRestoredTab(
134    Browser* browser,
135    const std::vector<SerializedNavigationEntry>& navigations,
136    int selected_navigation,
137    bool from_last_session,
138    const std::string& extension_app_id,
139    content::SessionStorageNamespace* session_storage_namespace,
140    const std::string& user_agent_override) {
141  WebContents* web_contents = CreateRestoredTab(browser,
142                                                navigations,
143                                                selected_navigation,
144                                                extension_app_id,
145                                                from_last_session,
146                                                session_storage_namespace,
147                                                user_agent_override);
148
149  // ReplaceWebContentsAt won't animate in the restoration, so manually do the
150  // equivalent of ReplaceWebContentsAt.
151  TabStripModel* tab_strip = browser->tab_strip_model();
152  int insertion_index = tab_strip->active_index();
153  tab_strip->InsertWebContentsAt(insertion_index + 1,
154                                 web_contents,
155                                 TabStripModel::ADD_ACTIVE |
156                                 TabStripModel::ADD_INHERIT_GROUP);
157  tab_strip->CloseWebContentsAt(insertion_index, TabStripModel::CLOSE_NONE);
158}
159
160}  // namespace chrome
161