blob: b438145b483686c353d2f5c44a257ea9ccc92f1a [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/doodle/doodle_types.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
namespace doodle {
namespace {
// String representations for the DoodleType enum.
const char kDoodleTypeUnknown[] = "UNKNOWN";
const char kDoodleTypeSimple[] = "SIMPLE";
const char kDoodleTypeRandom[] = "RANDOM";
const char kDoodleTypeVideo[] = "VIDEO";
const char kDoodleTypeInteractive[] = "INTERACTIVE";
const char kDoodleTypeInlineInteractive[] = "INLINE_INTERACTIVE";
const char kDoodleTypeSlideshow[] = "SLIDESHOW";
// JSON keys for DoodleImage fields.
const char kKeyUrl[] = "url";
// JSON keys for DoodleConfig fields.
const char kKeyDoodleType[] = "doodle_type";
const char kKeyAltText[] = "alt_text";
const char kKeyTargetUrl[] = "target_url";
const char kKeyLargeImage[] = "large_image";
const char kKeyLargeCtaImage[] = "large_cta_image";
std::string DoodleTypeToString(DoodleType type) {
switch (type) {
case DoodleType::UNKNOWN:
return kDoodleTypeUnknown;
case DoodleType::SIMPLE:
return kDoodleTypeSimple;
case DoodleType::RANDOM:
return kDoodleTypeRandom;
case DoodleType::VIDEO:
return kDoodleTypeVideo;
case DoodleType::INTERACTIVE:
return kDoodleTypeInteractive;
case DoodleType::INLINE_INTERACTIVE:
return kDoodleTypeInlineInteractive;
case DoodleType::SLIDESHOW:
return kDoodleTypeSlideshow;
}
NOTREACHED();
return std::string();
}
DoodleType DoodleTypeFromString(const std::string& type_str) {
if (type_str == kDoodleTypeSimple) {
return DoodleType::SIMPLE;
}
if (type_str == kDoodleTypeRandom) {
return DoodleType::RANDOM;
}
if (type_str == kDoodleTypeVideo) {
return DoodleType::VIDEO;
}
if (type_str == kDoodleTypeInteractive) {
return DoodleType::INTERACTIVE;
}
if (type_str == kDoodleTypeInlineInteractive) {
return DoodleType::INLINE_INTERACTIVE;
}
if (type_str == kDoodleTypeSlideshow) {
return DoodleType::SLIDESHOW;
}
return DoodleType::UNKNOWN;
}
GURL ResolvePossiblyRelativeUrl(const std::string& url_str,
const base::Optional<GURL>& base_url) {
if (!base_url.has_value()) {
return GURL(url_str);
}
return base_url->Resolve(url_str);
}
GURL ParseUrl(const base::DictionaryValue& parent_dict,
const std::string& key,
const base::Optional<GURL>& base_url) {
std::string url_str;
if (!parent_dict.GetString(key, &url_str) || url_str.empty()) {
return GURL();
}
return ResolvePossiblyRelativeUrl(url_str, base_url);
}
base::Optional<DoodleImage> ParseImage(const base::DictionaryValue& parent_dict,
const std::string& key,
const base::Optional<GURL>& base_url) {
const base::DictionaryValue* image_dict = nullptr;
if (!parent_dict.GetDictionary(key, &image_dict)) {
return base::nullopt;
}
return DoodleImage::FromDictionary(*image_dict, base_url);
}
} // namespace
// static
base::Optional<DoodleImage> DoodleImage::FromDictionary(
const base::DictionaryValue& dict,
const base::Optional<GURL>& base_url) {
// The URL is the only required field.
GURL url = ParseUrl(dict, kKeyUrl, base_url);
if (!url.is_valid()) {
return base::nullopt;
}
return DoodleImage(url);
}
DoodleImage::DoodleImage(const GURL& url) : url(url) {
DCHECK(url.is_valid());
}
DoodleImage::~DoodleImage() = default;
std::unique_ptr<base::DictionaryValue> DoodleImage::ToDictionary() const {
auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString(kKeyUrl, url.spec());
return dict;
}
bool DoodleImage::operator==(const DoodleImage& other) const {
return url == other.url;
}
bool DoodleImage::operator!=(const DoodleImage& other) const {
return !(*this == other);
}
DoodleConfig::DoodleConfig(DoodleType doodle_type,
const DoodleImage& large_image)
: doodle_type(doodle_type), large_image(large_image) {}
DoodleConfig::DoodleConfig(const DoodleConfig& config) = default;
DoodleConfig::~DoodleConfig() = default;
// static
base::Optional<DoodleConfig> DoodleConfig::FromDictionary(
const base::DictionaryValue& dict,
const base::Optional<GURL>& base_url) {
// The |large_image| field is required (it's the "default" representation for
// the doodle).
base::Optional<DoodleImage> large_image =
ParseImage(dict, kKeyLargeImage, base_url);
if (!large_image.has_value()) {
return base::nullopt;
}
std::string type_str;
dict.GetString(kKeyDoodleType, &type_str);
DoodleConfig doodle(DoodleTypeFromString(type_str), large_image.value());
dict.GetString(kKeyAltText, &doodle.alt_text);
doodle.target_url = ParseUrl(dict, kKeyTargetUrl, base_url);
doodle.large_cta_image = ParseImage(dict, kKeyLargeCtaImage, base_url);
return doodle;
}
std::unique_ptr<base::DictionaryValue> DoodleConfig::ToDictionary() const {
auto dict = base::MakeUnique<base::DictionaryValue>();
dict->SetString(kKeyDoodleType, DoodleTypeToString(doodle_type));
dict->SetString(kKeyAltText, alt_text);
dict->SetString(kKeyTargetUrl, target_url.spec());
dict->Set(kKeyLargeImage, large_image.ToDictionary());
if (large_cta_image.has_value()) {
dict->Set(kKeyLargeCtaImage, large_cta_image->ToDictionary());
}
return dict;
}
bool DoodleConfig::operator==(const DoodleConfig& other) const {
return doodle_type == other.doodle_type && alt_text == other.alt_text &&
large_image == other.large_image &&
large_cta_image == other.large_cta_image;
}
bool DoodleConfig::operator!=(const DoodleConfig& other) const {
return !(*this == other);
}
} // namespace doodle