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

Side by Side Diff: content/renderer/manifest/manifest_parser.cc

Issue 1571633002: Pass Manifest JSON paser error line and column number to console. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add comments Created 4 years, 11 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/manifest/manifest_parser.h" 5 #include "content/renderer/manifest/manifest_parser.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/strings/nullable_string16.h" 10 #include "base/strings/nullable_string16.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 : data_(data), 98 : data_(data),
99 manifest_url_(manifest_url), 99 manifest_url_(manifest_url),
100 document_url_(document_url), 100 document_url_(document_url),
101 failed_(false) { 101 failed_(false) {
102 } 102 }
103 103
104 ManifestParser::~ManifestParser() { 104 ManifestParser::~ManifestParser() {
105 } 105 }
106 106
107 void ManifestParser::Parse() { 107 void ManifestParser::Parse() {
108 std::string parse_error; 108 std::string error_msg;
109 int error_line = 0;
110 int error_column = 0;
109 scoped_ptr<base::Value> value = base::JSONReader::ReadAndReturnError( 111 scoped_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
110 data_, base::JSON_PARSE_RFC, nullptr, &parse_error); 112 data_, base::JSON_PARSE_RFC, nullptr, &error_msg, &error_line,
113 &error_column);
111 114
112 if (!value) { 115 if (!value) {
113 errors_.push_back(GetErrorPrefix() + parse_error); 116 AddErrorInfo(GetErrorPrefix() + error_msg, error_line, error_column);
114 ManifestUmaUtil::ParseFailed(); 117 ManifestUmaUtil::ParseFailed();
115 failed_ = true; 118 failed_ = true;
116 return; 119 return;
117 } 120 }
118 121
119 base::DictionaryValue* dictionary = nullptr; 122 base::DictionaryValue* dictionary = nullptr;
120 if (!value->GetAsDictionary(&dictionary)) { 123 if (!value->GetAsDictionary(&dictionary)) {
121 errors_.push_back(GetErrorPrefix() + 124 AddErrorInfo(GetErrorPrefix() +
122 "root element must be a valid JSON object."); 125 "root element must be a valid JSON object.");
123 ManifestUmaUtil::ParseFailed(); 126 ManifestUmaUtil::ParseFailed();
124 failed_ = true; 127 failed_ = true;
125 return; 128 return;
126 } 129 }
127 DCHECK(dictionary); 130 DCHECK(dictionary);
128 131
129 manifest_.name = ParseName(*dictionary); 132 manifest_.name = ParseName(*dictionary);
130 manifest_.short_name = ParseShortName(*dictionary); 133 manifest_.short_name = ParseShortName(*dictionary);
131 manifest_.start_url = ParseStartURL(*dictionary); 134 manifest_.start_url = ParseStartURL(*dictionary);
132 manifest_.display = ParseDisplay(*dictionary); 135 manifest_.display = ParseDisplay(*dictionary);
133 manifest_.orientation = ParseOrientation(*dictionary); 136 manifest_.orientation = ParseOrientation(*dictionary);
134 manifest_.icons = ParseIcons(*dictionary); 137 manifest_.icons = ParseIcons(*dictionary);
135 manifest_.related_applications = ParseRelatedApplications(*dictionary); 138 manifest_.related_applications = ParseRelatedApplications(*dictionary);
136 manifest_.prefer_related_applications = 139 manifest_.prefer_related_applications =
137 ParsePreferRelatedApplications(*dictionary); 140 ParsePreferRelatedApplications(*dictionary);
138 manifest_.theme_color = ParseThemeColor(*dictionary); 141 manifest_.theme_color = ParseThemeColor(*dictionary);
139 manifest_.background_color = ParseBackgroundColor(*dictionary); 142 manifest_.background_color = ParseBackgroundColor(*dictionary);
140 manifest_.gcm_sender_id = ParseGCMSenderID(*dictionary); 143 manifest_.gcm_sender_id = ParseGCMSenderID(*dictionary);
141 144
142 ManifestUmaUtil::ParseSucceeded(manifest_); 145 ManifestUmaUtil::ParseSucceeded(manifest_);
143 } 146 }
144 147
145 const Manifest& ManifestParser::manifest() const { 148 const Manifest& ManifestParser::manifest() const {
146 return manifest_; 149 return manifest_;
147 } 150 }
148 151
149 const std::vector<std::string>& ManifestParser::errors() const { 152 const std::vector<scoped_ptr<ManifestParser::ErrorInfo>>&
153 ManifestParser::errors() const {
150 return errors_; 154 return errors_;
151 } 155 }
152 156
153 bool ManifestParser::failed() const { 157 bool ManifestParser::failed() const {
154 return failed_; 158 return failed_;
155 } 159 }
156 160
157 bool ManifestParser::ParseBoolean(const base::DictionaryValue& dictionary, 161 bool ManifestParser::ParseBoolean(const base::DictionaryValue& dictionary,
158 const std::string& key, 162 const std::string& key,
159 bool default_value) { 163 bool default_value) {
160 if (!dictionary.HasKey(key)) 164 if (!dictionary.HasKey(key))
161 return default_value; 165 return default_value;
162 166
163 bool value; 167 bool value;
164 if (!dictionary.GetBoolean(key, &value)) { 168 if (!dictionary.GetBoolean(key, &value)) {
165 errors_.push_back(GetErrorPrefix() + 169 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, type " +
166 "property '" + key + "' ignored, type boolean expected."); 170 "boolean expected.");
167 return default_value; 171 return default_value;
168 } 172 }
169 173
170 return value; 174 return value;
171 } 175 }
172 176
173 base::NullableString16 ManifestParser::ParseString( 177 base::NullableString16 ManifestParser::ParseString(
174 const base::DictionaryValue& dictionary, 178 const base::DictionaryValue& dictionary,
175 const std::string& key, 179 const std::string& key,
176 TrimType trim) { 180 TrimType trim) {
177 if (!dictionary.HasKey(key)) 181 if (!dictionary.HasKey(key))
178 return base::NullableString16(); 182 return base::NullableString16();
179 183
180 base::string16 value; 184 base::string16 value;
181 if (!dictionary.GetString(key, &value)) { 185 if (!dictionary.GetString(key, &value)) {
182 errors_.push_back(GetErrorPrefix() + 186 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, type " +
183 "property '" + key + "' ignored, type string expected."); 187 "string expected.");
184 return base::NullableString16(); 188 return base::NullableString16();
185 } 189 }
186 190
187 if (trim == Trim) 191 if (trim == Trim)
188 base::TrimWhitespace(value, base::TRIM_ALL, &value); 192 base::TrimWhitespace(value, base::TRIM_ALL, &value);
189 return base::NullableString16(value, false); 193 return base::NullableString16(value, false);
190 } 194 }
191 195
192 int64_t ManifestParser::ParseColor( 196 int64_t ManifestParser::ParseColor(
193 const base::DictionaryValue& dictionary, 197 const base::DictionaryValue& dictionary,
194 const std::string& key) { 198 const std::string& key) {
195 base::NullableString16 parsed_color = ParseString(dictionary, key, Trim); 199 base::NullableString16 parsed_color = ParseString(dictionary, key, Trim);
196 if (parsed_color.is_null()) 200 if (parsed_color.is_null())
197 return Manifest::kInvalidOrMissingColor; 201 return Manifest::kInvalidOrMissingColor;
198 202
199 blink::WebColor color; 203 blink::WebColor color;
200 if (!blink::WebCSSParser::parseColor(&color, parsed_color.string())) { 204 if (!blink::WebCSSParser::parseColor(&color, parsed_color.string())) {
201 errors_.push_back(GetErrorPrefix() + 205 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, '" +
202 "property '" + key + "' ignored, '" + 206 base::UTF16ToUTF8(parsed_color.string()) + "' is not a " +
203 base::UTF16ToUTF8(parsed_color.string()) + 207 "valid color.");
204 "' is not a valid color.");
205 return Manifest::kInvalidOrMissingColor; 208 return Manifest::kInvalidOrMissingColor;
206 } 209 }
207 210
208 // We do this here because Java does not have an unsigned int32_t type so 211 // We do this here because Java does not have an unsigned int32_t type so
209 // colors with high alpha values will be negative. Instead of doing the 212 // colors with high alpha values will be negative. Instead of doing the
210 // conversion after we pass over to Java, we do it here as it is easier and 213 // conversion after we pass over to Java, we do it here as it is easier and
211 // clearer. 214 // clearer.
212 int32_t signed_color = reinterpret_cast<int32_t&>(color); 215 int32_t signed_color = reinterpret_cast<int32_t&>(color);
213 return static_cast<int64_t>(signed_color); 216 return static_cast<int64_t>(signed_color);
214 } 217 }
(...skipping 17 matching lines...) Expand all
232 const base::DictionaryValue& dictionary) { 235 const base::DictionaryValue& dictionary) {
233 return ParseString(dictionary, "short_name", Trim); 236 return ParseString(dictionary, "short_name", Trim);
234 } 237 }
235 238
236 GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) { 239 GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) {
237 GURL start_url = ParseURL(dictionary, "start_url", manifest_url_); 240 GURL start_url = ParseURL(dictionary, "start_url", manifest_url_);
238 if (!start_url.is_valid()) 241 if (!start_url.is_valid())
239 return GURL(); 242 return GURL();
240 243
241 if (start_url.GetOrigin() != document_url_.GetOrigin()) { 244 if (start_url.GetOrigin() != document_url_.GetOrigin()) {
242 errors_.push_back(GetErrorPrefix() + "property 'start_url' ignored, should " 245 AddErrorInfo(GetErrorPrefix() + "property 'start_url' ignored, should be " +
243 "be same origin as document."); 246 "same origin as document.");
244 return GURL(); 247 return GURL();
245 } 248 }
246 249
247 return start_url; 250 return start_url;
248 } 251 }
249 252
250 blink::WebDisplayMode ManifestParser::ParseDisplay( 253 blink::WebDisplayMode ManifestParser::ParseDisplay(
251 const base::DictionaryValue& dictionary) { 254 const base::DictionaryValue& dictionary) {
252 base::NullableString16 display = ParseString(dictionary, "display", Trim); 255 base::NullableString16 display = ParseString(dictionary, "display", Trim);
253 if (display.is_null()) 256 if (display.is_null())
254 return blink::WebDisplayModeUndefined; 257 return blink::WebDisplayModeUndefined;
255 258
256 if (base::LowerCaseEqualsASCII(display.string(), "fullscreen")) 259 if (base::LowerCaseEqualsASCII(display.string(), "fullscreen"))
257 return blink::WebDisplayModeFullscreen; 260 return blink::WebDisplayModeFullscreen;
258 else if (base::LowerCaseEqualsASCII(display.string(), "standalone")) 261 else if (base::LowerCaseEqualsASCII(display.string(), "standalone"))
259 return blink::WebDisplayModeStandalone; 262 return blink::WebDisplayModeStandalone;
260 else if (base::LowerCaseEqualsASCII(display.string(), "minimal-ui")) 263 else if (base::LowerCaseEqualsASCII(display.string(), "minimal-ui"))
261 return blink::WebDisplayModeMinimalUi; 264 return blink::WebDisplayModeMinimalUi;
262 else if (base::LowerCaseEqualsASCII(display.string(), "browser")) 265 else if (base::LowerCaseEqualsASCII(display.string(), "browser"))
263 return blink::WebDisplayModeBrowser; 266 return blink::WebDisplayModeBrowser;
264 else { 267 else {
265 errors_.push_back(GetErrorPrefix() + "unknown 'display' value ignored."); 268 AddErrorInfo(GetErrorPrefix() + "unknown 'display' value ignored.");
266 return blink::WebDisplayModeUndefined; 269 return blink::WebDisplayModeUndefined;
267 } 270 }
268 } 271 }
269 272
270 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation( 273 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation(
271 const base::DictionaryValue& dictionary) { 274 const base::DictionaryValue& dictionary) {
272 base::NullableString16 orientation = 275 base::NullableString16 orientation =
273 ParseString(dictionary, "orientation", Trim); 276 ParseString(dictionary, "orientation", Trim);
274 277
275 if (orientation.is_null()) 278 if (orientation.is_null())
(...skipping 13 matching lines...) Expand all
289 return blink::WebScreenOrientationLockLandscapeSecondary; 292 return blink::WebScreenOrientationLockLandscapeSecondary;
290 else if (base::LowerCaseEqualsASCII(orientation.string(), "portrait")) 293 else if (base::LowerCaseEqualsASCII(orientation.string(), "portrait"))
291 return blink::WebScreenOrientationLockPortrait; 294 return blink::WebScreenOrientationLockPortrait;
292 else if (base::LowerCaseEqualsASCII(orientation.string(), 295 else if (base::LowerCaseEqualsASCII(orientation.string(),
293 "portrait-primary")) 296 "portrait-primary"))
294 return blink::WebScreenOrientationLockPortraitPrimary; 297 return blink::WebScreenOrientationLockPortraitPrimary;
295 else if (base::LowerCaseEqualsASCII(orientation.string(), 298 else if (base::LowerCaseEqualsASCII(orientation.string(),
296 "portrait-secondary")) 299 "portrait-secondary"))
297 return blink::WebScreenOrientationLockPortraitSecondary; 300 return blink::WebScreenOrientationLockPortraitSecondary;
298 else { 301 else {
299 errors_.push_back(GetErrorPrefix() + 302 AddErrorInfo(GetErrorPrefix() + "unknown 'orientation' value ignored.");
300 "unknown 'orientation' value ignored.");
301 return blink::WebScreenOrientationLockDefault; 303 return blink::WebScreenOrientationLockDefault;
302 } 304 }
303 } 305 }
304 306
305 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) { 307 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) {
306 return ParseURL(icon, "src", manifest_url_); 308 return ParseURL(icon, "src", manifest_url_);
307 } 309 }
308 310
309 base::NullableString16 ManifestParser::ParseIconType( 311 base::NullableString16 ManifestParser::ParseIconType(
310 const base::DictionaryValue& icon) { 312 const base::DictionaryValue& icon) {
311 return ParseString(icon, "type", Trim); 313 return ParseString(icon, "type", Trim);
312 } 314 }
313 315
314 double ManifestParser::ParseIconDensity(const base::DictionaryValue& icon) { 316 double ManifestParser::ParseIconDensity(const base::DictionaryValue& icon) {
315 double density; 317 double density;
316 if (!icon.HasKey("density")) 318 if (!icon.HasKey("density"))
317 return Manifest::Icon::kDefaultDensity; 319 return Manifest::Icon::kDefaultDensity;
318 320
319 if (!icon.GetDouble("density", &density) || density <= 0) { 321 if (!icon.GetDouble("density", &density) || density <= 0) {
320 errors_.push_back(GetErrorPrefix() + 322 AddErrorInfo(GetErrorPrefix() +
321 "icon 'density' ignored, must be float greater than 0."); 323 "icon 'density' ignored, must be float greater than 0.");
322 return Manifest::Icon::kDefaultDensity; 324 return Manifest::Icon::kDefaultDensity;
323 } 325 }
324 return density; 326 return density;
325 } 327 }
326 328
327 std::vector<gfx::Size> ManifestParser::ParseIconSizes( 329 std::vector<gfx::Size> ManifestParser::ParseIconSizes(
328 const base::DictionaryValue& icon) { 330 const base::DictionaryValue& icon) {
329 base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim); 331 base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim);
330 332
331 if (sizes_str.is_null()) 333 if (sizes_str.is_null())
332 return std::vector<gfx::Size>(); 334 return std::vector<gfx::Size>();
333 335
334 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string()); 336 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string());
335 if (sizes.empty()) { 337 if (sizes.empty()) {
336 errors_.push_back(GetErrorPrefix() + "found icon with no valid size."); 338 AddErrorInfo(GetErrorPrefix() + "found icon with no valid size.");
337 } 339 }
338 return sizes; 340 return sizes;
339 } 341 }
340 342
341 std::vector<Manifest::Icon> ManifestParser::ParseIcons( 343 std::vector<Manifest::Icon> ManifestParser::ParseIcons(
342 const base::DictionaryValue& dictionary) { 344 const base::DictionaryValue& dictionary) {
343 std::vector<Manifest::Icon> icons; 345 std::vector<Manifest::Icon> icons;
344 if (!dictionary.HasKey("icons")) 346 if (!dictionary.HasKey("icons"))
345 return icons; 347 return icons;
346 348
347 const base::ListValue* icons_list = nullptr; 349 const base::ListValue* icons_list = nullptr;
348 if (!dictionary.GetList("icons", &icons_list)) { 350 if (!dictionary.GetList("icons", &icons_list)) {
349 errors_.push_back(GetErrorPrefix() + 351 AddErrorInfo(GetErrorPrefix() +
350 "property 'icons' ignored, type array expected."); 352 "property 'icons' ignored, type array expected.");
351 return icons; 353 return icons;
352 } 354 }
353 355
354 for (size_t i = 0; i < icons_list->GetSize(); ++i) { 356 for (size_t i = 0; i < icons_list->GetSize(); ++i) {
355 const base::DictionaryValue* icon_dictionary = nullptr; 357 const base::DictionaryValue* icon_dictionary = nullptr;
356 if (!icons_list->GetDictionary(i, &icon_dictionary)) 358 if (!icons_list->GetDictionary(i, &icon_dictionary))
357 continue; 359 continue;
358 360
359 Manifest::Icon icon; 361 Manifest::Icon icon;
360 icon.src = ParseIconSrc(*icon_dictionary); 362 icon.src = ParseIconSrc(*icon_dictionary);
(...skipping 27 matching lines...) Expand all
388 390
389 std::vector<Manifest::RelatedApplication> 391 std::vector<Manifest::RelatedApplication>
390 ManifestParser::ParseRelatedApplications( 392 ManifestParser::ParseRelatedApplications(
391 const base::DictionaryValue& dictionary) { 393 const base::DictionaryValue& dictionary) {
392 std::vector<Manifest::RelatedApplication> applications; 394 std::vector<Manifest::RelatedApplication> applications;
393 if (!dictionary.HasKey("related_applications")) 395 if (!dictionary.HasKey("related_applications"))
394 return applications; 396 return applications;
395 397
396 const base::ListValue* applications_list = nullptr; 398 const base::ListValue* applications_list = nullptr;
397 if (!dictionary.GetList("related_applications", &applications_list)) { 399 if (!dictionary.GetList("related_applications", &applications_list)) {
398 errors_.push_back( 400 AddErrorInfo(
399 GetErrorPrefix() + 401 GetErrorPrefix() +
400 "property 'related_applications' ignored, type array expected."); 402 "property 'related_applications' ignored, type array expected.");
401 return applications; 403 return applications;
402 } 404 }
403 405
404 for (size_t i = 0; i < applications_list->GetSize(); ++i) { 406 for (size_t i = 0; i < applications_list->GetSize(); ++i) {
405 const base::DictionaryValue* application_dictionary = nullptr; 407 const base::DictionaryValue* application_dictionary = nullptr;
406 if (!applications_list->GetDictionary(i, &application_dictionary)) 408 if (!applications_list->GetDictionary(i, &application_dictionary))
407 continue; 409 continue;
408 410
409 Manifest::RelatedApplication application; 411 Manifest::RelatedApplication application;
410 application.platform = 412 application.platform =
411 ParseRelatedApplicationPlatform(*application_dictionary); 413 ParseRelatedApplicationPlatform(*application_dictionary);
412 // "If platform is undefined, move onto the next item if any are left." 414 // "If platform is undefined, move onto the next item if any are left."
413 if (application.platform.is_null()) { 415 if (application.platform.is_null()) {
414 errors_.push_back( 416 AddErrorInfo(
415 GetErrorPrefix() + 417 GetErrorPrefix() +
416 "'platform' is a required field, related application ignored."); 418 "'platform' is a required field, related application ignored.");
417 continue; 419 continue;
418 } 420 }
419 421
420 application.id = ParseRelatedApplicationId(*application_dictionary); 422 application.id = ParseRelatedApplicationId(*application_dictionary);
421 application.url = ParseRelatedApplicationURL(*application_dictionary); 423 application.url = ParseRelatedApplicationURL(*application_dictionary);
422 // "If both id and url are undefined, move onto the next item if any are 424 // "If both id and url are undefined, move onto the next item if any are
423 // left." 425 // left."
424 if (application.url.is_empty() && application.id.is_null()) { 426 if (application.url.is_empty() && application.id.is_null()) {
425 errors_.push_back( 427 AddErrorInfo(
426 GetErrorPrefix() + 428 GetErrorPrefix() +
427 "one of 'url' or 'id' is required, related application ignored."); 429 "one of 'url' or 'id' is required, related application ignored.");
428 continue; 430 continue;
429 } 431 }
430 432
431 applications.push_back(application); 433 applications.push_back(application);
432 } 434 }
433 435
434 return applications; 436 return applications;
435 } 437 }
(...skipping 11 matching lines...) Expand all
447 int64_t ManifestParser::ParseBackgroundColor( 449 int64_t ManifestParser::ParseBackgroundColor(
448 const base::DictionaryValue& dictionary) { 450 const base::DictionaryValue& dictionary) {
449 return ParseColor(dictionary, "background_color"); 451 return ParseColor(dictionary, "background_color");
450 } 452 }
451 453
452 base::NullableString16 ManifestParser::ParseGCMSenderID( 454 base::NullableString16 ManifestParser::ParseGCMSenderID(
453 const base::DictionaryValue& dictionary) { 455 const base::DictionaryValue& dictionary) {
454 return ParseString(dictionary, "gcm_sender_id", Trim); 456 return ParseString(dictionary, "gcm_sender_id", Trim);
455 } 457 }
456 458
459 void ManifestParser::AddErrorInfo(const std::string& error_msg,
460 int error_line,
461 int error_column) {
462 errors_.push_back(
463 make_scoped_ptr(new ErrorInfo(error_msg, error_line, error_column)));
464 }
457 } // namespace content 465 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/manifest/manifest_parser.h ('k') | content/renderer/manifest/manifest_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698