// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/full_restore/full_restore_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/sessions/core/session_types.h"
#include "content/public/common/url_constants.h"
namespace full_restore {
namespace {
constexpr size_t kMaxUrls = 5u;
} // namespace
crosapi::mojom::SessionWindowPtr ToSessionWindowPtr(
const sessions::SessionWindow& session_window,
uint64_t lacros_profile_id) {
crosapi::mojom::SessionWindowPtr new_session_window =
crosapi::mojom::SessionWindow::New();
new_session_window->window_id = session_window.window_id.id();
new_session_window->profile_id = lacros_profile_id;
// App browsers app ID is the same as regular chrome browsers. To get the
// correct icon and title from the app service, we need to find the app
// name and remove the "_crx_", then use that result. For example, the google
// meet PWA has an app name "_crx_kjgfgldnnfoeklkmfkjfagphfepbbdan". We will
// send this to ash where it will use "kjgfgldnnfoeklkmfkjfagphfepbbdan" to
// query the app service for data.
if (!session_window.app_name.empty()) {
new_session_window->app_name = session_window.app_name;
// App browsers will use the new app id to get an app icon and app
// title. We don't need to look at tab data for these.
return new_session_window;
}
// If there is no selected tab index or it is invalid, we can just pass the
// URLs as they are. If the selected tab index is one of the first five
// elements, then we place that URL at the front and place the remaining
// four URLs afterwards. Otherwise, we put the selected tab index at the
// front and insert the first four URLs after it.
std::string active_tab_title;
std::vector<GURL> tab_urls;
const std::vector<std::unique_ptr<sessions::SessionTab>>& tabs =
session_window.tabs;
auto maybe_add_display_tab =
[&tab_urls, &active_tab_title](sessions::SessionTab* tab) -> void {
const auto& navigations = tab->navigations;
const int index = tab->current_navigation_index;
// `index` can actually be larger than the size of `navigations`. See
// `sessions::SessionTab::current_navigation_index` for more details.
if (navigations.size() > static_cast<size_t>(index)) {
const sessions::SerializedNavigationEntry& entry = navigations[index];
// Use the tab title if possible. If no tab title is available and it is a
// chrome WebUI, use the host piece (history, extensions, etc.). Otherwise
// we will default to the app title, "Chrome".
if (active_tab_title.empty()) {
active_tab_title = base::UTF16ToUTF8(entry.title());
if (active_tab_title.empty() &&
entry.original_request_url().SchemeIs(content::kChromeUIScheme)) {
active_tab_title = entry.original_request_url().host_piece();
}
}
tab_urls.push_back(entry.original_request_url());
}
};
// Add the selected tab first if possible.
const int selected_tab_index = session_window.selected_tab_index;
if (selected_tab_index > -1 &&
selected_tab_index < static_cast<int>(tabs.size())) {
maybe_add_display_tab(tabs[selected_tab_index].get());
}
// Add the other tabs in order until there are no more tabs or we reach the
// limit.
for (int i = 0; i < static_cast<int>(tabs.size()); ++i) {
if (i == selected_tab_index) {
continue;
}
maybe_add_display_tab(tabs[i].get());
// We only show five favicons maximum so we can stop once we reach that
// amount.
if (tab_urls.size() >= kMaxUrls) {
break;
}
}
new_session_window->active_tab_title = active_tab_title;
new_session_window->urls = tab_urls;
new_session_window->tab_count = tabs.size();
return new_session_window;
}
} // namespace full_restore