#include "components/bookmarks/browser/bookmark_load_details.h"
#include "base/uuid.h"
#include "components/bookmarks/browser/bookmark_uuids.h"
#include "components/bookmarks/browser/titled_url_index.h"
#include "components/bookmarks/browser/url_index.h"
#include "components/bookmarks/common/user_folder_load_stats.h"
namespace bookmarks {
namespace {
constexpr size_t kNumDefaultTopLevelPermanentFolders = 3u;
void UpdateUserFolderStatsRecursively(const BookmarkNode& node,
bool top_level,
UserFolderLoadStats& stats) {
DCHECK(!node.is_permanent_node());
if (!node.is_folder()) {
return;
}
stats.total_folders++;
if (top_level) {
stats.total_top_level_folders++;
}
for (auto& child : node.children()) {
UpdateUserFolderStatsRecursively(*child, false, stats);
}
}
}
BookmarkLoadDetails::BookmarkLoadDetails()
: titled_url_index_(std::make_unique<TitledUrlIndex>()),
load_start_(base::TimeTicks::Now()) {
root_node_ = std::make_unique<BookmarkNode>(
0, base::Uuid::ParseLowercase(kRootNodeUuid), GURL());
bb_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(BookmarkPermanentNode::CreateBookmarkBar(
0, false)));
other_folder_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(BookmarkPermanentNode::CreateOtherBookmarks(
0, false)));
mobile_folder_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(BookmarkPermanentNode::CreateMobileBookmarks(
0, false)));
const base::Time current_timestamp = base::Time::Now();
bb_node_->set_date_added(current_timestamp);
other_folder_node_->set_date_added(current_timestamp);
mobile_folder_node_->set_date_added(current_timestamp);
CHECK_EQ(kNumDefaultTopLevelPermanentFolders, root_node_->children().size());
}
BookmarkLoadDetails::~BookmarkLoadDetails() = default;
void BookmarkLoadDetails::AddAccountPermanentNodes(
std::unique_ptr<BookmarkPermanentNode> account_bb_node,
std::unique_ptr<BookmarkPermanentNode> account_other_folder_node,
std::unique_ptr<BookmarkPermanentNode> account_mobile_folder_node) {
CHECK(account_bb_node);
CHECK(account_other_folder_node);
CHECK(account_mobile_folder_node);
CHECK(!account_bb_node_);
CHECK(!account_other_folder_node_);
CHECK(!account_mobile_folder_node_);
account_bb_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(std::move(account_bb_node)));
account_other_folder_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(std::move(account_other_folder_node)));
account_mobile_folder_node_ = static_cast<BookmarkPermanentNode*>(
root_node_->Add(std::move(account_mobile_folder_node)));
}
void BookmarkLoadDetails::PopulateNodeIdsForLocalOrSyncablePermanentNodes() {
CHECK(bb_node_);
CHECK(other_folder_node_);
CHECK(mobile_folder_node_);
CHECK(!has_managed_node_);
if (bb_node_->id() == 0) {
bb_node_->set_id(max_id_++);
}
if (other_folder_node_->id() == 0) {
other_folder_node_->set_id(max_id_++);
}
if (mobile_folder_node_->id() == 0) {
mobile_folder_node_->set_id(max_id_++);
}
}
void BookmarkLoadDetails::AddManagedNode(
std::unique_ptr<BookmarkPermanentNode> managed_node) {
CHECK(managed_node);
CHECK(!has_managed_node_);
CHECK_NE(bb_node_->id(), 0);
CHECK_NE(other_folder_node_->id(), 0);
CHECK_NE(mobile_folder_node_->id(), 0);
has_managed_node_ = true;
root_node_->Add(std::move(managed_node));
}
void BookmarkLoadDetails::CreateIndices() {
local_or_syncable_uuid_index_.insert(root_node_.get());
static_assert(kNumDefaultTopLevelPermanentFolders == 3u,
"The code below assumes three permanent nodes");
for (const auto& child : root_node_->children()) {
if (child.get() == account_bb_node_ ||
child.get() == account_other_folder_node_ ||
child.get() == account_mobile_folder_node_) {
AddNodeToIndexRecursive(child.get(), account_uuid_index_);
} else {
AddNodeToIndexRecursive(child.get(), local_or_syncable_uuid_index_);
}
}
url_index_ = base::MakeRefCounted<UrlIndex>(std::move(root_node_));
}
void BookmarkLoadDetails::ResetPermanentNodePointers() {
bb_node_ = nullptr;
other_folder_node_ = nullptr;
mobile_folder_node_ = nullptr;
account_bb_node_ = nullptr;
account_other_folder_node_ = nullptr;
account_mobile_folder_node_ = nullptr;
}
const BookmarkNode* BookmarkLoadDetails::RootNodeForTest() const {
return GetRootNode();
}
UserFolderLoadStats BookmarkLoadDetails::ComputeUserFolderStats() const {
UserFolderLoadStats stats;
const BookmarkNode* root = GetRootNode();
for (const auto& root_child : root->children()) {
if (!root_child->is_permanent_node()) {
continue;
}
if (root_child->is_folder() &&
root_child->type() == BookmarkNode::BOOKMARK_BAR) {
stats.bookmark_bar_top_level_items = root_child->children().size();
}
for (const auto& child : root_child->children()) {
UpdateUserFolderStatsRecursively(*child, true, stats);
}
}
return stats;
}
void BookmarkLoadDetails::AddNodeToIndexRecursive(BookmarkNode* node,
UuidIndex& uuid_index) {
uuid_index.insert(node);
if (node->is_url()) {
if (node->url().is_valid()) {
titled_url_index_->Add(node);
}
} else {
titled_url_index_->AddPath(node);
for (const auto& child : node->children()) {
AddNodeToIndexRecursive(child.get(), uuid_index);
}
}
}
const BookmarkNode* BookmarkLoadDetails::GetRootNode() const {
return url_index_ ? url_index_->root() : root_node_.get();
}
}