1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
// Copyright 2014 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.
#ifndef COMPONENTS_OMNIBOX_BROWSER_SUGGESTION_ANSWER_H_
#define COMPONENTS_OMNIBOX_BROWSER_SUGGESTION_ANSWER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "url/gurl.h"
namespace base {
class DictionaryValue;
}
// Structured representation of the JSON payload of a suggestion with an answer.
// An answer has exactly two image lines, so called because they are a
// combination of text and an optional image URL. Each image line has 1 or more
// text fields, each of which is required to contain a string and an integer
// type. The text fields are contained in a non-empty vector and two optional
// named properties, referred to as "additional text" and "status text".
//
// When represented in the UI, these elements should be styled and laid out
// according to the specification at https://goto.google.com/ais_api.
class SuggestionAnswer {
public:
class TextField;
typedef std::vector<TextField> TextFields;
typedef std::vector<GURL> URLs;
// These values are based on the server-side type AnswerTriggererKey. Do not
// remove values from this enum (or the client/server will become out of
// sync).
enum AnswerType {
ANSWER_TYPE_INVALID,
ANSWER_TYPE_DICTIONARY,
ANSWER_TYPE_FINANCE,
ANSWER_TYPE_KNOWLEDGE_GRAPH,
ANSWER_TYPE_LOCAL,
ANSWER_TYPE_SPORTS,
ANSWER_TYPE_SUNRISE,
ANSWER_TYPE_TRANSLATION,
ANSWER_TYPE_WEATHER,
ANSWER_TYPE_WHEN_IS,
ANSWER_TYPE_CURRENCY,
ANSWER_TYPE_LOCAL_TIME,
ANSWER_TYPE_PLAY_INSTALL,
};
static_assert(ANSWER_TYPE_PLAY_INSTALL == 12,
"Do not remove enums from AnswerType");
// These values are named and numbered to match a specification at go/ais_api.
// The values are only used for answer results.
enum TextType {
// Deprecated: ANSWER = 1,
// Deprecated: HEADLINE = 2,
TOP_ALIGNED = 3,
// Deprecated: DESCRIPTION = 4,
DESCRIPTION_NEGATIVE = 5,
DESCRIPTION_POSITIVE = 6,
// Deprecated: MORE_INFO = 7,
SUGGESTION = 8,
// Deprecated: SUGGESTION_POSITIVE = 9,
// Deprecated: SUGGESTION_NEGATIVE = 10,
// Deprecated: SUGGESTION_LINK = 11,
// Deprecated: STATUS = 12,
PERSONALIZED_SUGGESTION = 13,
// Deprecated: IMMERSIVE_DESCRIPTION_TEXT = 14,
// Deprecated: DATE_TEXT = 15,
// Deprecated: PREVIEW_TEXT = 16,
ANSWER_TEXT_MEDIUM = 17,
ANSWER_TEXT_LARGE = 18,
SUGGESTION_SECONDARY_TEXT_SMALL = 19,
SUGGESTION_SECONDARY_TEXT_MEDIUM = 20,
};
// The above TextType values match what is sent by server, but are not used
// normally by new answers. These enum values are used instead, styling
// answer text through a client-side process of interpretation that depends
// on answer type, text type, and even line rank (first|second). This
// interpretation process happens during answer parsing and allows
// downstream logic to remain simple, deciding how to present answers
// based on a finite set of text types instead of answer properties and rules.
// Performance is also improved by doing this once at parse time instead of
// every time render text is invalidated.
enum class TextStyle {
NONE,
NORMAL,
NORMAL_DIM,
SECONDARY,
BOLD,
POSITIVE,
NEGATIVE,
SUPERIOR, // This is not superscript (see gfx::BaselineStyle).
};
class TextField {
public:
TextField();
~TextField();
// Parses |field_json| and populates |text_field| with the contents. If any
// of the required elements is missing, returns false and leaves text_field
// in a partially populated state.
static bool ParseTextField(const base::DictionaryValue* field_json,
TextField* text_field);
const base::string16& text() const { return text_; }
int type() const { return type_; }
TextStyle style() const { return style_; }
void set_style(TextStyle style) { style_ = style; }
bool has_num_lines() const { return has_num_lines_; }
int num_lines() const { return num_lines_; }
bool Equals(const TextField& field) const;
// Estimates dynamic memory usage.
// See base/trace_event/memory_usage_estimator.h for more info.
size_t EstimateMemoryUsage() const;
private:
base::string16 text_;
int type_ = -1;
bool has_num_lines_ = false;
int num_lines_ = 1;
TextStyle style_ = TextStyle::NONE;
FRIEND_TEST_ALL_PREFIXES(SuggestionAnswerTest, DifferentValuesAreUnequal);
// No DISALLOW_COPY_AND_ASSIGN since we depend on the copy constructor in
// SuggestionAnswer::copy and the assignment operator as values in vector.
};
class ImageLine {
public:
ImageLine();
explicit ImageLine(const ImageLine& line);
ImageLine& operator=(const ImageLine& line);
~ImageLine();
// Parses |line_json| and populates |image_line| with the contents. If any
// of the required elements is missing, returns false and leaves text_field
// in a partially populated state.
static bool ParseImageLine(const base::DictionaryValue* line_json,
ImageLine* image_line);
const TextFields& text_fields() const { return text_fields_; }
int num_text_lines() const { return num_text_lines_; }
const TextField* additional_text() const {
if (additional_text_)
return &additional_text_.value();
else
return nullptr;
}
const TextField* status_text() const {
if (status_text_)
return &status_text_.value();
else
return nullptr;
}
const GURL& image_url() const { return image_url_; }
bool Equals(const ImageLine& line) const;
// Returns a string appropriate for use as a readable representation of the
// content of this line.
base::string16 AccessibleText() const;
// Estimates dynamic memory usage.
// See base/trace_event/memory_usage_estimator.h for more info.
size_t EstimateMemoryUsage() const;
// Set text style on all fields where text type matches from_type and style
// is not already set. Using from_type = 0 matches all values from TextType.
void SetTextStyles(int from_type, TextStyle style);
private:
TextFields text_fields_;
int num_text_lines_;
base::Optional<TextField> additional_text_;
base::Optional<TextField> status_text_;
GURL image_url_;
FRIEND_TEST_ALL_PREFIXES(SuggestionAnswerTest, DifferentValuesAreUnequal);
};
SuggestionAnswer();
SuggestionAnswer(const SuggestionAnswer& answer);
SuggestionAnswer& operator=(const SuggestionAnswer& answer);
~SuggestionAnswer();
// Parses |answer_json| and fills a SuggestionAnswer containing the
// contents. Returns true on success. If the supplied data is not well
// formed or is missing required elements, returns false instead.
static bool ParseAnswer(const base::DictionaryValue* answer_json,
const base::string16& answer_type_str,
SuggestionAnswer* answer);
const GURL& image_url() const { return image_url_; }
const ImageLine& first_line() const { return first_line_; }
const ImageLine& second_line() const { return second_line_; }
// Answer type accessors. Valid types are non-negative and defined at
// https://goto.google.com/visual_element_configuration.
int type() const { return type_; }
void set_type(int type) { type_ = type; }
bool Equals(const SuggestionAnswer& answer) const;
// Retrieves any image URLs appearing in this answer and adds them to |urls|.
void AddImageURLsTo(URLs* urls) const;
// Estimates dynamic memory usage.
// See base/trace_event/memory_usage_estimator.h for more info.
size_t EstimateMemoryUsage() const;
// For new answers, replace old answer text types with appropriate new types.
void InterpretTextTypes();
private:
GURL image_url_;
ImageLine first_line_;
ImageLine second_line_;
int type_ = -1;
FRIEND_TEST_ALL_PREFIXES(SuggestionAnswerTest, DifferentValuesAreUnequal);
};
#endif // COMPONENTS_OMNIBOX_BROWSER_SUGGESTION_ANSWER_H_
|