15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_tabrestore.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_service_factory.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/tab_contents/tab_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/browser/session_storage_namespace.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using sessions::SerializedNavigationEntry;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NavigationController::RestoreType GetRestoreType(Browser* browser,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 bool from_last_session) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!from_last_session)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NavigationController::RESTORE_CURRENT_SESSION;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return browser->profile()->GetLastSessionExitType() == Profile::EXIT_CRASHED ?
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NavigationController::RESTORE_LAST_SESSION_CRASHED :
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContents* CreateRestoredTab(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<SerializedNavigationEntry>& navigations,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_navigation,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_app_id,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool from_last_session,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::SessionStorageNamespace* session_storage_namespace,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent_override) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL restore_url = navigations.at(selected_navigation).virtual_url();
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TODO(ajwong): Remove the temporary session_storage_namespace_map when
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // we teach session restore to understand that one tab can have multiple
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // SessionStorageNamespace objects. Also remove the
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // session_storage_namespace.h include since we only need that to assign
52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // into the map.
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  content::SessionStorageNamespaceMap session_storage_namespace_map;
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_storage_namespace_map[std::string()] = session_storage_namespace;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents::CreateParams create_params(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser->profile(),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab_util::GetSiteInstanceForNewTab(browser->profile(), restore_url));
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents* base_web_contents =
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      browser->tab_strip_model()->GetActiveWebContents();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (base_web_contents) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    create_params.initial_size =
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base_web_contents->GetView()->GetContainerSize();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents* web_contents = content::WebContents::CreateWithSessionStorage(
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      create_params,
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      session_storage_namespace_map);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::TabHelper::CreateForWebContents(web_contents);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::TabHelper::FromWebContents(web_contents)->
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetExtensionAppById(extension_app_id);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<NavigationEntry*> entries =
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SerializedNavigationEntry::ToNavigationEntries(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          navigations, browser->profile());
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents->SetUserAgentOverride(user_agent_override);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents->GetController().Restore(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      selected_navigation, GetRestoreType(browser, from_last_session),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &entries);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0u, entries.size());
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebContents* AddRestoredTab(
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Browser* browser,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<SerializedNavigationEntry>& navigations,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int tab_index,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int selected_navigation,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_app_id,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool select,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool pin,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool from_last_session,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::SessionStorageNamespace* session_storage_namespace,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& user_agent_override) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents* web_contents = CreateRestoredTab(browser,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                navigations,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                selected_navigation,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                extension_app_id,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                from_last_session,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                session_storage_namespace,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                user_agent_override);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int add_types = select ? TabStripModel::ADD_ACTIVE
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         : TabStripModel::ADD_NONE;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pin) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int first_mini_tab_idx =
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->tab_strip_model()->IndexOfFirstNonMiniTab();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_index = std::min(tab_index, first_mini_tab_idx);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_types |= TabStripModel::ADD_PINNED;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  browser->tab_strip_model()->InsertWebContentsAt(tab_index, web_contents,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  add_types);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser->window()->Activate();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We set the size of the view here, before WebKit does its initial
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // layout.  If we don't, the initial layout of background tabs will be
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // performed with a view width of 0, which may cause script outputs and
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // anchor link location calculations to be incorrect even after a new
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // layout with proper view dimensions. TabStripModel::AddWebContents()
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // contains similar logic.
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    web_contents->GetView()->SizeContents(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser->window()->GetRestoredBounds().size());
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    web_contents->WasHidden();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionService* session_service =
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SessionServiceFactory::GetForProfileIfExisting(browser->profile());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session_service)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_service->TabRestored(web_contents, pin);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return web_contents;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochcontent::WebContents* ReplaceRestoredTab(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Browser* browser,
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<SerializedNavigationEntry>& navigations,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int selected_navigation,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool from_last_session,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_app_id,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::SessionStorageNamespace* session_storage_namespace,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent_override) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebContents* web_contents = CreateRestoredTab(browser,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                navigations,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                selected_navigation,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                extension_app_id,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                from_last_session,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                session_storage_namespace,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                user_agent_override);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ReplaceWebContentsAt won't animate in the restoration, so manually do the
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // equivalent of ReplaceWebContentsAt.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TabStripModel* tab_strip = browser->tab_strip_model();
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int insertion_index = tab_strip->active_index();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tab_strip->InsertWebContentsAt(insertion_index + 1,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 web_contents,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 TabStripModel::ADD_ACTIVE |
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 TabStripModel::ADD_INHERIT_GROUP);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tab_strip->CloseWebContentsAt(insertion_index, TabStripModel::CLOSE_NONE);
1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return web_contents;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome
162