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 21 using content::WebContents; 22 using content::NavigationController; 23 using content::NavigationEntry; 24 using sessions::SerializedNavigationEntry; 25 26 namespace chrome { 27 28 namespace { 29 30 NavigationController::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 39 WebContents* 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 84 content::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 133 content::WebContents* 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 return web_contents; 159 } 160 161 } // namespace chrome 162