blob: 1826de0905033293e42abdc31d96353f8b897a28 [file] [log] [blame]
// Copyright 2025 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/tab/tab_storage_packager.h"
#include <memory>
#include <utility>
#include "base/strings/utf_string_conversions.h"
#include "base/token.h"
#include "chrome/browser/tab/collection_storage_package.h"
#include "chrome/browser/tab/payload.h"
#include "chrome/browser/tab/protocol/children.pb.h"
#include "chrome/browser/tab/protocol/split_collection_state.pb.h"
#include "chrome/browser/tab/protocol/tab_group_collection_state.pb.h"
#include "chrome/browser/tab/storage_id_mapping.h"
#include "chrome/browser/tab/storage_package.h"
#include "chrome/browser/tab/tab_group_collection_data.h"
#include "chrome/browser/tab/tab_storage_package.h"
#include "chrome/browser/tab/tab_storage_type.h"
#include "chrome/browser/tab/tab_storage_util.h"
#include "components/tabs/public/direct_child_walker.h"
#include "components/tabs/public/split_tab_collection.h"
#include "components/tabs/public/split_tab_data.h"
namespace tabs {
// Crawls the direct children of a TabCollection and adds them to the list of
// children.
class ChildProcessor : public DirectChildWalker::Processor {
public:
ChildProcessor(tabs_pb::Children& children_proto, StorageIdMapping& mapping)
: children_proto_(children_proto), mapping_(mapping) {}
void ProcessTab(const TabInterface* tab) override {
children_proto_->add_storage_id(mapping_->GetStorageId(tab));
}
void ProcessCollection(const TabCollection* collection) override {
children_proto_->add_storage_id(mapping_->GetStorageId(collection));
}
private:
raw_ref<tabs_pb::Children> children_proto_;
raw_ref<StorageIdMapping> mapping_;
};
// An empty payload of data.
class EmptyPayload : public Payload {
public:
EmptyPayload() = default;
std::string SerializePayload() const override { return ""; }
};
// A payload representing the collection children.
class ChildrenPayload : public Payload {
public:
explicit ChildrenPayload(tabs_pb::Children children)
: children_(std::move(children)) {}
std::string SerializePayload() const override {
return children_.SerializeAsString();
}
private:
tabs_pb::Children children_;
};
// A payload of data representing SplitTabCollections.
class SplitCollectionStorageData : public Payload {
public:
explicit SplitCollectionStorageData(
tabs_pb::SplitCollectionState split_collection_state)
: split_collection_state_(std::move(split_collection_state)) {}
~SplitCollectionStorageData() override = default;
std::string SerializePayload() const override {
return split_collection_state_.SerializeAsString();
}
private:
tabs_pb::SplitCollectionState split_collection_state_;
};
// A payload of data representing TabGroupTabCollection.
class TabGroupCollectionStorageData : public Payload {
public:
explicit TabGroupCollectionStorageData(tabs_pb::TabGroupCollectionState state)
: state_(std::move(state)) {}
~TabGroupCollectionStorageData() override = default;
std::string SerializePayload() const override {
return state_.SerializeAsString();
}
private:
tabs_pb::TabGroupCollectionState state_;
};
TabStoragePackager::TabStoragePackager() = default;
TabStoragePackager::~TabStoragePackager() = default;
void PopulateChildren(tabs_pb::Children& children_proto,
const TabCollection* collection,
StorageIdMapping& mapping) {
ChildProcessor processor(children_proto, mapping);
DirectChildWalker walker(collection, &processor);
walker.Walk();
}
std::unique_ptr<StoragePackage> TabStoragePackager::Package(
const TabCollection* collection,
StorageIdMapping& mapping) {
tabs_pb::Children children_proto;
PopulateChildren(children_proto, collection, mapping);
return std::make_unique<CollectionStoragePackage>(
TabStoragePackager::PackagePayload(collection, mapping),
std::move(children_proto));
}
std::unique_ptr<Payload> TabStoragePackager::PackagePayload(
const TabCollection* collection,
StorageIdMapping& mapping) {
TabStorageType type = TabCollectionTypeToTabStorageType(collection->type());
if (type == TabStorageType::kSplit) {
return PackageSplitTabCollectionData(
static_cast<const SplitTabCollection*>(collection), mapping);
} else if (type == TabStorageType::kGroup) {
return PackageTabGroupTabCollectionData(
static_cast<const TabGroupTabCollection*>(collection), mapping);
} else if (type == TabStorageType::kTabStrip) {
return PackageTabStripCollectionData(
static_cast<const TabStripCollection*>(collection), mapping);
} else {
return std::make_unique<EmptyPayload>();
}
}
std::unique_ptr<Payload> TabStoragePackager::PackageChildren(
const TabCollection* collection,
StorageIdMapping& mapping) {
tabs_pb::Children children_proto;
PopulateChildren(children_proto, collection, mapping);
return std::make_unique<ChildrenPayload>(std::move(children_proto));
}
const TabCollection* TabStoragePackager::GetRootCollection(
const TabCollection* collection) const {
CHECK(collection);
const TabCollection* parent = collection->GetParentCollection();
while (parent) {
collection = parent;
parent = collection->GetParentCollection();
}
return collection;
}
std::unique_ptr<Payload> TabStoragePackager::PackageTabGroupTabCollectionData(
const TabGroupTabCollection* collection,
StorageIdMapping& mapping) {
tabs_pb::TabGroupCollectionState state;
const base::Token group_id = collection->GetTabGroupId().token();
state.set_group_id_high(group_id.high());
state.set_group_id_low(group_id.low());
const tab_groups::TabGroupVisualData* visual_data =
collection->GetTabGroup()->visual_data();
state.set_color(static_cast<int32_t>(visual_data->color()));
state.set_is_collapsed(visual_data->is_collapsed());
state.set_title(base::UTF16ToUTF8(visual_data->title()));
return std::make_unique<TabGroupCollectionStorageData>(std::move(state));
}
std::unique_ptr<Payload> TabStoragePackager::PackageSplitTabCollectionData(
const SplitTabCollection* collection,
StorageIdMapping& mapping) {
tabs_pb::SplitCollectionState state;
const base::Token split_tab_id = collection->GetSplitTabId().token();
state.set_split_tab_id_high(split_tab_id.high());
state.set_split_tab_id_low(split_tab_id.low());
split_tabs::SplitTabData* data = collection->data();
split_tabs::SplitTabVisualData* visual_data = data->visual_data();
state.set_split_layout(static_cast<int32_t>(visual_data->split_layout()));
state.set_split_ratio(visual_data->split_ratio());
return std::make_unique<SplitCollectionStorageData>(std::move(state));
}
} // namespace tabs