blob: 1dd01cc0ae081e19a214589c8d48c72d79a21d9e [file] [log] [blame]
// Copyright 2019 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/notifications/scheduler/internal/icon_store.h"
#include <map>
#include <utility>
#include "base/containers/contains.h"
#include "base/uuid.h"
#include "chrome/browser/notifications/scheduler/internal/icon_entry.h"
#include "chrome/browser/notifications/scheduler/internal/proto_conversion.h"
#include "chrome/browser/notifications/scheduler/internal/stats.h"
#include "chrome/browser/notifications/scheduler/public/notification_scheduler_types.h"
namespace leveldb_proto {
void DataToProto(notifications::IconEntry* icon_entry,
notifications::proto::Icon* proto) {
IconEntryToProto(icon_entry, proto);
}
void ProtoToData(notifications::proto::Icon* proto,
notifications::IconEntry* icon_entry) {
IconEntryFromProto(proto, icon_entry);
}
} // namespace leveldb_proto
namespace notifications {
namespace {
bool HasKeyInDb(const std::vector<std::string>& key_dict,
const std::string& key) {
return base::Contains(key_dict, key);
}
} // namespace
using KeyEntryPair = std::pair<std::string, IconEntry>;
using KeyEntryVector = std::vector<KeyEntryPair>;
using KeyVector = std::vector<std::string>;
IconProtoDbStore::IconProtoDbStore(
std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db,
std::unique_ptr<IconConverter> icon_converter)
: db_(std::move(db)), icon_converter_(std::move(icon_converter)) {}
IconProtoDbStore::~IconProtoDbStore() = default;
void IconProtoDbStore::InitAndLoadKeys(InitAndLoadKeysCallback callback) {
db_->Init(base::BindOnce(&IconProtoDbStore::OnDbInitialized,
weak_ptr_factory_.GetWeakPtr(),
std::move(callback)));
}
void IconProtoDbStore::AddIcons(IconTypeBundleMap icons, AddCallback callback) {
if (icons.empty()) {
std::move(callback).Run(IconTypeUuidMap{}, true);
return;
}
std::vector<std::string> icons_uuid;
for (size_t i = 0; i < icons.size(); i++) {
icons_uuid.emplace_back(base::Uuid::GenerateRandomV4().AsLowercaseString());
}
std::vector<IconType> icons_type;
std::vector<SkBitmap> icons_bitmap;
for (auto&& it = icons.begin(); it != icons.end(); ++it) {
icons_type.emplace_back(it->first);
icons_bitmap.emplace_back(std::move(it->second.bitmap));
}
icon_converter_->ConvertIconToString(
std::move(icons_bitmap),
base::BindOnce(&IconProtoDbStore::OnIconsEncoded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
std::move(icons_type), std::move(icons_uuid)));
}
void IconProtoDbStore::LoadIcons(const std::vector<std::string>& keys,
LoadIconsCallback callback) {
if (keys.empty()) {
std::move(callback).Run(true, LoadedIconsMap{});
return;
}
db_->LoadKeysAndEntriesWithFilter(
base::BindRepeating(&HasKeyInDb, keys),
base::BindOnce(&IconProtoDbStore::OnIconEntriesLoaded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void IconProtoDbStore::DeleteIcons(const std::vector<std::string>& keys,
UpdateCallback callback) {
if (keys.empty()) {
std::move(callback).Run(true);
return;
}
auto keys_to_delete = std::make_unique<KeyVector>();
for (size_t i = 0; i < keys.size(); i++)
keys_to_delete->emplace_back(keys[i]);
db_->UpdateEntries(std::make_unique<KeyEntryVector>() /*keys_to_save*/,
std::move(keys_to_delete), std::move(callback));
}
void IconProtoDbStore::OnDbInitialized(
InitAndLoadKeysCallback callback,
leveldb_proto::Enums::InitStatus status) {
bool success = (status == leveldb_proto::Enums::InitStatus::kOK);
if (!success) {
std::move(callback).Run(success, nullptr /*LoadedIconKeys*/);
return;
}
db_->LoadKeys(base::BindOnce(&IconProtoDbStore::OnIconKeysLoaded,
weak_ptr_factory_.GetWeakPtr(),
std::move(callback)));
}
void IconProtoDbStore::OnIconKeysLoaded(InitAndLoadKeysCallback callback,
bool success,
LoadedIconKeys loaded_keys) {
if (!success) {
std::move(callback).Run(success, nullptr /*LoadedIconKeys*/);
return;
}
std::move(callback).Run(success, std::move(loaded_keys));
}
void IconProtoDbStore::OnIconEntriesLoaded(
LoadIconsCallback callback,
bool success,
std::unique_ptr<std::map<std::string, IconEntry>> icon_entries) {
if (!success) {
std::move(callback).Run(false, LoadedIconsMap{});
return;
}
std::vector<std::string> icons_uuid;
std::vector<std::string> encoded_icons_data;
for (auto& entry : *icon_entries.get()) {
icons_uuid.emplace_back(std::move(entry.first));
encoded_icons_data.emplace_back(std::move(entry.second.data));
}
icon_converter_->ConvertStringToIcon(
std::move(encoded_icons_data),
base::BindOnce(&IconProtoDbStore::OnIconsDecoded,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
std::move(icons_uuid)));
}
void IconProtoDbStore::OnIconsEncoded(
AddCallback callback,
std::vector<IconType> icons_type,
std::vector<std::string> icons_uuid,
std::unique_ptr<EncodeResult> encode_result) {
stats::LogPngIconConverterEncodeResult(encode_result->success);
IconTypeUuidMap icons_uuid_map;
if (!encode_result->success) {
std::move(callback).Run(std::move(icons_uuid_map), false);
return;
}
auto entries_to_save = std::make_unique<KeyEntryVector>();
auto encoded_data = std::move(encode_result->encoded_data);
for (size_t i = 0; i < encoded_data.size(); i++) {
IconEntry icon_entry;
icon_entry.data = std::move(encoded_data[i]);
entries_to_save->emplace_back(icons_uuid[i], std::move(icon_entry));
icons_uuid_map.emplace(icons_type[i], std::move(icons_uuid[i]));
}
auto add_callback =
base::BindOnce(std::move(callback), std::move(icons_uuid_map));
db_->UpdateEntries(std::move(entries_to_save),
std::make_unique<KeyVector>() /*entries_to_delete*/,
std::move(add_callback));
}
void IconProtoDbStore::OnIconsDecoded(
LoadIconsCallback callback,
std::vector<std::string> icons_uuid,
std::unique_ptr<DecodeResult> decoded_result) {
stats::LogPngIconConverterDecodeResult(decoded_result->success);
if (!decoded_result->success) {
std::move(callback).Run(false, LoadedIconsMap{});
return;
}
LoadedIconsMap icons_map;
auto icons = std::move(decoded_result->decoded_icons);
for (size_t i = 0; i < icons_uuid.size(); i++) {
IconBundle icon_bundle(std::move(icons[i]));
icons_map.emplace(std::move(icons_uuid[i]), std::move(icon_bundle));
}
std::move(callback).Run(true, std::move(icons_map));
}
} // namespace notifications