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

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

Issue 936413003: Allow extensions of the ManifestParser outside of the content/ layer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WIP - changing chrome layer relationship Created 5 years, 10 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 "base/json/json_reader.h" 7 #include "base/json/json_reader.h"
8 #include "base/strings/nullable_string16.h" 8 #include "base/strings/nullable_string16.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h" 10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "content/public/common/content_client.h"
14 #include "content/public/common/manifest.h" 15 #include "content/public/common/manifest.h"
16 #include "content/public/renderer/content_renderer_client.h"
15 #include "content/renderer/manifest/manifest_uma_util.h" 17 #include "content/renderer/manifest/manifest_uma_util.h"
16 #include "ui/gfx/geometry/size.h" 18 #include "ui/gfx/geometry/size.h"
17 19
18 namespace content { 20 namespace content {
19 21
20 namespace { 22 namespace {
21 23
22 // Helper function that returns whether the given |str| is a valid width or 24 // Helper function that returns whether the given |str| is a valid width or
23 // height value for an icon sizes per: 25 // height value for an icon sizes per:
24 // https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes 26 // https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 } 80 }
79 81
80 const std::string& GetErrorPrefix() { 82 const std::string& GetErrorPrefix() {
81 CR_DEFINE_STATIC_LOCAL(std::string, error_prefix, 83 CR_DEFINE_STATIC_LOCAL(std::string, error_prefix,
82 ("Manifest parsing error: ")); 84 ("Manifest parsing error: "));
83 return error_prefix; 85 return error_prefix;
84 } 86 }
85 87
86 } // anonymous namespace 88 } // anonymous namespace
87 89
88
89 ManifestParser::ManifestParser(const base::StringPiece& data, 90 ManifestParser::ManifestParser(const base::StringPiece& data,
90 const GURL& manifest_url, 91 const GURL& manifest_url,
91 const GURL& document_url) 92 const GURL& document_url)
92 : data_(data), 93 : data_(data),
93 manifest_url_(manifest_url), 94 manifest_url_(manifest_url),
94 document_url_(document_url), 95 document_url_(document_url),
95 failed_(false) { 96 failed_(false) {
97 DCHECK(manifest_url_.is_valid());
98 DCHECK(document_url_.is_valid());
96 } 99 }
97 100
98 ManifestParser::~ManifestParser() { 101 ManifestParser::~ManifestParser() {
99 } 102 }
100 103
101 void ManifestParser::Parse() { 104 void ManifestParser::Parse() {
102 std::string parse_error; 105 std::string parse_error;
103 scoped_ptr<base::Value> value( 106 scoped_ptr<base::Value> value(
104 base::JSONReader::ReadAndReturnError(data_, base::JSON_PARSE_RFC, 107 base::JSONReader::ReadAndReturnError(data_, base::JSON_PARSE_RFC,
105 nullptr, &parse_error)); 108 nullptr, &parse_error));
106 109
107 if (!value) { 110 if (!value) {
108 errors_.push_back(GetErrorPrefix() + parse_error); 111 errors_.push_back(GetErrorPrefix() + parse_error);
109 ManifestUmaUtil::ParseFailed(); 112 ManifestUmaUtil::ParseFailed();
110 failed_ = true; 113 failed_ = true;
111 return; 114 return;
112 } 115 }
113 116
114 base::DictionaryValue* dictionary = nullptr; 117 base::DictionaryValue* dictionary = nullptr;
115 if (!value->GetAsDictionary(&dictionary)) { 118 if (!value->GetAsDictionary(&dictionary)) {
116 errors_.push_back(GetErrorPrefix() + 119 errors_.push_back(GetErrorPrefix() +
117 "root element must be a valid JSON object."); 120 "root element must be a valid JSON object.");
118 ManifestUmaUtil::ParseFailed(); 121 ManifestUmaUtil::ParseFailed();
119 failed_ = true; 122 failed_ = true;
120 return; 123 return;
121 } 124 }
122 DCHECK(dictionary); 125 DCHECK(dictionary);
123 126
124 manifest_.name = ParseName(*dictionary); 127 for (base::DictionaryValue::Iterator iterator(*dictionary);
125 manifest_.short_name = ParseShortName(*dictionary); 128 !iterator.IsAtEnd(); iterator.Advance()) {
126 manifest_.start_url = ParseStartURL(*dictionary); 129 const std::string& key = iterator.key();
127 manifest_.display = ParseDisplay(*dictionary); 130 const base::Value& value = iterator.value();
128 manifest_.orientation = ParseOrientation(*dictionary); 131
129 manifest_.icons = ParseIcons(*dictionary); 132 bool handled = Parse(key, value);
130 manifest_.gcm_sender_id = ParseGCMSenderID(*dictionary); 133 if (!handled) {
131 manifest_.gcm_user_visible_only = ParseGCMUserVisibleOnly(*dictionary); 134 handled = GetContentClient()->renderer()->ParseManifestProperty(key,
135 value);
136 }
137
138 if (!handled)
139 errors_.push_back(GetErrorPrefix() + "unknown property '" + key + "'.");
140 }
132 141
133 ManifestUmaUtil::ParseSucceeded(manifest_); 142 ManifestUmaUtil::ParseSucceeded(manifest_);
134 } 143 }
135 144
145 bool ManifestParser::Parse(const std::string& key, const base::Value& value) {
146 if (key == "name")
147 manifest_.name = ParseName(key, value);
148 else if (key == "short_name")
149 manifest_.short_name = ParseShortName(key, value);
150 else if (key == "start_url")
151 manifest_.start_url = ParseStartURL(key, value);
152 else if (key == "display")
153 manifest_.display = ParseDisplay(key, value);
154 else if (key == "orientation")
155 manifest_.orientation = ParseOrientation(key, value);
156 else if (key == "icons")
157 manifest_.icons = ParseIcons(key, value);
158 else
159 return false;
160
161 return true;
162 }
163
136 const Manifest& ManifestParser::manifest() const { 164 const Manifest& ManifestParser::manifest() const {
137 return manifest_; 165 return manifest_;
138 } 166 }
139 167
140 const std::vector<std::string>& ManifestParser::errors() const { 168 const std::vector<std::string>& ManifestParser::errors() const {
141 return errors_; 169 return errors_;
142 } 170 }
143 171
144 bool ManifestParser::failed() const { 172 bool ManifestParser::failed() const {
145 return failed_; 173 return failed_;
146 } 174 }
147 175
148 bool ManifestParser::ParseBoolean(const base::DictionaryValue& dictionary, 176 bool ManifestParser::ParseBoolean(
149 const std::string& key, 177 const std::string& key, const base::Value& value, bool default_value) {
150 bool default_value) { 178 bool bool_value;
151 if (!dictionary.HasKey(key)) 179 if (!value.GetAsBoolean(&bool_value)) {
152 return default_value;
153
154 bool value;
155 if (!dictionary.GetBoolean(key, &value)) {
156 errors_.push_back(GetErrorPrefix() + 180 errors_.push_back(GetErrorPrefix() +
157 "property '" + key + "' ignored, type boolean expected."); 181 "property '" + key + "' ignored, type boolean expected.");
158 return default_value; 182 return default_value;
159 } 183 }
160 184
161 return value; 185 return bool_value;
162 } 186 }
163 187
164 base::NullableString16 ManifestParser::ParseString( 188 base::NullableString16 ManifestParser::ParseString(
165 const base::DictionaryValue& dictionary, 189 const std::string& key, const base::Value& value, TrimType trim) {
166 const std::string& key, 190 base::string16 string_value;
167 TrimType trim) { 191 if (!value.GetAsString(&string_value)) {
168 if (!dictionary.HasKey(key))
169 return base::NullableString16();
170
171 base::string16 value;
172 if (!dictionary.GetString(key, &value)) {
173 errors_.push_back(GetErrorPrefix() + 192 errors_.push_back(GetErrorPrefix() +
174 "property '" + key + "' ignored, type string expected."); 193 "property '" + key + "' ignored, type string expected.");
175 return base::NullableString16(); 194 return base::NullableString16();
176 } 195 }
177 196
178 if (trim == Trim) 197 if (trim == Trim)
179 base::TrimWhitespace(value, base::TRIM_ALL, &value); 198 base::TrimWhitespace(string_value, base::TRIM_ALL, &string_value);
180 return base::NullableString16(value, false); 199 return base::NullableString16(string_value, false);
181 } 200 }
182 201
183 GURL ManifestParser::ParseURL(const base::DictionaryValue& dictionary, 202 GURL ManifestParser::ParseURL(
184 const std::string& key, 203 const std::string& key, const base::Value& value, const GURL& base_url) {
185 const GURL& base_url) { 204 base::NullableString16 url_str = ParseString(key, value, NoTrim);
186 base::NullableString16 url_str = ParseString(dictionary, key, NoTrim);
187 if (url_str.is_null()) 205 if (url_str.is_null())
188 return GURL(); 206 return GURL();
189 207
190 return base_url.Resolve(url_str.string()); 208 return base_url.Resolve(url_str.string());
191 } 209 }
192 210
193 base::NullableString16 ManifestParser::ParseName( 211 base::NullableString16 ManifestParser::ParseName(
194 const base::DictionaryValue& dictionary) { 212 const std::string& key, const base::Value& value) {
195 return ParseString(dictionary, "name", Trim); 213 return ParseString(key, value, Trim);
196 } 214 }
197 215
198 base::NullableString16 ManifestParser::ParseShortName( 216 base::NullableString16 ManifestParser::ParseShortName(
199 const base::DictionaryValue& dictionary) { 217 const std::string& key, const base::Value& value) {
200 return ParseString(dictionary, "short_name", Trim); 218 return ParseString(key, value, Trim);
201 } 219 }
202 220
203 GURL ManifestParser::ParseStartURL(const base::DictionaryValue& dictionary) { 221 GURL ManifestParser::ParseStartURL(
204 GURL start_url = ParseURL(dictionary, "start_url", manifest_url_); 222 const std::string& key, const base::Value& value) {
223 GURL start_url = ParseURL(key, value, manifest_url_);
205 if (!start_url.is_valid()) 224 if (!start_url.is_valid())
206 return GURL(); 225 return GURL();
207 226
208 if (start_url.GetOrigin() != document_url_.GetOrigin()) { 227 if (start_url.GetOrigin() != document_url_.GetOrigin()) {
209 errors_.push_back(GetErrorPrefix() + "property 'start_url' ignored, should " 228 errors_.push_back(GetErrorPrefix() + "property 'start_url' ignored, should "
210 "be same origin as document."); 229 "be same origin as document.");
211 return GURL(); 230 return GURL();
212 } 231 }
213 232
214 return start_url; 233 return start_url;
215 } 234 }
216 235
217 Manifest::DisplayMode ManifestParser::ParseDisplay( 236 Manifest::DisplayMode ManifestParser::ParseDisplay(
218 const base::DictionaryValue& dictionary) { 237 const std::string& key, const base::Value& value) {
219 base::NullableString16 display = ParseString(dictionary, "display", Trim); 238 base::NullableString16 display = ParseString(key, value, Trim);
220 if (display.is_null()) 239 if (display.is_null())
221 return Manifest::DISPLAY_MODE_UNSPECIFIED; 240 return Manifest::DISPLAY_MODE_UNSPECIFIED;
222 241
223 if (LowerCaseEqualsASCII(display.string(), "fullscreen")) 242 if (LowerCaseEqualsASCII(display.string(), "fullscreen"))
224 return Manifest::DISPLAY_MODE_FULLSCREEN; 243 return Manifest::DISPLAY_MODE_FULLSCREEN;
225 else if (LowerCaseEqualsASCII(display.string(), "standalone")) 244 else if (LowerCaseEqualsASCII(display.string(), "standalone"))
226 return Manifest::DISPLAY_MODE_STANDALONE; 245 return Manifest::DISPLAY_MODE_STANDALONE;
227 else if (LowerCaseEqualsASCII(display.string(), "minimal-ui")) 246 else if (LowerCaseEqualsASCII(display.string(), "minimal-ui"))
228 return Manifest::DISPLAY_MODE_MINIMAL_UI; 247 return Manifest::DISPLAY_MODE_MINIMAL_UI;
229 else if (LowerCaseEqualsASCII(display.string(), "browser")) 248 else if (LowerCaseEqualsASCII(display.string(), "browser"))
230 return Manifest::DISPLAY_MODE_BROWSER; 249 return Manifest::DISPLAY_MODE_BROWSER;
231 else { 250 else {
232 errors_.push_back(GetErrorPrefix() + "unknown 'display' value ignored."); 251 errors_.push_back(GetErrorPrefix() + "unknown 'display' value ignored.");
233 return Manifest::DISPLAY_MODE_UNSPECIFIED; 252 return Manifest::DISPLAY_MODE_UNSPECIFIED;
234 } 253 }
235 } 254 }
236 255
237 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation( 256 blink::WebScreenOrientationLockType ManifestParser::ParseOrientation(
238 const base::DictionaryValue& dictionary) { 257 const std::string& key, const base::Value& value) {
239 base::NullableString16 orientation = 258 base::NullableString16 orientation = ParseString(key, value, Trim);
240 ParseString(dictionary, "orientation", Trim);
241
242 if (orientation.is_null()) 259 if (orientation.is_null())
243 return blink::WebScreenOrientationLockDefault; 260 return blink::WebScreenOrientationLockDefault;
244 261
245 if (LowerCaseEqualsASCII(orientation.string(), "any")) 262 if (LowerCaseEqualsASCII(orientation.string(), "any"))
246 return blink::WebScreenOrientationLockAny; 263 return blink::WebScreenOrientationLockAny;
247 else if (LowerCaseEqualsASCII(orientation.string(), "natural")) 264 else if (LowerCaseEqualsASCII(orientation.string(), "natural"))
248 return blink::WebScreenOrientationLockNatural; 265 return blink::WebScreenOrientationLockNatural;
249 else if (LowerCaseEqualsASCII(orientation.string(), "landscape")) 266 else if (LowerCaseEqualsASCII(orientation.string(), "landscape"))
250 return blink::WebScreenOrientationLockLandscape; 267 return blink::WebScreenOrientationLockLandscape;
251 else if (LowerCaseEqualsASCII(orientation.string(), "landscape-primary")) 268 else if (LowerCaseEqualsASCII(orientation.string(), "landscape-primary"))
252 return blink::WebScreenOrientationLockLandscapePrimary; 269 return blink::WebScreenOrientationLockLandscapePrimary;
253 else if (LowerCaseEqualsASCII(orientation.string(), "landscape-secondary")) 270 else if (LowerCaseEqualsASCII(orientation.string(), "landscape-secondary"))
254 return blink::WebScreenOrientationLockLandscapeSecondary; 271 return blink::WebScreenOrientationLockLandscapeSecondary;
255 else if (LowerCaseEqualsASCII(orientation.string(), "portrait")) 272 else if (LowerCaseEqualsASCII(orientation.string(), "portrait"))
256 return blink::WebScreenOrientationLockPortrait; 273 return blink::WebScreenOrientationLockPortrait;
257 else if (LowerCaseEqualsASCII(orientation.string(), "portrait-primary")) 274 else if (LowerCaseEqualsASCII(orientation.string(), "portrait-primary"))
258 return blink::WebScreenOrientationLockPortraitPrimary; 275 return blink::WebScreenOrientationLockPortraitPrimary;
259 else if (LowerCaseEqualsASCII(orientation.string(), "portrait-secondary")) 276 else if (LowerCaseEqualsASCII(orientation.string(), "portrait-secondary"))
260 return blink::WebScreenOrientationLockPortraitSecondary; 277 return blink::WebScreenOrientationLockPortraitSecondary;
261 else { 278 else {
262 errors_.push_back(GetErrorPrefix() + 279 errors_.push_back(GetErrorPrefix() +
263 "unknown 'orientation' value ignored."); 280 "unknown 'orientation' value ignored.");
264 return blink::WebScreenOrientationLockDefault; 281 return blink::WebScreenOrientationLockDefault;
265 } 282 }
266 } 283 }
267 284
268 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) { 285 GURL ManifestParser::ParseIconSrc(const base::DictionaryValue& icon) {
269 return ParseURL(icon, "src", manifest_url_); 286 const std::string key = "src";
287 const base::Value* value;
288
289 if (!icon.Get(key, &value))
290 return GURL();
291 return ParseURL(key, *value, manifest_url_);
270 } 292 }
271 293
272 base::NullableString16 ManifestParser::ParseIconType( 294 base::NullableString16 ManifestParser::ParseIconType(
273 const base::DictionaryValue& icon) { 295 const base::DictionaryValue& icon) {
274 return ParseString(icon, "type", Trim); 296 const std::string key = "type";
297 const base::Value* value;
298
299 if (!icon.Get(key, &value))
300 return base::NullableString16();
301 return ParseString(key, *value, Trim);
275 } 302 }
276 303
277 double ManifestParser::ParseIconDensity(const base::DictionaryValue& icon) { 304 double ManifestParser::ParseIconDensity(const base::DictionaryValue& icon) {
278 double density; 305 double density;
279 if (!icon.HasKey("density")) 306 if (!icon.HasKey("density"))
280 return Manifest::Icon::kDefaultDensity; 307 return Manifest::Icon::kDefaultDensity;
281 308
282 if (!icon.GetDouble("density", &density) || density <= 0) { 309 if (!icon.GetDouble("density", &density) || density <= 0) {
283 errors_.push_back(GetErrorPrefix() + 310 errors_.push_back(GetErrorPrefix() +
284 "icon 'density' ignored, must be float greater than 0."); 311 "icon 'density' ignored, must be float greater than 0.");
285 return Manifest::Icon::kDefaultDensity; 312 return Manifest::Icon::kDefaultDensity;
286 } 313 }
287 return density; 314 return density;
288 } 315 }
289 316
290 std::vector<gfx::Size> ManifestParser::ParseIconSizes( 317 std::vector<gfx::Size> ManifestParser::ParseIconSizes(
291 const base::DictionaryValue& icon) { 318 const base::DictionaryValue& icon) {
292 base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim); 319 const std::string key = "sizes";
320 const base::Value* value;
293 321
322 if (!icon.Get(key, &value))
323 return std::vector<gfx::Size>();
324
325 base::NullableString16 sizes_str = ParseString(key, *value, NoTrim);
294 if (sizes_str.is_null()) 326 if (sizes_str.is_null())
295 return std::vector<gfx::Size>(); 327 return std::vector<gfx::Size>();
296 328
297 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string()); 329 std::vector<gfx::Size> sizes = ParseIconSizesHTML(sizes_str.string());
298 if (sizes.empty()) { 330 if (sizes.empty()) {
299 errors_.push_back(GetErrorPrefix() + "found icon with no valid size."); 331 errors_.push_back(GetErrorPrefix() + "found icon with no valid size.");
300 } 332 }
301 return sizes; 333 return sizes;
302 } 334 }
303 335
304 std::vector<Manifest::Icon> ManifestParser::ParseIcons( 336 std::vector<Manifest::Icon> ManifestParser::ParseIcons(
305 const base::DictionaryValue& dictionary) { 337 const std::string& key, const base::Value& value) {
306 std::vector<Manifest::Icon> icons; 338 std::vector<Manifest::Icon> icons;
307 if (!dictionary.HasKey("icons"))
308 return icons;
309 339
310 const base::ListValue* icons_list = nullptr; 340 const base::ListValue* icons_list = nullptr;
311 if (!dictionary.GetList("icons", &icons_list)) { 341 if (!value.GetAsList(&icons_list)) {
312 errors_.push_back(GetErrorPrefix() + 342 errors_.push_back(GetErrorPrefix() +
313 "property 'icons' ignored, type array expected."); 343 "property 'icons' ignored, type array expected.");
314 return icons; 344 return icons;
315 } 345 }
316 346
317 for (size_t i = 0; i < icons_list->GetSize(); ++i) { 347 for (size_t i = 0; i < icons_list->GetSize(); ++i) {
318 const base::DictionaryValue* icon_dictionary = nullptr; 348 const base::DictionaryValue* icon_dictionary = nullptr;
319 if (!icons_list->GetDictionary(i, &icon_dictionary)) 349 if (!icons_list->GetDictionary(i, &icon_dictionary))
320 continue; 350 continue;
321 351
322 Manifest::Icon icon; 352 Manifest::Icon icon;
323 icon.src = ParseIconSrc(*icon_dictionary); 353 icon.src = ParseIconSrc(*icon_dictionary);
324 // An icon MUST have a valid src. If it does not, it MUST be ignored. 354 // An icon MUST have a valid src. If it does not, it MUST be ignored.
325 if (!icon.src.is_valid()) 355 if (!icon.src.is_valid())
326 continue; 356 continue;
327 icon.type = ParseIconType(*icon_dictionary); 357 icon.type = ParseIconType(*icon_dictionary);
328 icon.density = ParseIconDensity(*icon_dictionary); 358 icon.density = ParseIconDensity(*icon_dictionary);
329 icon.sizes = ParseIconSizes(*icon_dictionary); 359 icon.sizes = ParseIconSizes(*icon_dictionary);
330 360
331 icons.push_back(icon); 361 icons.push_back(icon);
332 } 362 }
333 363
334 return icons; 364 return icons;
335 } 365 }
336 366
337 base::NullableString16 ManifestParser::ParseGCMSenderID(
338 const base::DictionaryValue& dictionary) {
339 return ParseString(dictionary, "gcm_sender_id", Trim);
340 }
341
342 bool ManifestParser::ParseGCMUserVisibleOnly(
343 const base::DictionaryValue& dictionary) {
344 return ParseBoolean(dictionary, "gcm_user_visible_only", false);
345 }
346
347 } // namespace content 367 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698