OLD | NEW |
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 Loading... |
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 Loading... |
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, |
213 ErrorInfo* error_info) { | 266 ErrorInfo* error_info) { |
214 if (error_info == NULL) return false; | 267 if (error_info == NULL) return false; |
215 | 268 |
216 // An ISA to URL dictionary has to be an object. | 269 // An ISA to URL dictionary has to be an object. |
217 if (!dictionary.isObject()) { | 270 if (!dictionary.isObject()) { |
218 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, | 271 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, |
219 nacl::string("manifest: ") + parent_key + | 272 nacl::string("manifest: ") + parent_key + |
220 " property is not an ISA to URL dictionary"); | 273 " property is not an ISA to URL dictionary"); |
221 return false; | 274 return false; |
222 } | 275 } |
223 // The keys to the dictionary have to be valid ISA names. | 276 // The keys to the dictionary have to be valid ISA names. |
224 Json::Value::Members members = dictionary.getMemberNames(); | 277 Json::Value::Members members = dictionary.getMemberNames(); |
225 for (size_t i = 0; i < members.size(); ++i) { | 278 for (size_t i = 0; i < members.size(); ++i) { |
226 // The known ISA values for ISA dictionaries in the manifest. | 279 const char** isaProperties; |
227 static const char* kManifestISAProperties[] = { | 280 size_t isaPropertiesLength; |
228 kX8632Key, | 281 if (sandbox_isa == kPortableKey) { |
229 kX8664Key, | 282 // The known values for PNaCl ISA dictionaries in the manifest. |
230 kArmKey, | 283 static const char* kPnaclManifestISAProperties[] = { |
231 kPortableKey | 284 kPortableKey |
232 }; | 285 }; |
| 286 isaProperties = kPnaclManifestISAProperties; |
| 287 isaPropertiesLength = NACL_ARRAY_SIZE(kPnaclManifestISAProperties); |
| 288 } else { |
| 289 // The known values for NaCl ISA dictionaries in the manifest. |
| 290 static const char* kNaClManifestISAProperties[] = { |
| 291 kX8632Key, |
| 292 kX8664Key, |
| 293 kArmKey, |
| 294 // "portable" is here to allow checking that, if present, it can |
| 295 // only refer to an URL, such as for a data file, and not to |
| 296 // "pnacl-translate", which would cause the creation of a nexe. |
| 297 kPortableKey |
| 298 }; |
| 299 isaProperties = kNaClManifestISAProperties; |
| 300 isaPropertiesLength = NACL_ARRAY_SIZE(kNaClManifestISAProperties); |
| 301 } |
233 nacl::string property_name = members[i]; | 302 nacl::string property_name = members[i]; |
234 if (!FindMatchingProperty(property_name, | 303 if (FindMatchingProperty(property_name, |
235 kManifestISAProperties, | 304 isaProperties, |
236 NACL_ARRAY_SIZE(kManifestISAProperties))) { | 305 isaPropertiesLength)) { |
237 PLUGIN_PRINTF(("IsValidISADictionary: unrecognized ISA '%s'.\n", | 306 Json::Value property_value = dictionary[property_name]; |
| 307 nacl::string error_string; |
| 308 // For NaCl, arch entries can only be |
| 309 // "arch/portable" : URLSpec |
| 310 // For PNaCl arch in "program" dictionary entries can only be |
| 311 // "portable" : { "pnacl-translate": URLSpec } |
| 312 // For PNaCl arch elsewhere, dictionary entries can only be |
| 313 // "portable" : URLSpec |
| 314 if ((sandbox_isa != kPortableKey && |
| 315 !IsValidUrlSpec(property_value, property_name, parent_key, |
| 316 sandbox_isa, &error_string)) || |
| 317 (sandbox_isa == kPortableKey && |
| 318 parent_key == kProgramKey && |
| 319 !IsValidPnaclTranslateSpec(property_value, property_name, parent_key, |
| 320 sandbox_isa, &error_string)) || |
| 321 (sandbox_isa == kPortableKey && |
| 322 parent_key != kProgramKey && |
| 323 !IsValidUrlSpec(property_value, property_name, parent_key, |
| 324 sandbox_isa, &error_string))) { |
| 325 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, |
| 326 nacl::string("manifest: ") + error_string); |
| 327 return false; |
| 328 } |
| 329 } else { |
| 330 // For forward compatibility, we do not prohibit other keys being in |
| 331 // the dictionary. |
| 332 PLUGIN_PRINTF(("IsValidISADictionary: unrecognized key '%s'.\n", |
238 property_name.c_str())); | 333 property_name.c_str())); |
239 } | 334 } |
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]; | |
244 nacl::string error_string; | |
245 if (!IsValidUrlSpec(property_value, property_name, parent_key, | |
246 &error_string) && | |
247 !IsValidPnaclTranslateSpec(property_value, property_name, | |
248 parent_key, &error_string)) { | |
249 error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, | |
250 nacl::string("manifest: ") + error_string); | |
251 return false; | |
252 } | |
253 } | 335 } |
254 | 336 |
255 if (!sandbox_isa.empty()) { | 337 if (sandbox_isa == kPortableKey) { |
| 338 bool has_portable = dictionary.isMember(kPortableKey); |
| 339 |
| 340 if (!has_portable) { |
| 341 error_info->SetReport( |
| 342 ERROR_MANIFEST_PROGRAM_MISSING_ARCH, |
| 343 nacl::string("manifest: no version of ") + parent_key + |
| 344 " given for portable."); |
| 345 return false; |
| 346 } |
| 347 } else { |
256 // TODO(elijahtaylor) add ISA resolver here if we expand ISAs to include | 348 // TODO(elijahtaylor) add ISA resolver here if we expand ISAs to include |
257 // micro-architectures that can resolve to multiple valid sandboxes. | 349 // micro-architectures that can resolve to multiple valid sandboxes. |
258 bool has_isa = dictionary.isMember(sandbox_isa); | 350 bool has_isa = dictionary.isMember(sandbox_isa); |
259 bool has_portable = dictionary.isMember(kPortableKey); | 351 bool has_portable = dictionary.isMember(kPortableKey); |
260 | 352 |
261 if (!has_isa && !has_portable) { | 353 if (!has_isa && !has_portable) { |
262 error_info->SetReport( | 354 error_info->SetReport( |
263 ERROR_MANIFEST_PROGRAM_MISSING_ARCH, | 355 ERROR_MANIFEST_PROGRAM_MISSING_ARCH, |
264 nacl::string("manifest: no version of ") + parent_key + | 356 nacl::string("manifest: no version of ") + parent_key + |
265 " given for current arch and no portable version found."); | 357 " given for current arch and no portable version found."); |
(...skipping 20 matching lines...) Expand all Loading... |
286 } | 378 } |
287 if (url_spec.isMember(kPnaclExperimentalFlags)) { | 379 if (url_spec.isMember(kPnaclExperimentalFlags)) { |
288 pnacl_options->set_experimental_flags( | 380 pnacl_options->set_experimental_flags( |
289 url_spec[kPnaclExperimentalFlags].asString()); | 381 url_spec[kPnaclExperimentalFlags].asString()); |
290 } | 382 } |
291 } | 383 } |
292 | 384 |
293 bool GetURLFromISADictionary(const Json::Value& dictionary, | 385 bool GetURLFromISADictionary(const Json::Value& dictionary, |
294 const nacl::string& parent_key, | 386 const nacl::string& parent_key, |
295 const nacl::string& sandbox_isa, | 387 const nacl::string& sandbox_isa, |
296 bool prefer_portable, | |
297 nacl::string* url, | 388 nacl::string* url, |
298 PnaclOptions* pnacl_options, | 389 PnaclOptions* pnacl_options, |
299 ErrorInfo* error_info) { | 390 ErrorInfo* error_info) { |
300 if (url == NULL || pnacl_options == NULL || error_info == NULL) | 391 if (url == NULL || pnacl_options == NULL || error_info == NULL) |
301 return false; | 392 return false; |
302 | 393 |
303 if (!IsValidISADictionary(dictionary, parent_key, sandbox_isa, error_info)) { | 394 if (!IsValidISADictionary(dictionary, parent_key, sandbox_isa, error_info)) { |
304 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, | 395 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, |
305 "architecture " + sandbox_isa + | 396 "architecture " + sandbox_isa + |
306 " is not found for file " + parent_key); | 397 " is not found for file " + parent_key); |
307 return false; | 398 return false; |
308 } | 399 } |
309 | 400 |
310 *url = ""; | 401 *url = ""; |
311 | 402 |
312 // The call to IsValidISADictionary() above guarantees that either | 403 // The call to IsValidISADictionary() above guarantees that either |
313 // sandbox_isa or kPortableKey is present in the dictionary. | 404 // sandbox_isa or kPortableKey is present in the dictionary. |
314 bool has_portable = dictionary.isMember(kPortableKey); | 405 bool has_portable = dictionary.isMember(kPortableKey); |
315 bool has_isa = dictionary.isMember(sandbox_isa); | 406 bool has_isa = dictionary.isMember(sandbox_isa); |
316 nacl::string chosen_isa; | 407 nacl::string chosen_isa; |
317 if ((has_portable && prefer_portable) || !has_isa) { | 408 if ((sandbox_isa == kPortableKey) || (has_portable && !has_isa)) { |
318 chosen_isa = kPortableKey; | 409 chosen_isa = kPortableKey; |
319 } else { | 410 } else { |
320 chosen_isa = sandbox_isa; | 411 chosen_isa = sandbox_isa; |
321 } | 412 } |
322 const Json::Value& isa_spec = dictionary[chosen_isa]; | 413 const Json::Value& isa_spec = dictionary[chosen_isa]; |
323 // Check if this requires a pnacl-translate, otherwise just grab the URL. | 414 // 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. | 415 // We may have pnacl-translate for isa-specific bitcode for CPU tuning. |
325 if (isa_spec.isMember(kPnaclTranslateKey)) { | 416 if (isa_spec.isMember(kPnaclTranslateKey)) { |
| 417 // PNaCl |
326 GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); | 418 GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); |
327 pnacl_options->set_translate(true); | 419 pnacl_options->set_translate(true); |
328 } else { | 420 } else { |
| 421 // NaCl |
329 *url = isa_spec[kUrlKey].asString(); | 422 *url = isa_spec[kUrlKey].asString(); |
330 pnacl_options->set_translate(false); | 423 pnacl_options->set_translate(false); |
331 } | 424 } |
332 | 425 |
333 return true; | 426 return true; |
334 } | 427 } |
335 | 428 |
336 bool GetKeyUrl(const Json::Value& dictionary, | 429 bool GetKeyUrl(const Json::Value& dictionary, |
337 const nacl::string& key, | 430 const nacl::string& key, |
338 const nacl::string& sandbox_isa, | 431 const nacl::string& sandbox_isa, |
339 const Manifest* manifest, | 432 const Manifest* manifest, |
340 bool prefer_portable, | |
341 nacl::string* full_url, | 433 nacl::string* full_url, |
342 PnaclOptions* pnacl_options, | 434 PnaclOptions* pnacl_options, |
343 ErrorInfo* error_info) { | 435 ErrorInfo* error_info) { |
344 CHECK(full_url != NULL && error_info != NULL); | 436 CHECK(full_url != NULL && error_info != NULL); |
345 if (!dictionary.isMember(key)) { | 437 if (!dictionary.isMember(key)) { |
346 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, | 438 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, |
347 "file key not found in manifest"); | 439 "file key not found in manifest"); |
348 return false; | 440 return false; |
349 } | 441 } |
350 const Json::Value& isa_dict = dictionary[key]; | 442 const Json::Value& isa_dict = dictionary[key]; |
351 nacl::string relative_url; | 443 nacl::string relative_url; |
352 if (!GetURLFromISADictionary(isa_dict, key, sandbox_isa, prefer_portable, | 444 if (!GetURLFromISADictionary(isa_dict, key, sandbox_isa, &relative_url, |
353 &relative_url, pnacl_options, error_info)) { | 445 pnacl_options, error_info)) { |
354 return false; | 446 return false; |
355 } | 447 } |
356 return manifest->ResolveURL(relative_url, full_url, error_info); | 448 return manifest->ResolveURL(relative_url, full_url, error_info); |
357 } | 449 } |
358 | 450 |
359 } // namespace | 451 } // namespace |
360 | 452 |
361 bool JsonManifest::Init(const nacl::string& manifest_json, | 453 bool JsonManifest::Init(const nacl::string& manifest_json, |
362 ErrorInfo* error_info) { | 454 ErrorInfo* error_info) { |
363 if (error_info == NULL) { | 455 if (error_info == NULL) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 if (!files.isObject()) { | 525 if (!files.isObject()) { |
434 error_info->SetReport( | 526 error_info->SetReport( |
435 ERROR_MANIFEST_SCHEMA_VALIDATE, | 527 ERROR_MANIFEST_SCHEMA_VALIDATE, |
436 nacl::string("manifest: '") + kFilesKey + "' is not a dictionary."); | 528 nacl::string("manifest: '") + kFilesKey + "' is not a dictionary."); |
437 } | 529 } |
438 Json::Value::Members members = files.getMemberNames(); | 530 Json::Value::Members members = files.getMemberNames(); |
439 for (size_t i = 0; i < members.size(); ++i) { | 531 for (size_t i = 0; i < members.size(); ++i) { |
440 nacl::string file_name = members[i]; | 532 nacl::string file_name = members[i]; |
441 if (!IsValidISADictionary(files[file_name], | 533 if (!IsValidISADictionary(files[file_name], |
442 file_name, | 534 file_name, |
443 nacl::string(), | 535 sandbox_isa_, |
444 error_info)) { | 536 error_info)) { |
445 return false; | 537 return false; |
446 } | 538 } |
447 } | 539 } |
448 } | 540 } |
449 | 541 |
450 return true; | 542 return true; |
451 } | 543 } |
452 | 544 |
453 bool JsonManifest::ResolveURL(const nacl::string& relative_url, | 545 bool JsonManifest::ResolveURL(const nacl::string& relative_url, |
(...skipping 23 matching lines...) Expand all Loading... |
477 return false; | 569 return false; |
478 | 570 |
479 Json::Value program = dictionary_[kProgramKey]; | 571 Json::Value program = dictionary_[kProgramKey]; |
480 | 572 |
481 nacl::string nexe_url; | 573 nacl::string nexe_url; |
482 nacl::string error_string; | 574 nacl::string error_string; |
483 | 575 |
484 if (!GetURLFromISADictionary(program, | 576 if (!GetURLFromISADictionary(program, |
485 kProgramKey, | 577 kProgramKey, |
486 sandbox_isa_, | 578 sandbox_isa_, |
487 prefer_portable_, | |
488 &nexe_url, | 579 &nexe_url, |
489 pnacl_options, | 580 pnacl_options, |
490 error_info)) { | 581 error_info)) { |
491 return false; | 582 return false; |
492 } | 583 } |
493 | 584 |
494 return ResolveURL(nexe_url, full_url, error_info); | 585 return ResolveURL(nexe_url, full_url, error_info); |
495 } | 586 } |
496 | 587 |
497 bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const { | 588 bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const { |
(...skipping 14 matching lines...) Expand all Loading... |
512 nacl::string* full_url, | 603 nacl::string* full_url, |
513 PnaclOptions* pnacl_options, | 604 PnaclOptions* pnacl_options, |
514 ErrorInfo* error_info) const { | 605 ErrorInfo* error_info) const { |
515 NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str()); | 606 NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str()); |
516 // key must be one of kProgramKey or kFileKey '/' file-section-key | 607 // key must be one of kProgramKey or kFileKey '/' file-section-key |
517 | 608 |
518 if (full_url == NULL || pnacl_options == NULL || error_info == NULL) | 609 if (full_url == NULL || pnacl_options == NULL || error_info == NULL) |
519 return false; | 610 return false; |
520 | 611 |
521 if (key == kProgramKey) { | 612 if (key == kProgramKey) { |
522 return GetKeyUrl(dictionary_, key, sandbox_isa_, this, prefer_portable_, | 613 return GetKeyUrl(dictionary_, key, sandbox_isa_, this, full_url, |
523 full_url, pnacl_options, error_info); | 614 pnacl_options, error_info); |
524 } | 615 } |
525 nacl::string::const_iterator p = find(key.begin(), key.end(), '/'); | 616 nacl::string::const_iterator p = find(key.begin(), key.end(), '/'); |
526 if (p == key.end()) { | 617 if (p == key.end()) { |
527 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, | 618 error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, |
528 nacl::string("ResolveKey: invalid key, no slash: ") | 619 nacl::string("ResolveKey: invalid key, no slash: ") |
529 + key); | 620 + key); |
530 return false; | 621 return false; |
531 } | 622 } |
532 | 623 |
533 // generalize to permit other sections? | 624 // generalize to permit other sections? |
(...skipping 13 matching lines...) Expand all Loading... |
547 ERROR_MANIFEST_RESOLVE_URL, | 638 ERROR_MANIFEST_RESOLVE_URL, |
548 nacl::string("ResolveKey: no \"files\" dictionary")); | 639 nacl::string("ResolveKey: no \"files\" dictionary")); |
549 return false; | 640 return false; |
550 } | 641 } |
551 if (!files.isMember(rest)) { | 642 if (!files.isMember(rest)) { |
552 error_info->SetReport( | 643 error_info->SetReport( |
553 ERROR_MANIFEST_RESOLVE_URL, | 644 ERROR_MANIFEST_RESOLVE_URL, |
554 nacl::string("ResolveKey: no such \"files\" entry: ") + key); | 645 nacl::string("ResolveKey: no such \"files\" entry: ") + key); |
555 return false; | 646 return false; |
556 } | 647 } |
557 return GetKeyUrl(files, rest, sandbox_isa_, this, prefer_portable_, | 648 return GetKeyUrl(files, rest, sandbox_isa_, this, full_url, pnacl_options, |
558 full_url, pnacl_options, error_info); | 649 error_info); |
559 } | 650 } |
560 | 651 |
561 } // namespace plugin | 652 } // namespace plugin |
OLD | NEW |