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

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

Issue 1932623003: DevTools: Introduce Page.getManifest remote debugging protocol method. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: browser test updated Created 4 years, 7 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/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 !base::StringToInt(size_list[1], &height)) { 77 !base::StringToInt(size_list[1], &height)) {
78 continue; 78 continue;
79 } 79 }
80 80
81 sizes.push_back(gfx::Size(width, height)); 81 sizes.push_back(gfx::Size(width, height));
82 } 82 }
83 83
84 return sizes; 84 return sizes;
85 } 85 }
86 86
87 const std::string& GetErrorPrefix() {
88 CR_DEFINE_STATIC_LOCAL(std::string, error_prefix,
89 ("Manifest parsing error: "));
90 return error_prefix;
91 }
92
93 } // anonymous namespace 87 } // anonymous namespace
94 88
95 89
96 ManifestParser::ManifestParser(const base::StringPiece& data, 90 ManifestParser::ManifestParser(const base::StringPiece& data,
97 const GURL& manifest_url, 91 const GURL& manifest_url,
98 const GURL& document_url) 92 const GURL& document_url)
99 : data_(data), 93 : data_(data),
100 manifest_url_(manifest_url), 94 manifest_url_(manifest_url),
101 document_url_(document_url), 95 document_url_(document_url),
102 failed_(false) { 96 failed_(false) {
103 } 97 }
104 98
105 ManifestParser::~ManifestParser() { 99 ManifestParser::~ManifestParser() {
106 } 100 }
107 101
108 void ManifestParser::Parse() { 102 void ManifestParser::Parse() {
109 std::string error_msg; 103 std::string error_msg;
110 int error_line = 0; 104 int error_line = 0;
111 int error_column = 0; 105 int error_column = 0;
112 std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError( 106 std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
113 data_, base::JSON_PARSE_RFC, nullptr, &error_msg, &error_line, 107 data_, base::JSON_PARSE_RFC, nullptr, &error_msg, &error_line,
114 &error_column); 108 &error_column);
115 109
116 if (!value) { 110 if (!value) {
117 AddErrorInfo(GetErrorPrefix() + error_msg, error_line, error_column); 111 AddErrorInfo(error_msg, true, error_line, error_column);
118 ManifestUmaUtil::ParseFailed(); 112 ManifestUmaUtil::ParseFailed();
119 failed_ = true; 113 failed_ = true;
120 return; 114 return;
121 } 115 }
122 116
123 base::DictionaryValue* dictionary = nullptr; 117 base::DictionaryValue* dictionary = nullptr;
124 if (!value->GetAsDictionary(&dictionary)) { 118 if (!value->GetAsDictionary(&dictionary)) {
125 AddErrorInfo(GetErrorPrefix() + 119 AddErrorInfo("root element must be a valid JSON object.", true);
126 "root element must be a valid JSON object.");
127 ManifestUmaUtil::ParseFailed(); 120 ManifestUmaUtil::ParseFailed();
128 failed_ = true; 121 failed_ = true;
129 return; 122 return;
130 } 123 }
131 DCHECK(dictionary); 124 DCHECK(dictionary);
132 125
133 manifest_.name = ParseName(*dictionary); 126 manifest_.name = ParseName(*dictionary);
134 manifest_.short_name = ParseShortName(*dictionary); 127 manifest_.short_name = ParseShortName(*dictionary);
135 manifest_.start_url = ParseStartURL(*dictionary); 128 manifest_.start_url = ParseStartURL(*dictionary);
136 manifest_.display = ParseDisplay(*dictionary); 129 manifest_.display = ParseDisplay(*dictionary);
137 manifest_.orientation = ParseOrientation(*dictionary); 130 manifest_.orientation = ParseOrientation(*dictionary);
138 manifest_.icons = ParseIcons(*dictionary); 131 manifest_.icons = ParseIcons(*dictionary);
139 manifest_.related_applications = ParseRelatedApplications(*dictionary); 132 manifest_.related_applications = ParseRelatedApplications(*dictionary);
140 manifest_.prefer_related_applications = 133 manifest_.prefer_related_applications =
141 ParsePreferRelatedApplications(*dictionary); 134 ParsePreferRelatedApplications(*dictionary);
142 manifest_.theme_color = ParseThemeColor(*dictionary); 135 manifest_.theme_color = ParseThemeColor(*dictionary);
143 manifest_.background_color = ParseBackgroundColor(*dictionary); 136 manifest_.background_color = ParseBackgroundColor(*dictionary);
144 manifest_.gcm_sender_id = ParseGCMSenderID(*dictionary); 137 manifest_.gcm_sender_id = ParseGCMSenderID(*dictionary);
145 138
146 ManifestUmaUtil::ParseSucceeded(manifest_); 139 ManifestUmaUtil::ParseSucceeded(manifest_);
147 } 140 }
148 141
149 const Manifest& ManifestParser::manifest() const { 142 const Manifest& ManifestParser::manifest() const {
150 return manifest_; 143 return manifest_;
151 } 144 }
152 145
153 const std::vector<std::unique_ptr<ManifestParser::ErrorInfo>>& 146 void ManifestParser::TakeErrors(
154 ManifestParser::errors() const { 147 std::vector<ManifestDebugInfo::Error>* errors) {
155 return errors_; 148 errors->clear();
149 errors->swap(errors_);
156 } 150 }
157 151
158 bool ManifestParser::failed() const { 152 bool ManifestParser::failed() const {
159 return failed_; 153 return failed_;
160 } 154 }
161 155
162 bool ManifestParser::ParseBoolean(const base::DictionaryValue& dictionary, 156 bool ManifestParser::ParseBoolean(const base::DictionaryValue& dictionary,
163 const std::string& key, 157 const std::string& key,
164 bool default_value) { 158 bool default_value) {
165 if (!dictionary.HasKey(key)) 159 if (!dictionary.HasKey(key))
166 return default_value; 160 return default_value;
167 161
168 bool value; 162 bool value;
169 if (!dictionary.GetBoolean(key, &value)) { 163 if (!dictionary.GetBoolean(key, &value)) {
170 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, type " + 164 AddErrorInfo("property '" + key + "' ignored, type " +
171 "boolean expected."); 165 "boolean expected.");
172 return default_value; 166 return default_value;
173 } 167 }
174 168
175 return value; 169 return value;
176 } 170 }
177 171
178 base::NullableString16 ManifestParser::ParseString( 172 base::NullableString16 ManifestParser::ParseString(
179 const base::DictionaryValue& dictionary, 173 const base::DictionaryValue& dictionary,
180 const std::string& key, 174 const std::string& key,
181 TrimType trim) { 175 TrimType trim) {
182 if (!dictionary.HasKey(key)) 176 if (!dictionary.HasKey(key))
183 return base::NullableString16(); 177 return base::NullableString16();
184 178
185 base::string16 value; 179 base::string16 value;
186 if (!dictionary.GetString(key, &value)) { 180 if (!dictionary.GetString(key, &value)) {
187 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, type " + 181 AddErrorInfo("property '" + key + "' ignored, type " +
188 "string expected."); 182 "string expected.");
189 return base::NullableString16(); 183 return base::NullableString16();
190 } 184 }
191 185
192 if (trim == Trim) 186 if (trim == Trim)
193 base::TrimWhitespace(value, base::TRIM_ALL, &value); 187 base::TrimWhitespace(value, base::TRIM_ALL, &value);
194 return base::NullableString16(value, false); 188 return base::NullableString16(value, false);
195 } 189 }
196 190
197 int64_t ManifestParser::ParseColor( 191 int64_t ManifestParser::ParseColor(
198 const base::DictionaryValue& dictionary, 192 const base::DictionaryValue& dictionary,
199 const std::string& key) { 193 const std::string& key) {
200 base::NullableString16 parsed_color = ParseString(dictionary, key, Trim); 194 base::NullableString16 parsed_color = ParseString(dictionary, key, Trim);
201 if (parsed_color.is_null()) 195 if (parsed_color.is_null())
202 return Manifest::kInvalidOrMissingColor; 196 return Manifest::kInvalidOrMissingColor;
203 197
204 blink::WebColor color; 198 blink::WebColor color;
205 if (!blink::WebCSSParser::parseColor(&color, parsed_color.string())) { 199 if (!blink::WebCSSParser::parseColor(&color, parsed_color.string())) {
206 AddErrorInfo(GetErrorPrefix() + "property '" + key + "' ignored, '" + 200 AddErrorInfo("property '" + key + "' ignored, '" +
207 base::UTF16ToUTF8(parsed_color.string()) + "' is not a " + 201 base::UTF16ToUTF8(parsed_color.string()) + "' is not a " +
208 "valid color."); 202 "valid color.");
209 return Manifest::kInvalidOrMissingColor; 203 return Manifest::kInvalidOrMissingColor;
210 } 204 }
211 205
212 // We do this here because Java does not have an unsigned int32_t type so 206 // We do this here because Java does not have an unsigned int32_t type so
213 // colors with high alpha values will be negative. Instead of doing the 207 // colors with high alpha values will be negative. Instead of doing the
214 // conversion after we pass over to Java, we do it here as it is easier and 208 // conversion after we pass over to Java, we do it here as it is easier and
215 // clearer. 209 // clearer.
216 int32_t signed_color = reinterpret_cast<int32_t&>(color); 210 int32_t signed_color = reinterpret_cast<int32_t&>(color);
(...skipping 19 matching lines...) Expand all
236 const base::DictionaryValue& dictionary) { 230 const base::DictionaryValue& dictionary) {
237 return ParseString(dictionary, "short_name", Trim); 231 return ParseString(dictionary, "short_name", Trim);
238 } 232 }
239 233
240 GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) { 234 GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) {
241 GURL start_url = ParseURL(dictionary, "start_url", manifest_url_); 235 GURL start_url = ParseURL(dictionary, "start_url", manifest_url_);
242 if (!start_url.is_valid()) 236 if (!start_url.is_valid())
243 return GURL(); 237 return GURL();
244 238
245 if (start_url.GetOrigin() != document_url_.GetOrigin()) { 239 if (start_url.GetOrigin() != document_url_.GetOrigin()) {
246 AddErrorInfo(GetErrorPrefix() + "property 'start_url' ignored, should be " + 240 AddErrorInfo("property 'start_url' ignored, should be "
247 "same origin as document."); 241 "same origin as document.");
248 return GURL(); 242 return GURL();
249 } 243 }
250 244
251 return start_url; 245 return start_url;
252 } 246 }
253 247
254 blink::WebDisplayMode ManifestParser::ParseDisplay( 248 blink::WebDisplayMode ManifestParser::ParseDisplay(
255 const base::DictionaryValue& dictionary) { 249 const base::DictionaryValue& dictionary) {
256 base::NullableString16 display = ParseString(dictionary, "display", Trim); 250 base::NullableString16 display = ParseString(dictionary, "display", Trim);
257 if (display.is_null()) 251 if (display.is_null())
258 return blink::WebDisplayModeUndefined; 252 return blink::WebDisplayModeUndefined;
259 253
260 if (base::LowerCaseEqualsASCII(display.string(), "fullscreen")) 254 if (base::LowerCaseEqualsASCII(display.string(), "fullscreen"))
261 return blink::WebDisplayModeFullscreen; 255 return blink::WebDisplayModeFullscreen;
262 else if (base::LowerCaseEqualsASCII(display.string(), "standalone")) 256 else if (base::LowerCaseEqualsASCII(display.string(), "standalone"))
263 return blink::WebDisplayModeStandalone; 257 return blink::WebDisplayModeStandalone;
264 else if (base::LowerCaseEqualsASCII(display.string(), "minimal-ui")) 258 else if (base::LowerCaseEqualsASCII(display.string(), "minimal-ui"))
265 return blink::WebDisplayModeMinimalUi; 259 return blink::WebDisplayModeMinimalUi;
266 else if (base::LowerCaseEqualsASCII(display.string(), "browser")) 260 else if (base::LowerCaseEqualsASCII(display.string(), "browser"))
267 return blink::WebDisplayModeBrowser; 261 return blink::WebDisplayModeBrowser;
268 else { 262 else {
269 AddErrorInfo(GetErrorPrefix() + "unknown 'display' value ignored."); 263 AddErrorInfo("unknown 'display' value ignored.");
270 return blink::WebDisplayModeUndefined; 264 return blink::WebDisplayModeUndefined;
271 } 265 }
272 } 266 }
273 267
274 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation( 268 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation(
275 const base::DictionaryValue& dictionary) { 269 const base::DictionaryValue& dictionary) {
276 base::NullableString16 orientation = 270 base::NullableString16 orientation =
277 ParseString(dictionary, "orientation", Trim); 271 ParseString(dictionary, "orientation", Trim);
278 272
279 if (orientation.is_null()) 273 if (orientation.is_null())
(...skipping 13 matching lines...) Expand all
293 return blink::WebScreenOrientationLockLandscapeSecondary; 287 return blink::WebScreenOrientationLockLandscapeSecondary;
294 else if (base::LowerCaseEqualsASCII(orientation.string(), "portrait")) 288 else if (base::LowerCaseEqualsASCII(orientation.string(), "portrait"))
295 return blink::WebScreenOrientationLockPortrait; 289 return blink::WebScreenOrientationLockPortrait;
296 else if (base::LowerCaseEqualsASCII(orientation.string(), 290 else if (base::LowerCaseEqualsASCII(orientation.string(),
297 "portrait-primary")) 291 "portrait-primary"))
298 return blink::WebScreenOrientationLockPortraitPrimary; 292 return blink::WebScreenOrientationLockPortraitPrimary;
299 else if (base::LowerCaseEqualsASCII(orientation.string(), 293 else if (base::LowerCaseEqualsASCII(orientation.string(),
300 "portrait-secondary")) 294 "portrait-secondary"))
301 return blink::WebScreenOrientationLockPortraitSecondary; 295 return blink::WebScreenOrientationLockPortraitSecondary;
302 else { 296 else {
303 AddErrorInfo(GetErrorPrefix() + "unknown 'orientation' value ignored."); 297 AddErrorInfo("unknown 'orientation' value ignored.");
304 return blink::WebScreenOrientationLockDefault; 298 return blink::WebScreenOrientationLockDefault;
305 } 299 }
306 } 300 }
307 301
308 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) { 302 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) {
309 return ParseURL(icon, "src", manifest_url_); 303 return ParseURL(icon, "src", manifest_url_);
310 } 304 }
311 305
312 base::NullableString16 ManifestParser::ParseIconType( 306 base::NullableString16 ManifestParser::ParseIconType(
313 const base::DictionaryValue& icon) { 307 const base::DictionaryValue& icon) {
314 return ParseString(icon, "type", Trim); 308 return ParseString(icon, "type", Trim);
315 } 309 }
316 310
317 std::vector<gfx::Size> ManifestParser::ParseIconSizes( 311 std::vector<gfx::Size> ManifestParser::ParseIconSizes(
318 const base::DictionaryValue& icon) { 312 const base::DictionaryValue& icon) {
319 base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim); 313 base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim);
320 314
321 if (sizes_str.is_null()) 315 if (sizes_str.is_null())
322 return std::vector<gfx::Size>(); 316 return std::vector<gfx::Size>();
323 317
324 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string()); 318 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string());
325 if (sizes.empty()) { 319 if (sizes.empty()) {
326 AddErrorInfo(GetErrorPrefix() + "found icon with no valid size."); 320 AddErrorInfo("found icon with no valid size.");
327 } 321 }
328 return sizes; 322 return sizes;
329 } 323 }
330 324
331 std::vector<Manifest::Icon> ManifestParser::ParseIcons( 325 std::vector<Manifest::Icon> ManifestParser::ParseIcons(
332 const base::DictionaryValue& dictionary) { 326 const base::DictionaryValue& dictionary) {
333 std::vector<Manifest::Icon> icons; 327 std::vector<Manifest::Icon> icons;
334 if (!dictionary.HasKey("icons")) 328 if (!dictionary.HasKey("icons"))
335 return icons; 329 return icons;
336 330
337 const base::ListValue* icons_list = nullptr; 331 const base::ListValue* icons_list = nullptr;
338 if (!dictionary.GetList("icons", &icons_list)) { 332 if (!dictionary.GetList("icons", &icons_list)) {
339 AddErrorInfo(GetErrorPrefix() + 333 AddErrorInfo("property 'icons' ignored, type array expected.");
340 "property 'icons' ignored, type array expected.");
341 return icons; 334 return icons;
342 } 335 }
343 336
344 for (size_t i = 0; i < icons_list->GetSize(); ++i) { 337 for (size_t i = 0; i < icons_list->GetSize(); ++i) {
345 const base::DictionaryValue* icon_dictionary = nullptr; 338 const base::DictionaryValue* icon_dictionary = nullptr;
346 if (!icons_list->GetDictionary(i, &icon_dictionary)) 339 if (!icons_list->GetDictionary(i, &icon_dictionary))
347 continue; 340 continue;
348 341
349 Manifest::Icon icon; 342 Manifest::Icon icon;
350 icon.src = ParseIconSrc(*icon_dictionary); 343 icon.src = ParseIconSrc(*icon_dictionary);
(...skipping 26 matching lines...) Expand all
377 370
378 std::vector<Manifest::RelatedApplication> 371 std::vector<Manifest::RelatedApplication>
379 ManifestParser::ParseRelatedApplications( 372 ManifestParser::ParseRelatedApplications(
380 const base::DictionaryValue& dictionary) { 373 const base::DictionaryValue& dictionary) {
381 std::vector<Manifest::RelatedApplication> applications; 374 std::vector<Manifest::RelatedApplication> applications;
382 if (!dictionary.HasKey("related_applications")) 375 if (!dictionary.HasKey("related_applications"))
383 return applications; 376 return applications;
384 377
385 const base::ListValue* applications_list = nullptr; 378 const base::ListValue* applications_list = nullptr;
386 if (!dictionary.GetList("related_applications", &applications_list)) { 379 if (!dictionary.GetList("related_applications", &applications_list)) {
387 AddErrorInfo( 380 AddErrorInfo("property 'related_applications' ignored,"
388 GetErrorPrefix() + 381 " type array expected.");
389 "property 'related_applications' ignored, type array expected.");
390 return applications; 382 return applications;
391 } 383 }
392 384
393 for (size_t i = 0; i < applications_list->GetSize(); ++i) { 385 for (size_t i = 0; i < applications_list->GetSize(); ++i) {
394 const base::DictionaryValue* application_dictionary = nullptr; 386 const base::DictionaryValue* application_dictionary = nullptr;
395 if (!applications_list->GetDictionary(i, &application_dictionary)) 387 if (!applications_list->GetDictionary(i, &application_dictionary))
396 continue; 388 continue;
397 389
398 Manifest::RelatedApplication application; 390 Manifest::RelatedApplication application;
399 application.platform = 391 application.platform =
400 ParseRelatedApplicationPlatform(*application_dictionary); 392 ParseRelatedApplicationPlatform(*application_dictionary);
401 // "If platform is undefined, move onto the next item if any are left." 393 // "If platform is undefined, move onto the next item if any are left."
402 if (application.platform.is_null()) { 394 if (application.platform.is_null()) {
403 AddErrorInfo( 395 AddErrorInfo("'platform' is a required field, related application"
404 GetErrorPrefix() + 396 " ignored.");
405 "'platform' is a required field, related application ignored.");
406 continue; 397 continue;
407 } 398 }
408 399
409 application.id = ParseRelatedApplicationId(*application_dictionary); 400 application.id = ParseRelatedApplicationId(*application_dictionary);
410 application.url = ParseRelatedApplicationURL(*application_dictionary); 401 application.url = ParseRelatedApplicationURL(*application_dictionary);
411 // "If both id and url are undefined, move onto the next item if any are 402 // "If both id and url are undefined, move onto the next item if any are
412 // left." 403 // left."
413 if (application.url.is_empty() && application.id.is_null()) { 404 if (application.url.is_empty() && application.id.is_null()) {
414 AddErrorInfo( 405 AddErrorInfo("one of 'url' or 'id' is required, related application"
415 GetErrorPrefix() + 406 " ignored.");
416 "one of 'url' or 'id' is required, related application ignored.");
417 continue; 407 continue;
418 } 408 }
419 409
420 applications.push_back(application); 410 applications.push_back(application);
421 } 411 }
422 412
423 return applications; 413 return applications;
424 } 414 }
425 415
426 bool ManifestParser::ParsePreferRelatedApplications( 416 bool ManifestParser::ParsePreferRelatedApplications(
(...skipping 10 matching lines...) Expand all
437 const base::DictionaryValue& dictionary) { 427 const base::DictionaryValue& dictionary) {
438 return ParseColor(dictionary, "background_color"); 428 return ParseColor(dictionary, "background_color");
439 } 429 }
440 430
441 base::NullableString16 ManifestParser::ParseGCMSenderID( 431 base::NullableString16 ManifestParser::ParseGCMSenderID(
442 const base::DictionaryValue& dictionary) { 432 const base::DictionaryValue& dictionary) {
443 return ParseString(dictionary, "gcm_sender_id", Trim); 433 return ParseString(dictionary, "gcm_sender_id", Trim);
444 } 434 }
445 435
446 void ManifestParser::AddErrorInfo(const std::string& error_msg, 436 void ManifestParser::AddErrorInfo(const std::string& error_msg,
437 bool critical,
447 int error_line, 438 int error_line,
448 int error_column) { 439 int error_column) {
449 errors_.push_back( 440 errors_.push_back({error_msg, critical, error_line, error_column});
450 base::WrapUnique(new ErrorInfo(error_msg, error_line, error_column)));
451 } 441 }
442
452 } // namespace content 443 } // 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