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

Side by Side Diff: ppapi/native_client/src/trusted/plugin/json_manifest.cc

Issue 16296005: Split pnacl and nacl mime types (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After (hopefully) last rebase. Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "native_client/src/trusted/plugin/json_manifest.h" 9 #include "native_client/src/trusted/plugin/json_manifest.h"
10 10
(...skipping 27 matching lines...) Expand all
38 38
39 // Url Resolution keys 39 // Url Resolution keys
40 const char* const kPnaclTranslateKey = "pnacl-translate"; 40 const char* const kPnaclTranslateKey = "pnacl-translate";
41 const char* const kUrlKey = "url"; 41 const char* const kUrlKey = "url";
42 42
43 // Pnacl keys 43 // Pnacl keys
44 const char* const kCacheIdentityKey = "sha256"; 44 const char* const kCacheIdentityKey = "sha256";
45 const char* const kOptLevelKey = "-O"; 45 const char* const kOptLevelKey = "-O";
46 const char* const kPnaclExperimentalFlags = "experimental_flags"; 46 const char* const kPnaclExperimentalFlags = "experimental_flags";
47 47
48 // Sample manifest file: 48 // Sample NaCL manifest file:
49 // { 49 // {
50 // "program": { 50 // "program": {
51 // "x86-32": {"url": "myprogram_x86-32.nexe"}, 51 // "x86-32": {"url": "myprogram_x86-32.nexe"},
52 // "x86-64": {"url": "myprogram_x86-64.nexe"}, 52 // "x86-64": {"url": "myprogram_x86-64.nexe"},
53 // "arm": {"url": "myprogram_arm.nexe"}, 53 // "arm": {"url": "myprogram_arm.nexe"}
54 // "portable": {
55 // "pnacl-translate": {
56 // "url": "myprogram.pexe",
57 // "sha256": "...",
58 // "-O": 0
59 // }
60 // }
61 // }, 54 // },
62 // "interpreter": { 55 // "interpreter": {
63 // "x86-32": {"url": "interpreter_x86-32.nexe"}, 56 // "x86-32": {"url": "interpreter_x86-32.nexe"},
64 // "x86-64": {"url": "interpreter_x86-64.nexe"}, 57 // "x86-64": {"url": "interpreter_x86-64.nexe"},
65 // "arm": {"url": "interpreter_arm.nexe"} 58 // "arm": {"url": "interpreter_arm.nexe"}
66 // }, 59 // },
67 // "files": { 60 // "files": {
68 // "foo.txt": { 61 // "foo.txt": {
69 // "portable": {"url": "foo.txt"} 62 // "portable": {"url": "foo.txt"}
70 // }, 63 // },
71 // "bar.txt": { 64 // "bar.txt": {
72 // "x86-32": {"url": "x86-32/bar.txt"}, 65 // "x86-32": {"url": "x86-32/bar.txt"},
73 // "portable": {"url": "bar.txt"} 66 // "portable": {"url": "bar.txt"}
74 // }, 67 // },
75 // "libfoo.so": { 68 // "libfoo.so": {
76 // "x86-64-ivybridge-foo": { "url": "..."}, 69 // "x86-64" : { "url": "..." }
77 // "x86-64-ivybridge" : { "pnacl-translate": { "url": "..."}},
78 // "x86-64" : { "url": "..." },
79 // "portable": {"pnacl-translate": {"url": "..."}}
80 // } 70 // }
81 // } 71 // }
82 // } 72 // }
73
74 // Sample PNaCl manifest file:
75 // {
76 // "program": {
77 // "portable": {
78 // "pnacl-translate": {
79 // "url": "myprogram.pexe",
80 // "sha256": "...",
81 // "-O": 0
82 // }
83 // }
84 // },
85 // "files": {
86 // "foo.txt": {
87 // "portable": {"url": "foo.txt"}
88 // },
89 // "bar.txt": {
90 // "portable": {"url": "bar.txt"}
91 // }
92 // }
93 // }
83 94
84 // Looks up |property_name| in the vector |valid_names| with length 95 // Looks up |property_name| in the vector |valid_names| with length
85 // |valid_name_count|. Returns true if |property_name| is found. 96 // |valid_name_count|. Returns true if |property_name| is found.
86 bool FindMatchingProperty(const nacl::string& property_name, 97 bool FindMatchingProperty(const nacl::string& property_name,
87 const char** valid_names, 98 const char** valid_names,
88 size_t valid_name_count) { 99 size_t valid_name_count) {
89 for (size_t i = 0; i < valid_name_count; ++i) { 100 for (size_t i = 0; i < valid_name_count; ++i) {
90 if (property_name == valid_names[i]) { 101 if (property_name == valid_names[i]) {
91 return true; 102 return true;
92 } 103 }
(...skipping 22 matching lines...) Expand all
115 *error_string = error_stream.str(); 126 *error_string = error_stream.str();
116 return false; 127 return false;
117 } 128 }
118 // Check for unknown dictionary members. 129 // Check for unknown dictionary members.
119 Json::Value::Members members = dictionary.getMemberNames(); 130 Json::Value::Members members = dictionary.getMemberNames();
120 for (size_t i = 0; i < members.size(); ++i) { 131 for (size_t i = 0; i < members.size(); ++i) {
121 nacl::string property_name = members[i]; 132 nacl::string property_name = members[i];
122 if (!FindMatchingProperty(property_name, 133 if (!FindMatchingProperty(property_name,
123 valid_keys, 134 valid_keys,
124 valid_key_count)) { 135 valid_key_count)) {
125 // TODO(jvoung): Should this set error_string and return false? 136 // For forward compatibility, we do not prohibit other keys being in
137 // the dictionary.
126 PLUGIN_PRINTF(("WARNING: '%s' property '%s' has unknown key '%s'.\n", 138 PLUGIN_PRINTF(("WARNING: '%s' property '%s' has unknown key '%s'.\n",
127 parent_key.c_str(), 139 parent_key.c_str(),
128 container_key.c_str(), property_name.c_str())); 140 container_key.c_str(), property_name.c_str()));
129 } 141 }
130 } 142 }
131 // Check for required members. 143 // Check for required members.
132 for (size_t i = 0; i < required_key_count; ++i) { 144 for (size_t i = 0; i < required_key_count; ++i) {
133 if (!dictionary.isMember(required_keys[i])) { 145 if (!dictionary.isMember(required_keys[i])) {
134 nacl::stringstream error_stream; 146 nacl::stringstream error_stream;
135 error_stream << parent_key << " property '" << container_key 147 error_stream << parent_key << " property '" << container_key
136 << "' does not have required key: '" 148 << "' does not have required key: '"
137 << required_keys[i] << "'."; 149 << required_keys[i] << "'.";
138 *error_string = error_stream.str(); 150 *error_string = error_stream.str();
139 return false; 151 return false;
140 } 152 }
141 } 153 }
142 return true; 154 return true;
143 } 155 }
144 156
145 // Validate a "url" dictionary assuming it was resolved from container_key. 157 // Validate a "url" dictionary assuming it was resolved from container_key.
146 // E.g., "container_key" : { "url": "foo.txt" } 158 // E.g., "container_key" : { "url": "foo.txt" }
147 bool IsValidUrlSpec(const Json::Value& url_spec, 159 bool IsValidUrlSpec(const Json::Value& url_spec,
148 const nacl::string& container_key, 160 const nacl::string& container_key,
149 const nacl::string& parent_key, 161 const nacl::string& parent_key,
162 const nacl::string& sandbox_isa,
150 nacl::string* error_string) { 163 nacl::string* error_string) {
151 static const char* kManifestUrlSpecRequired[] = { 164 static const char* kManifestUrlSpecRequired[] = {
152 kUrlKey 165 kUrlKey
153 }; 166 };
154 static const char* kManifestUrlSpecPlusOptional[] = { 167 const char** urlSpecPlusOptional;
155 kUrlKey, 168 size_t urlSpecPlusOptionalLength;
156 kCacheIdentityKey 169 if (sandbox_isa == kPortableKey) {
157 }; 170 static const char* kPnaclUrlSpecPlusOptional[] = {
171 kUrlKey,
172 kCacheIdentityKey,
173 kOptLevelKey,
174 };
175 urlSpecPlusOptional = kPnaclUrlSpecPlusOptional;
176 urlSpecPlusOptionalLength = NACL_ARRAY_SIZE(kPnaclUrlSpecPlusOptional);
177 } else {
178 urlSpecPlusOptional = kManifestUrlSpecRequired;
179 urlSpecPlusOptionalLength = NACL_ARRAY_SIZE(kManifestUrlSpecRequired);
180 }
158 if (!IsValidDictionary(url_spec, container_key, parent_key, 181 if (!IsValidDictionary(url_spec, container_key, parent_key,
159 kManifestUrlSpecPlusOptional, 182 urlSpecPlusOptional,
160 NACL_ARRAY_SIZE(kManifestUrlSpecPlusOptional), 183 urlSpecPlusOptionalLength,
161 kManifestUrlSpecRequired, 184 kManifestUrlSpecRequired,
162 NACL_ARRAY_SIZE(kManifestUrlSpecRequired), 185 NACL_ARRAY_SIZE(kManifestUrlSpecRequired),
163 error_string)) { 186 error_string)) {
164 return false; 187 return false;
165 } 188 }
189 // URL specifications must not contain "pnacl-translate" keys.
190 // This prohibits NaCl clients from invoking PNaCl.
191 Json::Value translate = url_spec[kPnaclTranslateKey];
192 if (!translate.empty()) {
193 nacl::stringstream error_stream;
194 error_stream << parent_key << " property '" << container_key <<
195 "' has '" << kPnaclTranslateKey << "' inside URL spec.";
196 *error_string = error_stream.str();
197 return false;
198 }
199 // Verify the correct types of the fields if they exist.
166 Json::Value url = url_spec[kUrlKey]; 200 Json::Value url = url_spec[kUrlKey];
167 if (!url.isString()) { 201 if (!url.isString()) {
168 nacl::stringstream error_stream; 202 nacl::stringstream error_stream;
169 error_stream << parent_key << " property '" << container_key << 203 error_stream << parent_key << " property '" << container_key <<
170 "' has non-string value '" << url.toStyledString() << 204 "' has non-string value '" << url.toStyledString() <<
171 "' for key '" << kUrlKey << "'."; 205 "' for key '" << kUrlKey << "'.";
172 *error_string = error_stream.str(); 206 *error_string = error_stream.str();
173 return false; 207 return false;
174 } 208 }
209 Json::Value cache_identity = url_spec[kCacheIdentityKey];
210 if (!cache_identity.empty() && !cache_identity.isString()) {
211 nacl::stringstream error_stream;
212 error_stream << parent_key << " property '" << container_key <<
213 "' has non-string value '" << cache_identity.toStyledString() <<
214 "' for key '" << kCacheIdentityKey << "'.";
215 *error_string = error_stream.str();
216 return false;
217 }
218 Json::Value opt_level = url_spec[kOptLevelKey];
219 if (!opt_level.empty() && !opt_level.isNumeric()) {
220 nacl::stringstream error_stream;
221 error_stream << parent_key << " property '" << container_key <<
222 "' has non-numeric value '" << opt_level.toStyledString() <<
223 "' for key '" << kOptLevelKey << "'.";
224 *error_string = error_stream.str();
225 return false;
226 }
175 return true; 227 return true;
176 } 228 }
177 229
178 // Validate a "pnacl-translate" dictionary, assuming it was resolved from 230 // Validate a "pnacl-translate" dictionary, assuming it was resolved from
179 // container_key. E.g., "container_key" : { "pnacl_translate" : URLSpec } 231 // container_key. E.g., "container_key" : { "pnacl_translate" : URLSpec }
180 bool IsValidPnaclTranslateSpec(const Json::Value& pnacl_spec, 232 bool IsValidPnaclTranslateSpec(const Json::Value& pnacl_spec,
181 const nacl::string& container_key, 233 const nacl::string& container_key,
182 const nacl::string& parent_key, 234 const nacl::string& parent_key,
235 const nacl::string& sandbox_isa,
183 nacl::string* error_string) { 236 nacl::string* error_string) {
184 static const char* kManifestPnaclSpecProperties[] = { 237 static const char* kManifestPnaclSpecProperties[] = {
185 kPnaclTranslateKey 238 kPnaclTranslateKey
186 }; 239 };
187 if (!IsValidDictionary(pnacl_spec, container_key, parent_key, 240 if (!IsValidDictionary(pnacl_spec, container_key, parent_key,
188 kManifestPnaclSpecProperties, 241 kManifestPnaclSpecProperties,
189 NACL_ARRAY_SIZE(kManifestPnaclSpecProperties), 242 NACL_ARRAY_SIZE(kManifestPnaclSpecProperties),
190 kManifestPnaclSpecProperties, 243 kManifestPnaclSpecProperties,
191 NACL_ARRAY_SIZE(kManifestPnaclSpecProperties), 244 NACL_ARRAY_SIZE(kManifestPnaclSpecProperties),
192 error_string)) { 245 error_string)) {
193 return false; 246 return false;
194 } 247 }
195 Json::Value url_spec = pnacl_spec[kPnaclTranslateKey]; 248 Json::Value url_spec = pnacl_spec[kPnaclTranslateKey];
196 if (!IsValidUrlSpec(url_spec, kPnaclTranslateKey, 249 if (!IsValidUrlSpec(url_spec, kPnaclTranslateKey,
197 container_key, error_string)) { 250 container_key, sandbox_isa, error_string)) {
198 return false; 251 return false;
199 } 252 }
200 return true; 253 return true;
201 } 254 }
202 255
203 // Validates that |dictionary| is a valid ISA dictionary. An ISA dictionary 256 // Validates that |dictionary| is a valid ISA dictionary. An ISA dictionary
204 // is validated to have keys from within the set of recognized ISAs. Unknown 257 // is validated to have keys from within the set of recognized ISAs. Unknown
205 // ISAs are allowed, but ignored and warnings are produced. It is also validated 258 // ISAs are allowed, but ignored and warnings are produced. It is also validated
206 // that it must have an entry to match the ISA specified in |sandbox_isa| or 259 // that it must have an entry to match the ISA specified in |sandbox_isa| or
207 // have a fallback 'portable' entry if there is no match. Returns true if 260 // have a fallback 'portable' entry if there is no match. Returns true if
208 // |dictionary| is an ISA to URL map. Sets |error_info| to something 261 // |dictionary| is an ISA to URL map. Sets |error_info| to something
209 // descriptive if it fails. 262 // descriptive if it fails.
210 bool IsValidISADictionary(const Json::Value& dictionary, 263 bool IsValidISADictionary(const Json::Value& dictionary,
211 const nacl::string& parent_key, 264 const nacl::string& parent_key,
212 const nacl::string& sandbox_isa, 265 const nacl::string& sandbox_isa,
266 bool must_find_matching_entry,
213 ErrorInfo* error_info) { 267 ErrorInfo* error_info) {
214 if (error_info == NULL) return false; 268 if (error_info == NULL) return false;
215 269
216 // An ISA to URL dictionary has to be an object. 270 // An ISA to URL dictionary has to be an object.
217 if (!dictionary.isObject()) { 271 if (!dictionary.isObject()) {
218 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, 272 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE,
219 nacl::string("manifest: ") + parent_key + 273 nacl::string("manifest: ") + parent_key +
220 " property is not an ISA to URL dictionary"); 274 " property is not an ISA to URL dictionary");
221 return false; 275 return false;
222 } 276 }
223 // The keys to the dictionary have to be valid ISA names. 277 // Build the set of reserved ISA dictionary keys.
224 Json::Value::Members members = dictionary.getMemberNames(); 278 const char** isaProperties;
225 for (size_t i = 0; i < members.size(); ++i) { 279 size_t isaPropertiesLength;
226 // The known ISA values for ISA dictionaries in the manifest. 280 if (sandbox_isa == kPortableKey) {
227 static const char* kManifestISAProperties[] = { 281 // The known values for PNaCl ISA dictionaries in the manifest.
282 static const char* kPnaclManifestISAProperties[] = {
283 kPortableKey
284 };
285 isaProperties = kPnaclManifestISAProperties;
286 isaPropertiesLength = NACL_ARRAY_SIZE(kPnaclManifestISAProperties);
287 } else {
288 // The known values for NaCl ISA dictionaries in the manifest.
289 static const char* kNaClManifestISAProperties[] = {
228 kX8632Key, 290 kX8632Key,
229 kX8664Key, 291 kX8664Key,
230 kArmKey, 292 kArmKey,
293 // "portable" is here to allow checking that, if present, it can
294 // only refer to an URL, such as for a data file, and not to
295 // "pnacl-translate", which would cause the creation of a nexe.
231 kPortableKey 296 kPortableKey
232 }; 297 };
298 isaProperties = kNaClManifestISAProperties;
299 isaPropertiesLength = NACL_ARRAY_SIZE(kNaClManifestISAProperties);
300 }
301 // Check that entries in the dictionary are structurally correct.
302 Json::Value::Members members = dictionary.getMemberNames();
303 for (size_t i = 0; i < members.size(); ++i) {
233 nacl::string property_name = members[i]; 304 nacl::string property_name = members[i];
234 if (!FindMatchingProperty(property_name,
235 kManifestISAProperties,
236 NACL_ARRAY_SIZE(kManifestISAProperties))) {
237 PLUGIN_PRINTF(("IsValidISADictionary: unrecognized ISA '%s'.\n",
238 property_name.c_str()));
239 }
240 // Could be "arch/portable" : URLSpec, or
241 // it could be "arch/portable" : { "pnacl-translate": URLSpec }
242 // for executables that need to be translated.
243 Json::Value property_value = dictionary[property_name]; 305 Json::Value property_value = dictionary[property_name];
244 nacl::string error_string; 306 nacl::string error_string;
245 if (!IsValidUrlSpec(property_value, property_name, parent_key, 307 if (FindMatchingProperty(property_name,
246 &error_string) && 308 isaProperties,
247 !IsValidPnaclTranslateSpec(property_value, property_name, 309 isaPropertiesLength)) {
248 parent_key, &error_string)) { 310 // For NaCl, arch entries can only be
249 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, 311 // "arch/portable" : URLSpec
250 nacl::string("manifest: ") + error_string); 312 // For PNaCl arch in "program" dictionary entries can only be
251 return false; 313 // "portable" : { "pnacl-translate": URLSpec }
314 // For PNaCl arch elsewhere, dictionary entries can only be
315 // "portable" : URLSpec
316 if ((sandbox_isa != kPortableKey &&
317 !IsValidUrlSpec(property_value, property_name, parent_key,
318 sandbox_isa, &error_string)) ||
319 (sandbox_isa == kPortableKey &&
320 parent_key == kProgramKey &&
321 !IsValidPnaclTranslateSpec(property_value, property_name, parent_key,
322 sandbox_isa, &error_string)) ||
323 (sandbox_isa == kPortableKey &&
324 parent_key != kProgramKey &&
325 !IsValidUrlSpec(property_value, property_name, parent_key,
326 sandbox_isa, &error_string))) {
327 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE,
328 nacl::string("manifest: ") + error_string);
329 return false;
330 }
331 } else {
332 // For forward compatibility, we do not prohibit other keys being in
333 // the dictionary, as they may be architectures supported in later
334 // versions. However, the value of these entries must be an URLSpec.
335 PLUGIN_PRINTF(("IsValidISADictionary: unrecognized key '%s'.\n",
336 property_name.c_str()));
337 if (!IsValidUrlSpec(property_value, property_name, parent_key,
338 sandbox_isa, &error_string)) {
339 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE,
340 nacl::string("manifest: ") + error_string);
341 return false;
342 }
252 } 343 }
253 } 344 }
254 345
255 if (!sandbox_isa.empty()) { 346 if (sandbox_isa == kPortableKey) {
347 bool has_portable = dictionary.isMember(kPortableKey);
348
349 if (!has_portable) {
350 error_info->SetReport(
351 ERROR_MANIFEST_PROGRAM_MISSING_ARCH,
352 nacl::string("manifest: no version of ") + parent_key +
353 " given for portable.");
354 return false;
355 }
356 } else if (must_find_matching_entry) {
256 // TODO(elijahtaylor) add ISA resolver here if we expand ISAs to include 357 // TODO(elijahtaylor) add ISA resolver here if we expand ISAs to include
257 // micro-architectures that can resolve to multiple valid sandboxes. 358 // micro-architectures that can resolve to multiple valid sandboxes.
258 bool has_isa = dictionary.isMember(sandbox_isa); 359 bool has_isa = dictionary.isMember(sandbox_isa);
259 bool has_portable = dictionary.isMember(kPortableKey); 360 bool has_portable = dictionary.isMember(kPortableKey);
260 361
261 if (!has_isa && !has_portable) { 362 if (!has_isa && !has_portable) {
262 error_info->SetReport( 363 error_info->SetReport(
263 ERROR_MANIFEST_PROGRAM_MISSING_ARCH, 364 ERROR_MANIFEST_PROGRAM_MISSING_ARCH,
264 nacl::string("manifest: no version of ") + parent_key + 365 nacl::string("manifest: no version of ") + parent_key +
265 " given for current arch and no portable version found."); 366 " given for current arch and no portable version found.");
(...skipping 20 matching lines...) Expand all
286 } 387 }
287 if (url_spec.isMember(kPnaclExperimentalFlags)) { 388 if (url_spec.isMember(kPnaclExperimentalFlags)) {
288 pnacl_options->set_experimental_flags( 389 pnacl_options->set_experimental_flags(
289 url_spec[kPnaclExperimentalFlags].asString()); 390 url_spec[kPnaclExperimentalFlags].asString());
290 } 391 }
291 } 392 }
292 393
293 bool GetURLFromISADictionary(const Json::Value& dictionary, 394 bool GetURLFromISADictionary(const Json::Value& dictionary,
294 const nacl::string& parent_key, 395 const nacl::string& parent_key,
295 const nacl::string& sandbox_isa, 396 const nacl::string& sandbox_isa,
296 bool prefer_portable,
297 nacl::string* url, 397 nacl::string* url,
298 PnaclOptions* pnacl_options, 398 PnaclOptions* pnacl_options,
299 ErrorInfo* error_info) { 399 ErrorInfo* error_info) {
300 if (url == NULL || pnacl_options == NULL || error_info == NULL) 400 if (url == NULL || pnacl_options == NULL || error_info == NULL)
301 return false; 401 return false;
302 402
303 if (!IsValidISADictionary(dictionary, parent_key, sandbox_isa, error_info)) { 403 // When the application actually requests a resolved URL, we must have
404 // a matching entry (sandbox_isa or portable) for NaCl.
405 if (!IsValidISADictionary(dictionary, parent_key, sandbox_isa, true,
406 error_info)) {
304 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 407 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL,
305 "architecture " + sandbox_isa + 408 "architecture " + sandbox_isa +
306 " is not found for file " + parent_key); 409 " is not found for file " + parent_key);
307 return false; 410 return false;
308 } 411 }
309 412
310 *url = ""; 413 *url = "";
311 414
312 // The call to IsValidISADictionary() above guarantees that either 415 // The call to IsValidISADictionary() above guarantees that either
313 // sandbox_isa or kPortableKey is present in the dictionary. 416 // sandbox_isa or kPortableKey is present in the dictionary.
314 bool has_portable = dictionary.isMember(kPortableKey); 417 bool has_portable = dictionary.isMember(kPortableKey);
315 bool has_isa = dictionary.isMember(sandbox_isa); 418 bool has_isa = dictionary.isMember(sandbox_isa);
316 nacl::string chosen_isa; 419 nacl::string chosen_isa;
317 if ((has_portable && prefer_portable) || !has_isa) { 420 if ((sandbox_isa == kPortableKey) || (has_portable && !has_isa)) {
318 chosen_isa = kPortableKey; 421 chosen_isa = kPortableKey;
319 } else { 422 } else {
320 chosen_isa = sandbox_isa; 423 chosen_isa = sandbox_isa;
321 } 424 }
322 const Json::Value& isa_spec = dictionary[chosen_isa]; 425 const Json::Value& isa_spec = dictionary[chosen_isa];
323 // Check if this requires a pnacl-translate, otherwise just grab the URL. 426 // Check if this requires a pnacl-translate, otherwise just grab the URL.
324 // We may have pnacl-translate for isa-specific bitcode for CPU tuning. 427 // We may have pnacl-translate for isa-specific bitcode for CPU tuning.
325 if (isa_spec.isMember(kPnaclTranslateKey)) { 428 if (isa_spec.isMember(kPnaclTranslateKey)) {
429 // PNaCl
326 GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); 430 GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options);
327 pnacl_options->set_translate(true); 431 pnacl_options->set_translate(true);
328 } else { 432 } else {
433 // NaCl
329 *url = isa_spec[kUrlKey].asString(); 434 *url = isa_spec[kUrlKey].asString();
330 pnacl_options->set_translate(false); 435 pnacl_options->set_translate(false);
331 } 436 }
332 437
333 return true; 438 return true;
334 } 439 }
335 440
336 bool GetKeyUrl(const Json::Value& dictionary, 441 bool GetKeyUrl(const Json::Value& dictionary,
337 const nacl::string& key, 442 const nacl::string& key,
338 const nacl::string& sandbox_isa, 443 const nacl::string& sandbox_isa,
339 const Manifest* manifest, 444 const Manifest* manifest,
340 bool prefer_portable,
341 nacl::string* full_url, 445 nacl::string* full_url,
342 PnaclOptions* pnacl_options, 446 PnaclOptions* pnacl_options,
343 ErrorInfo* error_info) { 447 ErrorInfo* error_info) {
344 CHECK(full_url != NULL && error_info != NULL); 448 CHECK(full_url != NULL && error_info != NULL);
345 if (!dictionary.isMember(key)) { 449 if (!dictionary.isMember(key)) {
346 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 450 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL,
347 "file key not found in manifest"); 451 "file key not found in manifest");
348 return false; 452 return false;
349 } 453 }
350 const Json::Value& isa_dict = dictionary[key]; 454 const Json::Value& isa_dict = dictionary[key];
351 nacl::string relative_url; 455 nacl::string relative_url;
352 if (!GetURLFromISADictionary(isa_dict, key, sandbox_isa, prefer_portable, 456 if (!GetURLFromISADictionary(isa_dict, key, sandbox_isa, &relative_url,
353 &relative_url, pnacl_options, error_info)) { 457 pnacl_options, error_info)) {
354 return false; 458 return false;
355 } 459 }
356 return manifest->ResolveURL(relative_url, full_url, error_info); 460 return manifest->ResolveURL(relative_url, full_url, error_info);
357 } 461 }
358 462
359 } // namespace 463 } // namespace
360 464
361 bool JsonManifest::Init(const nacl::string& manifest_json, 465 bool JsonManifest::Init(const nacl::string& manifest_json,
362 ErrorInfo* error_info) { 466 ErrorInfo* error_info) {
363 if (error_info == NULL) { 467 if (error_info == NULL) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 507
404 // A manifest file must have a program section. 508 // A manifest file must have a program section.
405 if (!dictionary_.isMember(kProgramKey)) { 509 if (!dictionary_.isMember(kProgramKey)) {
406 error_info->SetReport( 510 error_info->SetReport(
407 ERROR_MANIFEST_SCHEMA_VALIDATE, 511 ERROR_MANIFEST_SCHEMA_VALIDATE,
408 nacl::string("manifest: missing '") + kProgramKey + "' section."); 512 nacl::string("manifest: missing '") + kProgramKey + "' section.");
409 return false; 513 return false;
410 } 514 }
411 515
412 // Validate the program section. 516 // Validate the program section.
517 // There must be a matching (portable or sandbox_isa_) entry for program for
518 // NaCl.
413 if (!IsValidISADictionary(dictionary_[kProgramKey], 519 if (!IsValidISADictionary(dictionary_[kProgramKey],
414 kProgramKey, 520 kProgramKey,
415 sandbox_isa_, 521 sandbox_isa_,
522 true,
416 error_info)) { 523 error_info)) {
417 return false; 524 return false;
418 } 525 }
419 526
420 // Validate the interpreter section (if given). 527 // Validate the interpreter section (if given).
528 // There must be a matching (portable or sandbox_isa_) entry for interpreter
529 // for NaCl.
421 if (dictionary_.isMember(kInterpreterKey)) { 530 if (dictionary_.isMember(kInterpreterKey)) {
422 if (!IsValidISADictionary(dictionary_[kInterpreterKey], 531 if (!IsValidISADictionary(dictionary_[kInterpreterKey],
423 kInterpreterKey, 532 kInterpreterKey,
424 sandbox_isa_, 533 sandbox_isa_,
534 true,
425 error_info)) { 535 error_info)) {
426 return false; 536 return false;
427 } 537 }
428 } 538 }
429 539
430 // Validate the file dictionary (if given). 540 // Validate the file dictionary (if given).
541 // The "files" key does not require a matching (portable or sandbox_isa_)
542 // entry at schema validation time for NaCl. This allows manifests to specify
543 // resources that are only loaded for a particular sandbox_isa.
431 if (dictionary_.isMember(kFilesKey)) { 544 if (dictionary_.isMember(kFilesKey)) {
432 const Json::Value& files = dictionary_[kFilesKey]; 545 const Json::Value& files = dictionary_[kFilesKey];
433 if (!files.isObject()) { 546 if (!files.isObject()) {
434 error_info->SetReport( 547 error_info->SetReport(
435 ERROR_MANIFEST_SCHEMA_VALIDATE, 548 ERROR_MANIFEST_SCHEMA_VALIDATE,
436 nacl::string("manifest: '") + kFilesKey + "' is not a dictionary."); 549 nacl::string("manifest: '") + kFilesKey + "' is not a dictionary.");
437 } 550 }
438 Json::Value::Members members = files.getMemberNames(); 551 Json::Value::Members members = files.getMemberNames();
439 for (size_t i = 0; i < members.size(); ++i) { 552 for (size_t i = 0; i < members.size(); ++i) {
440 nacl::string file_name = members[i]; 553 nacl::string file_name = members[i];
441 if (!IsValidISADictionary(files[file_name], 554 if (!IsValidISADictionary(files[file_name],
442 file_name, 555 file_name,
443 nacl::string(), 556 sandbox_isa_,
557 false,
444 error_info)) { 558 error_info)) {
445 return false; 559 return false;
446 } 560 }
447 } 561 }
448 } 562 }
449 563
450 return true; 564 return true;
451 } 565 }
452 566
453 bool JsonManifest::ResolveURL(const nacl::string& relative_url, 567 bool JsonManifest::ResolveURL(const nacl::string& relative_url,
(...skipping 23 matching lines...) Expand all
477 return false; 591 return false;
478 592
479 Json::Value program = dictionary_[kProgramKey]; 593 Json::Value program = dictionary_[kProgramKey];
480 594
481 nacl::string nexe_url; 595 nacl::string nexe_url;
482 nacl::string error_string; 596 nacl::string error_string;
483 597
484 if (!GetURLFromISADictionary(program, 598 if (!GetURLFromISADictionary(program,
485 kProgramKey, 599 kProgramKey,
486 sandbox_isa_, 600 sandbox_isa_,
487 prefer_portable_,
488 &nexe_url, 601 &nexe_url,
489 pnacl_options, 602 pnacl_options,
490 error_info)) { 603 error_info)) {
491 return false; 604 return false;
492 } 605 }
493 606
494 return ResolveURL(nexe_url, full_url, error_info); 607 return ResolveURL(nexe_url, full_url, error_info);
495 } 608 }
496 609
497 bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const { 610 bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const {
(...skipping 14 matching lines...) Expand all
512 nacl::string* full_url, 625 nacl::string* full_url,
513 PnaclOptions* pnacl_options, 626 PnaclOptions* pnacl_options,
514 ErrorInfo* error_info) const { 627 ErrorInfo* error_info) const {
515 NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str()); 628 NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str());
516 // key must be one of kProgramKey or kFileKey '/' file-section-key 629 // key must be one of kProgramKey or kFileKey '/' file-section-key
517 630
518 if (full_url == NULL || pnacl_options == NULL || error_info == NULL) 631 if (full_url == NULL || pnacl_options == NULL || error_info == NULL)
519 return false; 632 return false;
520 633
521 if (key == kProgramKey) { 634 if (key == kProgramKey) {
522 return GetKeyUrl(dictionary_, key, sandbox_isa_, this, prefer_portable_, 635 return GetKeyUrl(dictionary_, key, sandbox_isa_, this, full_url,
523 full_url, pnacl_options, error_info); 636 pnacl_options, error_info);
524 } 637 }
525 nacl::string::const_iterator p = find(key.begin(), key.end(), '/'); 638 nacl::string::const_iterator p = find(key.begin(), key.end(), '/');
526 if (p == key.end()) { 639 if (p == key.end()) {
527 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 640 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL,
528 nacl::string("ResolveKey: invalid key, no slash: ") 641 nacl::string("ResolveKey: invalid key, no slash: ")
529 + key); 642 + key);
530 return false; 643 return false;
531 } 644 }
532 645
533 // generalize to permit other sections? 646 // generalize to permit other sections?
(...skipping 13 matching lines...) Expand all
547 ERROR_MANIFEST_RESOLVE_URL, 660 ERROR_MANIFEST_RESOLVE_URL,
548 nacl::string("ResolveKey: no \"files\" dictionary")); 661 nacl::string("ResolveKey: no \"files\" dictionary"));
549 return false; 662 return false;
550 } 663 }
551 if (!files.isMember(rest)) { 664 if (!files.isMember(rest)) {
552 error_info->SetReport( 665 error_info->SetReport(
553 ERROR_MANIFEST_RESOLVE_URL, 666 ERROR_MANIFEST_RESOLVE_URL,
554 nacl::string("ResolveKey: no such \"files\" entry: ") + key); 667 nacl::string("ResolveKey: no such \"files\" entry: ") + key);
555 return false; 668 return false;
556 } 669 }
557 return GetKeyUrl(files, rest, sandbox_isa_, this, prefer_portable_, 670 return GetKeyUrl(files, rest, sandbox_isa_, this, full_url, pnacl_options,
558 full_url, pnacl_options, error_info); 671 error_info);
559 } 672 }
560 673
561 } // namespace plugin 674 } // namespace plugin
OLDNEW
« no previous file with comments | « ppapi/native_client/src/trusted/plugin/json_manifest.h ('k') | ppapi/native_client/src/trusted/plugin/plugin.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698