blob: 7003be07c99d134426466c9c87d1308606fe89f7 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync/test/bookmark_entity_builder.h"
#include <stdint.h>
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/browser/bookmark_uuids.h"
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/time.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/engine/loopback_server/persistent_bookmark_entity.h"
#include "components/sync/protocol/bookmark_specifics.pb.h"
#include "components/sync/protocol/entity_specifics.pb.h"
#include "components/sync/protocol/unique_position.pb.h"
using std::string;
using syncer::LoopbackServerEntity;
// A version must be passed when creating a LoopbackServerEntity, but this value
// is overrideen immediately when saving the entity in FakeServer.
constexpr int64_t kUnusedVersion = 0L;
// Default time (creation and last modified) used when creating entities.
constexpr int64_t kDefaultTime = 1234L;
namespace fake_server {
namespace {
syncer::UniquePosition::Suffix GenerateUniquePositionStringForBookmark(
const base::Uuid& uuid) {
if (!uuid.is_valid()) {
return syncer::UniquePosition::RandomSuffix();
}
return syncer::UniquePosition::GenerateSuffix(
syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
uuid.AsLowercaseString()));
}
} // namespace
BookmarkEntityBuilder::BookmarkEntityBuilder(
const string& title,
const base::Uuid& uuid,
const string& originator_cache_guid)
: title_(title),
uuid_(uuid),
originator_cache_guid_(originator_cache_guid),
originator_client_item_id_(uuid.AsLowercaseString()) {}
BookmarkEntityBuilder::BookmarkEntityBuilder(
const std::u16string& title,
const base::Uuid& uuid,
const std::string& originator_cache_guid)
: BookmarkEntityBuilder(base::UTF16ToUTF8(title),
uuid,
originator_cache_guid) {}
BookmarkEntityBuilder::BookmarkEntityBuilder(
const BookmarkEntityBuilder& other) = default;
BookmarkEntityBuilder::~BookmarkEntityBuilder() = default;
BookmarkEntityBuilder& BookmarkEntityBuilder::SetOriginatorClientItemId(
const std::string& originator_client_item_id) {
originator_client_item_id_ = originator_client_item_id;
return *this;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::EnableClientTagHash() {
use_client_tag_hash_ = true;
return *this;
}
void BookmarkEntityBuilder::SetId(const std::string& id) {
id_ = id;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::SetParentId(
const std::string& parent_id) {
parent_id_ = parent_id;
return *this;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::SetParentGuid(
const base::Uuid& parent_guid) {
DCHECK(parent_guid.is_valid()) << parent_guid.AsLowercaseString();
parent_guid_ = parent_guid;
return *this;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::SetIndex(int index) {
index_ = index;
return *this;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::SetGeneration(
BookmarkEntityBuilder::BookmarkGeneration generation) {
bookmark_generation_ = generation;
return *this;
}
BookmarkEntityBuilder& BookmarkEntityBuilder::SetFavicon(
const gfx::Image& favicon,
const GURL& icon_url) {
favicon_ = favicon;
icon_url_ = icon_url;
return *this;
}
std::unique_ptr<LoopbackServerEntity> BookmarkEntityBuilder::BuildBookmark(
const GURL& url) {
if (!url.is_valid()) {
return base::WrapUnique<LoopbackServerEntity>(nullptr);
}
sync_pb::EntitySpecifics entity_specifics =
CreateBaseEntitySpecifics(/*is_folder=*/false);
entity_specifics.mutable_bookmark()->set_url(url.spec());
FillWithFaviconIfNeeded(entity_specifics.mutable_bookmark());
return Build(entity_specifics, /*is_folder=*/false);
}
std::unique_ptr<LoopbackServerEntity> BookmarkEntityBuilder::BuildFolder() {
return Build(CreateBaseEntitySpecifics(/*is_folder=*/true),
/*is_folder=*/true);
}
sync_pb::UniquePosition BookmarkEntityBuilder::GetUniquePosition() const {
return syncer::UniquePosition::FromInt64(
index_, GenerateUniquePositionStringForBookmark(uuid_))
.ToProto();
}
sync_pb::EntitySpecifics BookmarkEntityBuilder::CreateBaseEntitySpecifics(
bool is_folder) {
sync_pb::EntitySpecifics entity_specifics;
sync_pb::BookmarkSpecifics* bookmark_specifics =
entity_specifics.mutable_bookmark();
if (parent_id_.empty() && !parent_guid_.is_valid()) {
parent_id_ =
LoopbackServerEntity::CreateId(syncer::BOOKMARKS, "bookmark_bar");
parent_guid_ = base::Uuid::ParseLowercase(bookmarks::kBookmarkBarNodeUuid);
}
if (bookmark_generation_ >= BookmarkGeneration::kValidGuidAndLegacyTitle) {
bookmark_specifics->set_legacy_canonicalized_title(title_);
// GUID must be valid for `kValidGuidAndLegacyTitle`.
CHECK(uuid_.is_valid());
bookmark_specifics->set_guid(uuid_.AsLowercaseString());
}
if (bookmark_generation_ >= BookmarkGeneration::kValidGuidAndFullTitle) {
bookmark_specifics->set_full_title(title_);
}
if (bookmark_generation_ >= BookmarkGeneration::kHierarchyFieldsInSpecifics) {
DCHECK(parent_guid_.is_valid());
bookmark_specifics->set_parent_guid(parent_guid_.AsLowercaseString());
bookmark_specifics->set_type(is_folder ? sync_pb::BookmarkSpecifics::FOLDER
: sync_pb::BookmarkSpecifics::URL);
*bookmark_specifics->mutable_unique_position() = GetUniquePosition();
}
return entity_specifics;
}
std::unique_ptr<LoopbackServerEntity> BookmarkEntityBuilder::Build(
const sync_pb::EntitySpecifics& entity_specifics,
bool is_folder) {
if (id_.empty()) {
id_ = LoopbackServerEntity::CreateId(
syncer::BOOKMARKS, base::Uuid::GenerateRandomV4().AsLowercaseString());
}
if (use_client_tag_hash_) {
return base::WrapUnique<LoopbackServerEntity>(
new syncer::PersistentBookmarkEntity(
id_, kUnusedVersion, title_, /*originator_cache_guid=*/"",
/*originator_client_item_id=*/"",
syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
uuid_.AsLowercaseString())
.value(),
GetUniquePosition(), entity_specifics, is_folder, parent_id_,
kDefaultTime, kDefaultTime));
} else {
return base::WrapUnique<LoopbackServerEntity>(
new syncer::PersistentBookmarkEntity(
id_, kUnusedVersion, title_, originator_cache_guid_,
/*originator_client_item_id=*/originator_client_item_id_,
/*client_tag_hash=*/"", GetUniquePosition(), entity_specifics,
is_folder, parent_id_, kDefaultTime, kDefaultTime));
}
}
void BookmarkEntityBuilder::FillWithFaviconIfNeeded(
sync_pb::BookmarkSpecifics* bookmark_specifics) {
DCHECK(bookmark_specifics);
// Both `favicon_` and `icon_url_` must be provided or empty simultaneously.
DCHECK(favicon_.IsEmpty() == icon_url_.is_empty());
if (favicon_.IsEmpty()) {
return;
}
scoped_refptr<base::RefCountedMemory> favicon_bytes = favicon_.As1xPNGBytes();
bookmark_specifics->set_favicon(favicon_bytes->front(),
favicon_bytes->size());
bookmark_specifics->set_icon_url(icon_url_.spec());
}
} // namespace fake_server