15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/json_manifest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/nacl_base.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/nacl_macros.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/nacl_string.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/include/portability.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/shared/platform/nacl_check.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/dev/url_util_dev.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h" 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/plugin_error.h" 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/pnacl_options.h" 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "ppapi/native_client/src/trusted/plugin/utility.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/jsoncpp/source/include/json/reader.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace plugin { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Top-level section name keys 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kProgramKey = "program"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kInterpreterKey = "interpreter"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kFilesKey = "files"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ISA Dictionary keys 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kX8632Key = "x86-32"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kX8664Key = "x86-64"; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kArmKey = "arm"; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kPortableKey = "portable"; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Url Resolution keys 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kPnaclTranslateKey = "pnacl-translate"; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kUrlKey = "url"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// PNaCl keys 44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst char* const kOptLevelKey = "optlevel"; 45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// DEPRECATED! TODO(jvoung): remove the error message after launch. 46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst char* const kOptLevelKeyDeprecated = "-O"; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Sample NaCl manifest file: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "program": { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "x86-32": {"url": "myprogram_x86-32.nexe"}, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "x86-64": {"url": "myprogram_x86-64.nexe"}, 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "arm": {"url": "myprogram_arm.nexe"} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "interpreter": { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "x86-32": {"url": "interpreter_x86-32.nexe"}, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "x86-64": {"url": "interpreter_x86-64.nexe"}, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "arm": {"url": "interpreter_arm.nexe"} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "files": { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "foo.txt": { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "portable": {"url": "foo.txt"} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "bar.txt": { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "x86-32": {"url": "x86-32/bar.txt"}, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "portable": {"url": "bar.txt"} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "libfoo.so": { 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "x86-64" : { "url": "..." } 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// } 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// } 727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// } 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Sample PNaCl manifest file: 757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// { 767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "program": { 777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "portable": { 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "pnacl-translate": { 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "url": "myprogram.pexe", 80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// "optlevel": 0 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// } 827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// } 837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// }, 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "files": { 857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "foo.txt": { 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "portable": {"url": "foo.txt"} 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// }, 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "bar.txt": { 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// "portable": {"url": "bar.txt"} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Looks up |property_name| in the vector |valid_names| with length 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |valid_name_count|. Returns true if |property_name| is found. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindMatchingProperty(const nacl::string& property_name, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char** valid_names, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t valid_name_count) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < valid_name_count; ++i) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (property_name == valid_names[i]) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return true if this is a valid dictionary. Having only keys present in 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |valid_keys| and having at least the keys in |required_keys|. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Error messages will be placed in |error_string|, given that the dictionary 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// was the property value of |container_key|. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// E.g., "container_key" : dictionary 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidDictionary(const Json::Value& dictionary, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& container_key, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& parent_key, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char** valid_keys, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t valid_key_count, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char** required_keys, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t required_key_count, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* error_string) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary.isObject()) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::stringstream error_stream; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_stream << parent_key << " property '" << container_key 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' is non-dictionary value '" 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << dictionary.toStyledString() << "'."; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_string = error_stream.str(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for unknown dictionary members. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value::Members members = dictionary.getMemberNames(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < members.size(); ++i) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string property_name = members[i]; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FindMatchingProperty(property_name, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_keys, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_key_count)) { 1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // For forward compatibility, we do not prohibit other keys being in 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // the dictionary. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("WARNING: '%s' property '%s' has unknown key '%s'.\n", 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_key.c_str(), 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_key.c_str(), property_name.c_str())); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for required members. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < required_key_count; ++i) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary.isMember(required_keys[i])) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::stringstream error_stream; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_stream << parent_key << " property '" << container_key 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "' does not have required key: '" 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << required_keys[i] << "'."; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_string = error_stream.str(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Validate a "url" dictionary assuming it was resolved from container_key. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// E.g., "container_key" : { "url": "foo.txt" } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidUrlSpec(const Json::Value& url_spec, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& container_key, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& parent_key, 1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const nacl::string& sandbox_isa, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* error_string) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* kManifestUrlSpecRequired[] = { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUrlKey 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char** urlSpecPlusOptional; 1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) size_t urlSpecPlusOptionalLength; 1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (sandbox_isa == kPortableKey) { 1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static const char* kPnaclUrlSpecPlusOptional[] = { 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kUrlKey, 1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kOptLevelKey, 1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) }; 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptional = kPnaclUrlSpecPlusOptional; 1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptionalLength = NACL_ARRAY_SIZE(kPnaclUrlSpecPlusOptional); 1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptional = kManifestUrlSpecRequired; 1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptionalLength = NACL_ARRAY_SIZE(kManifestUrlSpecRequired); 1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidDictionary(url_spec, container_key, parent_key, 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptional, 1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) urlSpecPlusOptionalLength, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kManifestUrlSpecRequired, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_ARRAY_SIZE(kManifestUrlSpecRequired), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_string)) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // URL specifications must not contain "pnacl-translate" keys. 1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // This prohibits NaCl clients from invoking PNaCl. 1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Json::Value translate = url_spec[kPnaclTranslateKey]; 1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!translate.empty()) { 1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl::stringstream error_stream; 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_stream << parent_key << " property '" << container_key << 1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) "' has '" << kPnaclTranslateKey << "' inside URL spec."; 1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *error_string = error_stream.str(); 1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Verify the correct types of the fields if they exist. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value url = url_spec[kUrlKey]; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.isString()) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::stringstream error_stream; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_stream << parent_key << " property '" << container_key << 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "' has non-string value '" << url.toStyledString() << 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "' for key '" << kUrlKey << "'."; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error_string = error_stream.str(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Json::Value opt_level = url_spec[kOptLevelKey]; 2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!opt_level.empty() && !opt_level.isNumeric()) { 2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl::stringstream error_stream; 2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_stream << parent_key << " property '" << container_key << 2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) "' has non-numeric value '" << opt_level.toStyledString() << 2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) "' for key '" << kOptLevelKey << "'."; 2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *error_string = error_stream.str(); 2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (url_spec.isMember(kOptLevelKeyDeprecated)) { 217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch nacl::stringstream error_stream; 218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch error_stream << parent_key << " property '" << container_key << 219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "' has deprecated key '" << kOptLevelKeyDeprecated << 220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "' please use '" << kOptLevelKey << "' instead."; 221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *error_string = error_stream.str(); 222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Validate a "pnacl-translate" dictionary, assuming it was resolved from 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// container_key. E.g., "container_key" : { "pnacl_translate" : URLSpec } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidPnaclTranslateSpec(const Json::Value& pnacl_spec, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& container_key, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& parent_key, 2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const nacl::string& sandbox_isa, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* error_string) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* kManifestPnaclSpecProperties[] = { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kPnaclTranslateKey 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidDictionary(pnacl_spec, container_key, parent_key, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kManifestPnaclSpecProperties, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_ARRAY_SIZE(kManifestPnaclSpecProperties), 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kManifestPnaclSpecProperties, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_ARRAY_SIZE(kManifestPnaclSpecProperties), 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_string)) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value url_spec = pnacl_spec[kPnaclTranslateKey]; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidUrlSpec(url_spec, kPnaclTranslateKey, 2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) container_key, sandbox_isa, error_string)) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Validates that |dictionary| is a valid ISA dictionary. An ISA dictionary 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is validated to have keys from within the set of recognized ISAs. Unknown 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ISAs are allowed, but ignored and warnings are produced. It is also validated 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that it must have an entry to match the ISA specified in |sandbox_isa| or 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have a fallback 'portable' entry if there is no match. Returns true if 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |dictionary| is an ISA to URL map. Sets |error_info| to something 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptive if it fails. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidISADictionary(const Json::Value& dictionary, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& parent_key, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& sandbox_isa, 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool must_find_matching_entry, 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorInfo* error_info) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error_info == NULL) return false; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An ISA to URL dictionary has to be an object. 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary.isObject()) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nacl::string("manifest: ") + parent_key + 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) " property is not an ISA to URL dictionary"); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Build the set of reserved ISA dictionary keys. 2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char** isaProperties; 2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) size_t isaPropertiesLength; 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (sandbox_isa == kPortableKey) { 2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The known values for PNaCl ISA dictionaries in the manifest. 2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static const char* kPnaclManifestISAProperties[] = { 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kPortableKey 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) }; 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaProperties = kPnaclManifestISAProperties; 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaPropertiesLength = NACL_ARRAY_SIZE(kPnaclManifestISAProperties); 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The known values for NaCl ISA dictionaries in the manifest. 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) static const char* kNaClManifestISAProperties[] = { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kX8632Key, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kX8664Key, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kArmKey, 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // "portable" is here to allow checking that, if present, it can 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // only refer to an URL, such as for a data file, and not to 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // "pnacl-translate", which would cause the creation of a nexe. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kPortableKey 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaProperties = kNaClManifestISAProperties; 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaPropertiesLength = NACL_ARRAY_SIZE(kNaClManifestISAProperties); 2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Check that entries in the dictionary are structurally correct. 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Json::Value::Members members = dictionary.getMemberNames(); 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (size_t i = 0; i < members.size(); ++i) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string property_name = members[i]; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value property_value = dictionary[property_name]; 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nacl::string error_string; 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (FindMatchingProperty(property_name, 3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaProperties, 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) isaPropertiesLength)) { 3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // For NaCl, arch entries can only be 3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // "arch/portable" : URLSpec 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // For PNaCl arch in "program" dictionary entries can only be 3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // "portable" : { "pnacl-translate": URLSpec } 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // For PNaCl arch elsewhere, dictionary entries can only be 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // "portable" : URLSpec 3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if ((sandbox_isa != kPortableKey && 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !IsValidUrlSpec(property_value, property_name, parent_key, 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sandbox_isa, &error_string)) || 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (sandbox_isa == kPortableKey && 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) parent_key == kProgramKey && 3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !IsValidPnaclTranslateSpec(property_value, property_name, parent_key, 3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sandbox_isa, &error_string)) || 3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (sandbox_isa == kPortableKey && 3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) parent_key != kProgramKey && 3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !IsValidUrlSpec(property_value, property_name, parent_key, 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sandbox_isa, &error_string))) { 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl::string("manifest: ") + error_string); 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // For forward compatibility, we do not prohibit other keys being in 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // the dictionary, as they may be architectures supported in later 3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // versions. However, the value of these entries must be an URLSpec. 3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PLUGIN_PRINTF(("IsValidISADictionary: unrecognized key '%s'.\n", 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) property_name.c_str())); 3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!IsValidUrlSpec(property_value, property_name, parent_key, 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sandbox_isa, &error_string)) { 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_SCHEMA_VALIDATE, 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl::string("manifest: ") + error_string); 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (sandbox_isa == kPortableKey) { 3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool has_portable = dictionary.isMember(kPortableKey); 3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!has_portable) { 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_info->SetReport( 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ERROR_MANIFEST_PROGRAM_MISSING_ARCH, 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) nacl::string("manifest: no version of ") + parent_key + 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) " given for portable."); 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return false; 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else if (must_find_matching_entry) { 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(elijahtaylor) add ISA resolver here if we expand ISAs to include 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // micro-architectures that can resolve to multiple valid sandboxes. 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool has_isa = dictionary.isMember(sandbox_isa); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool has_portable = dictionary.isMember(kPortableKey); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!has_isa && !has_portable) { 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) error_info->SetReport( 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERROR_MANIFEST_PROGRAM_MISSING_ARCH, 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) nacl::string("manifest: no version of ") + parent_key + 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " given for current arch and no portable version found."); 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GrabUrlAndPnaclOptions(const Json::Value& url_spec, 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nacl::string* url, 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *url = url_spec[kUrlKey].asString(); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (url_spec.isMember(kOptLevelKey)) { 376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int32_t opt_raw = url_spec[kOptLevelKey].asInt(); 377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // set_opt_level will normalize the values. 378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pnacl_options->set_opt_level(opt_raw); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetURLFromISADictionary(const Json::Value& dictionary, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& parent_key, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& sandbox_isa, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* url, 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options, 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorInfo* error_info) { 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (url == NULL || pnacl_options == NULL || error_info == NULL) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // When the application actually requests a resolved URL, we must have 3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // a matching entry (sandbox_isa or portable) for NaCl. 3937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!IsValidISADictionary(dictionary, parent_key, sandbox_isa, true, 3947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_info)) { 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "architecture " + sandbox_isa + 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " is not found for file " + parent_key); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *url = ""; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The call to IsValidISADictionary() above guarantees that either 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sandbox_isa or kPortableKey is present in the dictionary. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_portable = dictionary.isMember(kPortableKey); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_isa = dictionary.isMember(sandbox_isa); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string chosen_isa; 4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if ((sandbox_isa == kPortableKey) || (has_portable && !has_isa)) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chosen_isa = kPortableKey; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chosen_isa = sandbox_isa; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Json::Value& isa_spec = dictionary[chosen_isa]; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if this requires a pnacl-translate, otherwise just grab the URL. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We may have pnacl-translate for isa-specific bitcode for CPU tuning. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isa_spec.isMember(kPnaclTranslateKey)) { 4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // PNaCl 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GrabUrlAndPnaclOptions(isa_spec[kPnaclTranslateKey], url, pnacl_options); 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pnacl_options->set_translate(true); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // NaCl 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *url = isa_spec[kUrlKey].asString(); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pnacl_options->set_translate(false); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetKeyUrl(const Json::Value& dictionary, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& key, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const nacl::string& sandbox_isa, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Manifest* manifest, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* full_url, 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options, 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorInfo* error_info) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(full_url != NULL && error_info != NULL); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary.isMember(key)) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "file key not found in manifest"); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Json::Value& isa_dict = dictionary[key]; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string relative_url; 4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!GetURLFromISADictionary(isa_dict, key, sandbox_isa, &relative_url, 4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pnacl_options, error_info)) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return manifest->ResolveURL(relative_url, full_url, error_info); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::Init(const nacl::string& manifest_json, 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo* error_info) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_info == NULL) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Reader reader; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reader.parse(manifest_json, dictionary_)) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string json_error = reader.getFormatedErrorMessages(); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_PARSING, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "manifest JSON parsing failed: " + json_error); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse has ensured the string was valid JSON. Check that it matches the 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // manifest schema. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MatchesSchema(error_info); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::MatchesSchema(ErrorInfo* error_info) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Var exception; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_info == NULL) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary_.isObject()) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_SCHEMA_VALIDATE, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "manifest: is not a json dictionary."); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value::Members members = dictionary_.getMemberNames(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < members.size(); ++i) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The top level dictionary entries valid in the manifest file. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* kManifestTopLevelProperties[] = { kProgramKey, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInterpreterKey, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFilesKey }; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string property_name = members[i]; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FindMatchingProperty(property_name, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kManifestTopLevelProperties, 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NACL_ARRAY_SIZE(kManifestTopLevelProperties))) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLUGIN_PRINTF(("JsonManifest::MatchesSchema: WARNING: unknown top-level " 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "section '%s' in manifest.\n", property_name.c_str())); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A manifest file must have a program section. 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary_.isMember(kProgramKey)) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_SCHEMA_VALIDATE, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("manifest: missing '") + kProgramKey + "' section."); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the program section. 5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // There must be a matching (portable or sandbox_isa_) entry for program for 5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // NaCl. 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidISADictionary(dictionary_[kProgramKey], 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kProgramKey, 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox_isa_, 5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) true, 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_info)) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the interpreter section (if given). 5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // There must be a matching (portable or sandbox_isa_) entry for interpreter 5177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // for NaCl. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dictionary_.isMember(kInterpreterKey)) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidISADictionary(dictionary_[kInterpreterKey], 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInterpreterKey, 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox_isa_, 5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) true, 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_info)) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate the file dictionary (if given). 5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // The "files" key does not require a matching (portable or sandbox_isa_) 5307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // entry at schema validation time for NaCl. This allows manifests to specify 5317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // resources that are only loaded for a particular sandbox_isa. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dictionary_.isMember(kFilesKey)) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Json::Value& files = dictionary_[kFilesKey]; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!files.isObject()) { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_SCHEMA_VALIDATE, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("manifest: '") + kFilesKey + "' is not a dictionary."); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value::Members members = files.getMemberNames(); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < members.size(); ++i) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string file_name = members[i]; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidISADictionary(files[file_name], 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_name, 5447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sandbox_isa_, 5457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) false, 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_info)) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::ResolveURL(const nacl::string& relative_url, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* full_url, 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorInfo* error_info) const { 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The contents of the manifest are resolved relative to the manifest URL. 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(url_util_ != NULL); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Var resolved_url = 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_util_->ResolveRelativeToURL(pp::Var(manifest_base_url_), 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relative_url); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resolved_url.is_string()) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_RESOLVE_URL, 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "could not resolve url '" + relative_url + 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "' relative to manifest base url '" + manifest_base_url_.c_str() + 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'."); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *full_url = resolved_url.AsString(); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::GetProgramURL(nacl::string* full_url, 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options, 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorInfo* error_info) const { 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (full_url == NULL || pnacl_options == NULL || error_info == NULL) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value program = dictionary_[kProgramKey]; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string nexe_url; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string error_string; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetURLFromISADictionary(program, 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kProgramKey, 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sandbox_isa_, 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &nexe_url, 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pnacl_options, 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error_info)) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ResolveURL(nexe_url, full_url, error_info); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::GetFileKeys(std::set<nacl::string>* keys) const { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dictionary_.isMember(kFilesKey)) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trivial success: no keys when there is no "files" section. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Json::Value& files = dictionary_[kFilesKey]; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(files.isObject()); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Json::Value::Members members = files.getMemberNames(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < members.size(); ++i) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keys->insert(members[i]); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JsonManifest::ResolveKey(const nacl::string& key, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string* full_url, 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PnaclOptions* pnacl_options, 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorInfo* error_info) const { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClLog(3, "JsonManifest::ResolveKey(%s)\n", key.c_str()); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // key must be one of kProgramKey or kFileKey '/' file-section-key 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (full_url == NULL || pnacl_options == NULL || error_info == NULL) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == kProgramKey) { 6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return GetKeyUrl(dictionary_, key, sandbox_isa_, this, full_url, 6247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) pnacl_options, error_info); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string::const_iterator p = find(key.begin(), key.end(), '/'); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p == key.end()) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("ResolveKey: invalid key, no slash: ") 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + key); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // generalize to permit other sections? 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string prefix(key.begin(), p); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefix != kFilesKey) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("ResolveKey: invalid key: not \"files\"" 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " prefix: ") + key); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string rest(p + 1, key.end()); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Json::Value& files = dictionary_[kFilesKey]; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!files.isObject()) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_RESOLVE_URL, 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("ResolveKey: no \"files\" dictionary")); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!files.isMember(rest)) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_info->SetReport( 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERROR_MANIFEST_RESOLVE_URL, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nacl::string("ResolveKey: no such \"files\" entry: ") + key); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return GetKeyUrl(files, rest, sandbox_isa_, this, full_url, pnacl_options, 6597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) error_info); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace plugin 663