blob: fb1780a0ecbfd084fb8933643e321827bb0a60b0 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "weblayer/browser/persistence/browser_persistence_common.h"
#include "components/sessions/content/content_serialized_navigation_builder.h"
#include "components/sessions/content/session_tab_helper.h"
#include "components/sessions/core/session_command.h"
#include "components/sessions/core/session_service_commands.h"
#include "components/sessions/core/session_types.h"
#include "content/public/browser/browser_url_handler.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/storage_partition.h"
#include "weblayer/browser/browser_context_impl.h"
#include "weblayer/browser/browser_impl.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
namespace weblayer {
namespace {
void ProcessRestoreCommands(
BrowserImpl* browser,
const std::vector<std::unique_ptr<sessions::SessionWindow>>& windows) {
if (windows.empty() || windows[0]->tabs.empty())
return;
const bool had_tabs = !browser->GetTabs().empty();
content::BrowserContext* browser_context =
browser->profile()->GetBrowserContext();
for (int i = 0; i < static_cast<int>(windows[0]->tabs.size()); ++i) {
const sessions::SessionTab& session_tab = *(windows[0]->tabs[i]);
if (session_tab.navigations.empty())
continue;
// Associate sessionStorage (if any) to the restored tab.
scoped_refptr<content::SessionStorageNamespace> session_storage_namespace;
if (!session_tab.session_storage_persistent_id.empty()) {
session_storage_namespace =
browser_context->GetDefaultStoragePartition()
->GetDOMStorageContext()
->RecreateSessionStorage(
session_tab.session_storage_persistent_id);
}
const int selected_navigation_index =
session_tab.normalized_navigation_index();
GURL restore_url =
session_tab.navigations[selected_navigation_index].virtual_url();
content::SessionStorageNamespaceMap session_storage_namespace_map =
content::CreateMapWithDefaultSessionStorageNamespace(
browser_context, session_storage_namespace);
content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
&restore_url, browser_context);
content::WebContents::CreateParams create_params(
browser_context,
content::SiteInstance::ShouldAssignSiteForURL(restore_url)
? content::SiteInstance::CreateForURL(browser_context, restore_url)
: nullptr);
create_params.initially_hidden = true;
create_params.desired_renderer_state =
content::WebContents::CreateParams::kNoRendererProcess;
create_params.last_active_time = session_tab.last_active_time;
std::unique_ptr<content::WebContents> web_contents =
content::WebContents::CreateWithSessionStorage(
create_params, session_storage_namespace_map);
std::vector<std::unique_ptr<content::NavigationEntry>> entries =
sessions::ContentSerializedNavigationBuilder::ToNavigationEntries(
session_tab.navigations, browser_context);
blink::UserAgentOverride ua_override;
ua_override.ua_string_override =
session_tab.user_agent_override.ua_string_override;
ua_override.ua_metadata_override = blink::UserAgentMetadata::Demarshal(
session_tab.user_agent_override.opaque_ua_metadata_override);
web_contents->SetUserAgentOverride(ua_override, false);
web_contents->GetController().Restore(
selected_navigation_index, content::RestoreType::kRestored, &entries);
DCHECK(entries.empty());
TabImpl* tab = browser->CreateTabForSessionRestore(std::move(web_contents),
session_tab.guid);
tab->SetData(session_tab.data);
if (!had_tabs && i == (windows[0])->selected_tab_index)
browser->SetActiveTab(tab);
}
if (!had_tabs && !browser->GetTabs().empty() && !browser->GetActiveTab())
browser->SetActiveTab(browser->GetTabs().back());
}
} // namespace
void RestoreBrowserState(
BrowserImpl* browser,
std::vector<std::unique_ptr<sessions::SessionCommand>> commands) {
std::vector<std::unique_ptr<sessions::SessionWindow>> windows;
SessionID active_window_id = SessionID::InvalidValue();
sessions::RestoreSessionFromCommands(commands, &windows, &active_window_id);
ProcessRestoreCommands(browser, windows);
if (browser->GetTabs().empty()) {
// Nothing to restore, or restore failed. Create a default tab.
browser->SetActiveTab(
browser->CreateTabForSessionRestore(nullptr, std::string()));
}
}
std::vector<std::unique_ptr<sessions::SessionCommand>>
BuildCommandsForTabConfiguration(const SessionID& browser_session_id,
TabImpl* tab,
int index_in_browser) {
DCHECK(tab);
std::vector<std::unique_ptr<sessions::SessionCommand>> result;
const SessionID& tab_id = GetSessionIDForTab(tab);
result.push_back(
sessions::CreateSetTabWindowCommand(browser_session_id, tab_id));
result.push_back(sessions::CreateLastActiveTimeCommand(
tab_id, tab->web_contents()->GetLastActiveTime()));
const blink::UserAgentOverride& ua_override =
tab->web_contents()->GetUserAgentOverride();
if (!ua_override.ua_string_override.empty()) {
sessions::SerializedUserAgentOverride serialized_override;
serialized_override.ua_string_override = ua_override.ua_string_override;
serialized_override.opaque_ua_metadata_override =
blink::UserAgentMetadata::Marshal(ua_override.ua_metadata_override);
result.push_back(sessions::CreateSetTabUserAgentOverrideCommand(
tab_id, serialized_override));
}
if (index_in_browser != -1) {
result.push_back(
sessions::CreateSetTabIndexInWindowCommand(tab_id, index_in_browser));
}
result.push_back(sessions::CreateSetSelectedNavigationIndexCommand(
tab_id, tab->web_contents()->GetController().GetCurrentEntryIndex()));
result.push_back(sessions::CreateSetTabGuidCommand(tab_id, tab->GetGuid()));
result.push_back(sessions::CreateSetTabDataCommand(tab_id, tab->GetData()));
return result;
}
const SessionID& GetSessionIDForTab(Tab* tab) {
sessions::SessionTabHelper* session_tab_helper =
sessions::SessionTabHelper::FromWebContents(
static_cast<TabImpl*>(tab)->web_contents());
DCHECK(session_tab_helper);
return session_tab_helper->session_id();
}
} // namespace weblayer