#include "chrome/browser/ash/phonehub/browser_tabs_metadata_fetcher_impl.h"
#include "base/barrier_closure.h"
#include "base/time/time.h"
#include "components/favicon/core/history_ui_favicon_request_handler.h"
#include "components/favicon_base/favicon_types.h"
#include "components/sync_sessions/synced_session.h"
#include "components/ukm/scheme_constants.h"
#include "ui/gfx/image/image_skia.h"
namespace ash::phonehub {
namespace {
std::vector<BrowserTabsModel::BrowserTabMetadata>
GetSortedMetadataWithoutFavicons(const sync_sessions::SyncedSession* session) {
std::vector<BrowserTabsModel::BrowserTabMetadata> browser_tab_metadata;
using WindowPair =
std::pair<const SessionID,
std::unique_ptr<sync_sessions::SyncedSessionWindow>>;
for (const WindowPair& window_pair : session->windows) {
const sessions::SessionWindow& window = window_pair.second->wrapped_window;
for (const std::unique_ptr<sessions::SessionTab>& tab : window.tabs) {
int selected_index = tab->normalized_navigation_index();
if (selected_index + 1 > static_cast<int>(tab->navigations.size()) ||
tab->navigations.empty()) {
continue;
}
const sessions::SerializedNavigationEntry& current_navigation =
tab->navigations.at(selected_index);
GURL tab_url = current_navigation.virtual_url();
if (!tab_url.SchemeIsHTTPOrHTTPS()) {
continue;
}
if (!tab_url.is_valid()) {
continue;
}
const std::u16string& title = current_navigation.title();
const base::Time last_accessed_timestamp = tab->timestamp;
browser_tab_metadata.emplace_back(tab_url, title, last_accessed_timestamp,
gfx::Image());
}
}
std::sort(browser_tab_metadata.begin(), browser_tab_metadata.end());
size_t num_tabs_to_display = std::min(browser_tab_metadata.size(),
BrowserTabsModel::kMaxMostRecentTabs);
return std::vector<BrowserTabsModel::BrowserTabMetadata>(
browser_tab_metadata.begin(),
browser_tab_metadata.begin() + num_tabs_to_display);
}
}
BrowserTabsMetadataFetcherImpl::BrowserTabsMetadataFetcherImpl(
favicon::HistoryUiFaviconRequestHandler* favicon_request_handler)
: favicon_request_handler_(favicon_request_handler) {}
BrowserTabsMetadataFetcherImpl::~BrowserTabsMetadataFetcherImpl() = default;
void BrowserTabsMetadataFetcherImpl::Fetch(
const sync_sessions::SyncedSession* session,
base::OnceCallback<void(BrowserTabsMetadataResponse)> callback) {
if (!callback_.is_null()) {
weak_ptr_factory_.InvalidateWeakPtrs();
std::move(callback_).Run(std::nullopt);
}
results_ = GetSortedMetadataWithoutFavicons(session);
callback_ = std::move(callback);
base::RepeatingClosure barrier = base::BarrierClosure(
results_.size(),
base::BindOnce(&BrowserTabsMetadataFetcherImpl::OnAllFaviconsFetched,
weak_ptr_factory_.GetWeakPtr()));
for (size_t i = 0; i < results_.size(); ++i) {
favicon_request_handler_->GetFaviconImageForPageURL(
results_[i].url,
base::BindOnce(&BrowserTabsMetadataFetcherImpl::OnFaviconReady,
weak_ptr_factory_.GetWeakPtr(), i, barrier));
}
}
void BrowserTabsMetadataFetcherImpl::OnAllFaviconsFetched() {
std::move(callback_).Run(std::move(results_));
}
void BrowserTabsMetadataFetcherImpl::OnFaviconReady(
size_t index_in_results,
base::OnceClosure done_closure,
const favicon_base::FaviconImageResult& favicon_image_result) {
DCHECK(index_in_results < results_.size());
results_[index_in_results].favicon = std::move(favicon_image_result.image);
std::move(done_closure).Run();
}
}