#include "components/omnibox/browser/suggestion_answer.h"
#include <stddef.h>
#include <memory>
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "build/build_config.h"
#include "third_party/omnibox_proto/answer_type.pb.h"
#include "url/url_constants.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_string.h"
#include "components/omnibox/browser/jni_headers/SuggestionAnswer_jni.h"
using base::android::ScopedJavaLocalRef;
#endif
namespace {
static constexpr char kAnswerJsonLines[] = …;
static constexpr char kAnswerJsonImageLine[] = …;
static constexpr char kAnswerJsonText[] = …;
static constexpr char kAnswerJsonAdditionalText[] = …;
static constexpr char kAnswerJsonStatusText[] = …;
static constexpr char kAnswerJsonAccessibilityLabel[] = …;
static constexpr char kAnswerJsonTextType[] = …;
static constexpr char kAnswerJsonNumLines[] = …;
static constexpr char kAnswerJsonImage[] = …;
static constexpr char kAnswerJsonImageData[] = …;
constexpr char kAnswerUsedUmaHistogramName[] = …;
void AppendWithSpace(const SuggestionAnswer::TextField* text,
std::u16string* output) { … }
}
namespace omnibox::answer_data_parser {
GURL GetFormattedURL(const std::string* url_string) { … }
void SetColorType(int text_type,
omnibox::FormattedString::FormattedStringFragment* fragment) { … }
bool ParseJsonToFormattedStringFragment(
const base::Value::Dict& field_json,
omnibox::FormattedString* formatted_string) { … }
bool ParseJsonToFormattedString(const base::Value::Dict& line_json,
omnibox::FormattedString* formatted_string,
omnibox::Image* image) { … }
bool ParseJsonToAnswerData(const base::Value::Dict& answer_json,
omnibox::RichAnswerTemplate* answer_template) { … }
void LogAnswerUsed(omnibox::AnswerType answer_type) { … }
}
SuggestionAnswer::TextField::TextField() = default;
SuggestionAnswer::TextField::~TextField() = default;
SuggestionAnswer::TextField::TextField(const TextField&) = default;
SuggestionAnswer::TextField::TextField(TextField&&) noexcept = default;
SuggestionAnswer::TextField& SuggestionAnswer::TextField::operator=(
const TextField&) = default;
SuggestionAnswer::TextField& SuggestionAnswer::TextField::operator=(
TextField&&) noexcept = default;
bool SuggestionAnswer::TextField::ParseTextField(
const base::Value::Dict& field_json,
TextField* text_field) { … }
bool SuggestionAnswer::TextField::Equals(const TextField& field) const { … }
size_t SuggestionAnswer::TextField::EstimateMemoryUsage() const { … }
SuggestionAnswer::ImageLine::ImageLine() : … { … }
SuggestionAnswer::ImageLine::ImageLine(const ImageLine& line) = default;
SuggestionAnswer::ImageLine::ImageLine(ImageLine&&) noexcept = default;
SuggestionAnswer::ImageLine& SuggestionAnswer::ImageLine::operator=(
const ImageLine& line) = default;
SuggestionAnswer::ImageLine& SuggestionAnswer::ImageLine::operator=(
ImageLine&&) noexcept = default;
SuggestionAnswer::ImageLine::~ImageLine() = default;
bool SuggestionAnswer::ImageLine::ParseImageLine(
const base::Value::Dict& line_json,
ImageLine* image_line) { … }
bool SuggestionAnswer::ImageLine::Equals(const ImageLine& line) const { … }
std::u16string SuggestionAnswer::ImageLine::AccessibleText() const { … }
size_t SuggestionAnswer::ImageLine::EstimateMemoryUsage() const { … }
void SuggestionAnswer::ImageLine::SetTextStyles(
int from_type,
SuggestionAnswer::TextStyle style) { … }
SuggestionAnswer::SuggestionAnswer() = default;
SuggestionAnswer::SuggestionAnswer(const SuggestionAnswer& answer) = default;
SuggestionAnswer::SuggestionAnswer(SuggestionAnswer&&) noexcept = default;
SuggestionAnswer& SuggestionAnswer::operator=(const SuggestionAnswer& answer) =
default;
SuggestionAnswer& SuggestionAnswer::operator=(SuggestionAnswer&&) noexcept =
default;
SuggestionAnswer::~SuggestionAnswer() = default;
bool SuggestionAnswer::ParseAnswer(const base::Value::Dict& answer_json,
omnibox::AnswerType answer_type,
SuggestionAnswer* result) { … }
bool SuggestionAnswer::Equals(const SuggestionAnswer& answer) const { … }
size_t SuggestionAnswer::EstimateMemoryUsage() const { … }
void SuggestionAnswer::InterpretTextTypes(omnibox::AnswerType answer_type) { … }
bool SuggestionAnswer::IsExceptedFromLineReversal(
omnibox::AnswerType answer_type) const { … }
#if BUILDFLAG(IS_ANDROID)
namespace {
ScopedJavaLocalRef<jobject> CreateJavaTextField(
JNIEnv* env,
const SuggestionAnswer::TextField& text_field) {
return Java_SuggestionAnswer_createTextField(
env, text_field.type(),
base::android::ConvertUTF16ToJavaString(env, text_field.text()),
static_cast<int>(text_field.style()), text_field.num_lines());
}
ScopedJavaLocalRef<jobject> CreateJavaImageLine(
JNIEnv* env,
const SuggestionAnswer::ImageLine* image_line) {
ScopedJavaLocalRef<jobject> jtext_fields =
Java_SuggestionAnswer_createTextFieldList(env);
for (const SuggestionAnswer::TextField& text_field :
image_line->text_fields()) {
Java_SuggestionAnswer_addTextFieldToList(
env, jtext_fields, CreateJavaTextField(env, text_field));
}
ScopedJavaLocalRef<jobject> jadditional_text;
if (image_line->additional_text()) {
jadditional_text = CreateJavaTextField(env, *image_line->additional_text());
}
ScopedJavaLocalRef<jobject> jstatus_text;
if (image_line->status_text()) {
jstatus_text = CreateJavaTextField(env, *image_line->status_text());
}
ScopedJavaLocalRef<jstring> jimage_url;
if (image_line->image_url().is_valid()) {
jimage_url = base::android::ConvertUTF8ToJavaString(
env, image_line->image_url().spec());
}
return Java_SuggestionAnswer_createImageLine(
env, jtext_fields, jadditional_text, jstatus_text, jimage_url);
}
}
ScopedJavaLocalRef<jobject> SuggestionAnswer::CreateJavaObject(
omnibox::AnswerType answer_type) const {
JNIEnv* env = jni_zero::AttachCurrentThread();
return Java_SuggestionAnswer_createSuggestionAnswer(
env, answer_type, CreateJavaImageLine(env, &first_line_),
CreateJavaImageLine(env, &second_line_));
}
#endif