Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: components/omnibox/suggestion_answer.cc

Issue 669573005: Add a class to parse answer json. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tweaked API and finished unit tests Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/omnibox/suggestion_answer.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12
13 namespace {
14
15 static const char* kAnswerJsonLines = "l";
16 static const char* kAnswerJsonImageLine = "il";
17 static const char* kAnswerJsonText = "t";
18 static const char* kAnswerJsonAdditionalText = "at";
19 static const char* kAnswerJsonStatusText = "st";
20 static const char* kAnswerJsonTextType = "tt";
21 static const char* kAnswerJsonImage = "i";
22 static const char* kAnswerJsonImageData = "i.d";
23
24 }
25
26 // SuggestionAnswer::TextField -------------------------------------------------
27
28 SuggestionAnswer::TextField::TextField() : type_(-1) {}
29 SuggestionAnswer::TextField::~TextField() {}
30
31 // static
32 bool SuggestionAnswer::TextField::ParseTextField(
33 const base::DictionaryValue* field_json, TextField* text_field) {
34 if (!field_json->GetString(kAnswerJsonText, &text_field->text_) ||
35 text_field->text_.empty())
36 return false;
37 if (!field_json->GetInteger(kAnswerJsonTextType, &text_field->type_))
38 return false;
39 return true;
40 }
41
42 bool SuggestionAnswer::TextField::operator==(const TextField& field) const {
43 return type_ == field.type_ && text_ == field.text_;
44 }
45
46 bool SuggestionAnswer::TextField::operator!=(const TextField& field) const {
47 return !operator==(field);
48 }
49
50 void SuggestionAnswer::TextField::Clear() {
51 text_.clear();
52 type_ = -1;
53 }
54
55 // SuggestionAnswer::ImageLine -------------------------------------------------
56
57 SuggestionAnswer::ImageLine::ImageLine() : is_valid_(false) {}
58 SuggestionAnswer::ImageLine::~ImageLine() {}
59
60 // static
61 bool SuggestionAnswer::ImageLine::ParseImageLine(
62 const base::DictionaryValue* line_json, ImageLine* image_line) {
groby-ooo-7-16 2014/10/23 00:46:19 Why not just return ImageLine by value? (for all P
Justin Donnelly 2014/10/23 17:59:37 Fair question. Again, just because of the ubiquit
groby-ooo-7-16 2014/10/23 21:59:54 It's ubiquitous and ugly :) You're right, GetAnswe
Justin Donnelly 2014/10/24 14:58:08 I've left this as-is for now since they "two diffe
63 const base::DictionaryValue* inner_json;
64 if (!line_json->GetDictionary(kAnswerJsonImageLine, &inner_json))
65 return false;
66
67 const base::ListValue* fields_json;
68 if (!inner_json->GetList(kAnswerJsonText, &fields_json) ||
69 fields_json->GetSize() == 0)
70 return false;
71
72 for (size_t i = 0; i < fields_json->GetSize(); ++i) {
73 const base::DictionaryValue* field_json;
74 TextField text_field;
75 if (!fields_json->GetDictionary(i, &field_json) ||
76 !TextField::ParseTextField(field_json, &text_field))
77 return false;
78 image_line->text_fields_.push_back(text_field);
79 }
80
81 if (inner_json->HasKey(kAnswerJsonAdditionalText)) {
82 const base::DictionaryValue* field_json;
83 if (!inner_json->GetDictionary(kAnswerJsonAdditionalText, &field_json) ||
84 !TextField::ParseTextField(field_json, &image_line->additional_text_))
85 return false;
86 }
87
88 if (inner_json->HasKey(kAnswerJsonStatusText)) {
89 const base::DictionaryValue* field_json;
90 if (!inner_json->GetDictionary(kAnswerJsonStatusText, &field_json) ||
91 !TextField::ParseTextField(field_json, &image_line->status_text_))
92 return false;
93 }
94
95 if (inner_json->HasKey(kAnswerJsonImage)) {
96 base::string16 url_string;
97 if (!inner_json->GetString(kAnswerJsonImageData, &url_string) ||
98 url_string.empty())
99 return false;
100 // If necessary, concatenate scheme and host/path using only ':' as
101 // separator. This is due to the results delivering strings of the form
102 // "//host/path", which is web-speak for "use the enclosing page's scheme",
103 // but not a valid path of an URL.
104 if (StartsWith(url_string, base::ASCIIToUTF16("//"), false))
105 image_line->image_url_ = GURL(base::ASCIIToUTF16("https:") + url_string);
106 else
107 image_line->image_url_ = GURL(url_string);
108
109 if (!image_line->image_url_.is_valid())
groby-ooo-7-16 2014/10/23 00:46:19 I've been thinking of adding UMA metrics for parse
Justin Donnelly 2014/10/23 17:59:37 Given how you mentioned that Finch team is about t
110 return false;
111 }
112
113 image_line->is_valid_ = true;
groby-ooo-7-16 2014/10/23 00:46:19 Probably want to force that to invalid at the top.
Justin Donnelly 2014/10/23 17:59:37 Done.
114
115 return true;
116 }
117
118 bool SuggestionAnswer::ImageLine::operator==(const ImageLine& line) const {
119 if (text_fields_.size() != line.text_fields_.size())
groby-ooo-7-16 2014/10/23 00:46:19 std::vector has equality comparison, so you should
Justin Donnelly 2014/10/23 17:59:37 Done.
120 return false;
121 for (size_t i = 0; i < text_fields_.size(); ++i) {
122 if (text_fields_[i] != line.text_fields_[i])
123 return false;
124 }
125 return additional_text_ == line.additional_text_ &&
126 status_text_ == line.status_text_ &&
127 image_url_ == line.image_url_;
128 }
129
130 bool SuggestionAnswer::ImageLine::operator!=(const ImageLine& line) const {
131 return !operator==(line);
132 }
133
134 void SuggestionAnswer::ImageLine::Clear() {
135 text_fields_.clear();
136 additional_text_.Clear();
137 status_text_.Clear();
138 image_url_ = GURL();
139 is_valid_ = false;
140 }
141
142 // SuggestionAnswer ------------------------------------------------------------
143
144 SuggestionAnswer::SuggestionAnswer() : type_(-1) {}
145 SuggestionAnswer::~SuggestionAnswer() {}
146
147 // static
148 bool SuggestionAnswer::ParseAnswer(
149 const std::string& answer_json, SuggestionAnswer* answer) {
150 scoped_ptr<base::Value> value(base::JSONReader::Read(answer_json));
151 base::DictionaryValue* dict;
152 if (!value.get() || !value->GetAsDictionary(&dict))
153 return false;
154
155 return ParseAnswer(dict, answer);
156 }
157
158 // static
159 bool SuggestionAnswer::ParseAnswer(
160 const base::DictionaryValue* answer_json, SuggestionAnswer* answer) {
161 const base::ListValue* lines_json;
162 if (!answer_json->GetList(kAnswerJsonLines, &lines_json) ||
163 lines_json->GetSize() != 2)
164 return false;
165
166 const base::DictionaryValue* first_line_json;
167 if (!lines_json->GetDictionary(0, &first_line_json) ||
168 !ImageLine::ParseImageLine(first_line_json, &answer->first_line_))
169 return false;
170 const base::DictionaryValue* second_line_json;
171 if (!lines_json->GetDictionary(1, &second_line_json) ||
172 !ImageLine::ParseImageLine(second_line_json, &answer->second_line_))
173 return false;
174
175 return true;
176 }
177
178 bool SuggestionAnswer::operator==(const SuggestionAnswer& answer) const {
179 return type_ == answer.type_ &&
180 first_line_ == answer.first_line_ &&
181 second_line_ == answer.second_line_;
182 }
183
184 bool SuggestionAnswer::operator!=(const SuggestionAnswer& answer) const {
185 return !operator==(answer);
186 }
187
188 void SuggestionAnswer::SetType(const std::string& type) {
groby-ooo-7-16 2014/10/23 00:46:19 Do we really need string & string16 for this?
Justin Donnelly 2014/10/23 17:59:37 Done.
189 if (!base::StringToInt(type, &type_))
190 type_ = -1;
191 }
192
193 void SuggestionAnswer::SetType(const base::string16& type) {
194 if (!base::StringToInt(type, &type_))
195 type_ = -1;
196 }
197
198 void SuggestionAnswer::Clear() {
199 first_line_.Clear();
200 second_line_.Clear();
201 type_ = -1;
202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698