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.
5 #include "chrome/browser/ui/browser_tabrestore.h"
7 #include "base/memory/scoped_vector.h"
8 #include "chrome/browser/extensions/tab_helper.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/sessions/session_service.h"
11 #include "chrome/browser/sessions/session_service_factory.h"
12 #include "chrome/browser/tab_contents/tab_util.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_window.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/browser/ui/web_contents_sizer.h"
17 #include "components/sessions/content/content_serialized_navigation_builder.h"
18 #include "content/public/browser/navigation_controller.h"
19 #include "content/public/browser/navigation_entry.h"
20 #include "content/public/browser/session_storage_namespace.h"
21 #include "content/public/browser/web_contents.h"
23 using content::WebContents
;
24 using content::NavigationController
;
25 using content::NavigationEntry
;
26 using sessions::ContentSerializedNavigationBuilder
;
27 using sessions::SerializedNavigationEntry
;
33 NavigationController::RestoreType
GetRestoreType(Browser
* browser
,
34 bool from_last_session
) {
35 if (!from_last_session
)
36 return NavigationController::RESTORE_CURRENT_SESSION
;
37 return browser
->profile()->GetLastSessionExitType() == Profile::EXIT_CRASHED
?
38 NavigationController::RESTORE_LAST_SESSION_CRASHED
:
39 NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY
;
42 WebContents
* CreateRestoredTab(
44 const std::vector
<SerializedNavigationEntry
>& navigations
,
45 int selected_navigation
,
46 const std::string
& extension_app_id
,
47 bool from_last_session
,
48 content::SessionStorageNamespace
* session_storage_namespace
,
49 const std::string
& user_agent_override
,
50 bool initially_hidden
) {
51 GURL restore_url
= navigations
.at(selected_navigation
).virtual_url();
52 // TODO(ajwong): Remove the temporary session_storage_namespace_map when
53 // we teach session restore to understand that one tab can have multiple
54 // SessionStorageNamespace objects. Also remove the
55 // session_storage_namespace.h include since we only need that to assign
57 content::SessionStorageNamespaceMap session_storage_namespace_map
;
58 session_storage_namespace_map
[std::string()] = session_storage_namespace
;
59 WebContents::CreateParams
create_params(
61 tab_util::GetSiteInstanceForNewTab(browser
->profile(), restore_url
));
62 create_params
.initially_hidden
= initially_hidden
;
63 WebContents
* base_web_contents
=
64 browser
->tab_strip_model()->GetActiveWebContents();
65 if (base_web_contents
) {
66 create_params
.initial_size
=
67 base_web_contents
->GetContainerBounds().size();
69 WebContents
* web_contents
= content::WebContents::CreateWithSessionStorage(
71 session_storage_namespace_map
);
72 extensions::TabHelper::CreateForWebContents(web_contents
);
73 extensions::TabHelper::FromWebContents(web_contents
)->
74 SetExtensionAppById(extension_app_id
);
75 ScopedVector
<NavigationEntry
> scoped_entries
=
76 ContentSerializedNavigationBuilder::ToNavigationEntries(
77 navigations
, browser
->profile());
78 web_contents
->SetUserAgentOverride(user_agent_override
);
79 web_contents
->GetController().Restore(
80 selected_navigation
, GetRestoreType(browser
, from_last_session
),
82 DCHECK_EQ(0u, scoped_entries
.size());
89 content::WebContents
* AddRestoredTab(
91 const std::vector
<SerializedNavigationEntry
>& navigations
,
93 int selected_navigation
,
94 const std::string
& extension_app_id
,
97 bool from_last_session
,
98 content::SessionStorageNamespace
* session_storage_namespace
,
99 const std::string
& user_agent_override
) {
100 WebContents
* web_contents
= CreateRestoredTab(browser
,
105 session_storage_namespace
,
109 int add_types
= select
? TabStripModel::ADD_ACTIVE
110 : TabStripModel::ADD_NONE
;
112 tab_index
= std::min(
113 tab_index
, browser
->tab_strip_model()->IndexOfFirstNonPinnedTab());
114 add_types
|= TabStripModel::ADD_PINNED
;
116 browser
->tab_strip_model()->InsertWebContentsAt(tab_index
, web_contents
,
119 browser
->window()->Activate();
121 // We set the size of the view here, before Blink does its initial layout.
122 // If we don't, the initial layout of background tabs will be performed
123 // with a view width of 0, which may cause script outputs and anchor link
124 // location calculations to be incorrect even after a new layout with
125 // proper view dimensions. TabStripModel::AddWebContents() contains similar
127 gfx::Size size
= browser
->window()->GetBounds().size();
128 // Fallback to the restore bounds if it's empty as the window is not shown
129 // yet and the bounds may not be available on all platforms.
131 size
= browser
->window()->GetRestoredBounds().size();
132 ResizeWebContents(web_contents
, size
);
133 web_contents
->WasHidden();
135 SessionService
* session_service
=
136 SessionServiceFactory::GetForProfileIfExisting(browser
->profile());
138 session_service
->TabRestored(web_contents
, pin
);
142 content::WebContents
* ReplaceRestoredTab(
144 const std::vector
<SerializedNavigationEntry
>& navigations
,
145 int selected_navigation
,
146 bool from_last_session
,
147 const std::string
& extension_app_id
,
148 content::SessionStorageNamespace
* session_storage_namespace
,
149 const std::string
& user_agent_override
) {
150 WebContents
* web_contents
= CreateRestoredTab(browser
,
155 session_storage_namespace
,
159 // ReplaceWebContentsAt won't animate in the restoration, so manually do the
160 // equivalent of ReplaceWebContentsAt.
161 TabStripModel
* tab_strip
= browser
->tab_strip_model();
162 int insertion_index
= tab_strip
->active_index();
163 tab_strip
->InsertWebContentsAt(insertion_index
+ 1,
165 TabStripModel::ADD_ACTIVE
|
166 TabStripModel::ADD_INHERIT_GROUP
);
167 tab_strip
->CloseWebContentsAt(insertion_index
, TabStripModel::CLOSE_NONE
);
171 } // namespace chrome