This source file includes following definitions.
- GetBaseUrl
- IsPnaclComponent
- PnaclComponentURLToFilename
- GetPnaclFD
- WrapperForUrl
- ReadResourceInfo
- ReadResourceInfoError
- ParseResourceInfo
- GetFullUrl
- StartLoad
#include "ppapi/native_client/src/trusted/plugin/pnacl_resources.h"
#include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/native_client/src/trusted/plugin/file_utils.h"
#include "ppapi/native_client/src/trusted/plugin/manifest.h"
#include "ppapi/native_client/src/trusted/plugin/plugin.h"
#include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h"
#include "ppapi/native_client/src/trusted/plugin/utility.h"
#include "third_party/jsoncpp/source/include/json/reader.h"
#include "third_party/jsoncpp/source/include/json/value.h"
namespace plugin {
static const char kPnaclBaseUrl[] = "chrome://pnacl-translator/";
const char PnaclUrls::kResourceInfoUrl[] = "pnacl.json";
nacl::string PnaclUrls::GetBaseUrl() {
return nacl::string(kPnaclBaseUrl);
}
bool PnaclUrls::IsPnaclComponent(const nacl::string& full_url) {
return full_url.find(kPnaclBaseUrl, 0) == 0;
}
nacl::string PnaclUrls::PnaclComponentURLToFilename(
const nacl::string& full_url) {
nacl::string r = full_url.substr(nacl::string(kPnaclBaseUrl).length());
size_t replace_pos;
static const char* white_list = "abcdefghijklmnopqrstuvwxyz0123456789_";
replace_pos = r.find_first_not_of(white_list);
while(replace_pos != nacl::string::npos) {
r = r.replace(replace_pos, 1, "_");
replace_pos = r.find_first_not_of(white_list);
}
return r;
}
PnaclResources::~PnaclResources() {
for (std::map<nacl::string, nacl::DescWrapper*>::iterator
i = resource_wrappers_.begin(), e = resource_wrappers_.end();
i != e;
++i) {
delete i->second;
}
resource_wrappers_.clear();
}
int32_t PnaclResources::GetPnaclFD(Plugin* plugin, const char* filename) {
PP_FileHandle file_handle =
plugin->nacl_interface()->GetReadonlyPnaclFd(filename);
if (file_handle == PP_kInvalidFileHandle)
return -1;
#if NACL_WINDOWS
int32_t posix_desc = _open_osfhandle(reinterpret_cast<intptr_t>(file_handle),
_O_RDONLY | _O_BINARY);
if (posix_desc == -1) {
PLUGIN_PRINTF((
"PnaclResources::GetPnaclFD failed to convert HANDLE to posix\n"));
CloseHandle(file_handle);
}
return posix_desc;
#else
return file_handle;
#endif
}
nacl::DescWrapper* PnaclResources::WrapperForUrl(const nacl::string& url) {
CHECK(resource_wrappers_.find(url) != resource_wrappers_.end());
return resource_wrappers_[url];
}
void PnaclResources::ReadResourceInfo(
const nacl::string& resource_info_url,
const pp::CompletionCallback& resource_info_read_cb) {
PLUGIN_PRINTF(("PnaclResources::ReadResourceInfo\n"));
nacl::string full_url;
ErrorInfo error_info;
if (!manifest_->ResolveURL(resource_info_url, &full_url, &error_info)) {
ReadResourceInfoError(nacl::string("failed to resolve ") +
resource_info_url + ": " +
error_info.message() + ".");
return;
}
PLUGIN_PRINTF(("Resolved resources info url: %s\n", full_url.c_str()));
nacl::string resource_info_filename =
PnaclUrls::PnaclComponentURLToFilename(full_url);
PLUGIN_PRINTF(("Pnacl-converted resources info url: %s\n",
resource_info_filename.c_str()));
int32_t fd = GetPnaclFD(plugin_, resource_info_filename.c_str());
if (fd < 0) {
ReadResourceInfoError(
nacl::string("The Portable Native Client (pnacl) component is not "
"installed. Please consult chrome://components for more "
"information."));
return;
}
nacl::string json_buffer;
file_utils::StatusCode status = file_utils::SlurpFile(fd, json_buffer);
if (status != file_utils::PLUGIN_FILE_SUCCESS) {
ReadResourceInfoError(
nacl::string("PnaclResources::ReadResourceInfo reading "
"failed for: ") + resource_info_filename);
return;
}
PLUGIN_PRINTF(("Resource info JSON data:\n%s\n", json_buffer.c_str()));
nacl::string error_message;
if (!ParseResourceInfo(json_buffer, error_message)) {
ReadResourceInfoError(nacl::string("Parsing resource info failed: ") +
error_message + "\n");
return;
}
pp::Core* core = pp::Module::Get()->core();
core->CallOnMainThread(0, resource_info_read_cb, PP_OK);
}
void PnaclResources::ReadResourceInfoError(const nacl::string& msg) {
coordinator_->ReportNonPpapiError(PP_NACL_ERROR_PNACL_RESOURCE_FETCH, msg);
}
bool PnaclResources::ParseResourceInfo(const nacl::string& buf,
nacl::string& errmsg) {
Json::Reader json_reader;
Json::Value json_data;
if (!json_reader.parse(buf, json_data)) {
errmsg = nacl::string("JSON parse error: ") +
json_reader.getFormatedErrorMessages();
return false;
}
if (!json_data.isObject()) {
errmsg = nacl::string("Malformed JSON dictionary");
return false;
}
if (json_data.isMember("pnacl-llc-name")) {
Json::Value json_name = json_data["pnacl-llc-name"];
if (json_name.isString()) {
llc_tool_name = json_name.asString();
PLUGIN_PRINTF(("Set llc_tool_name=%s\n", llc_tool_name.c_str()));
}
}
if (json_data.isMember("pnacl-ld-name")) {
Json::Value json_name = json_data["pnacl-ld-name"];
if (json_name.isString()) {
ld_tool_name = json_name.asString();
PLUGIN_PRINTF(("Set ld_tool_name=%s\n", ld_tool_name.c_str()));
}
}
return true;
}
nacl::string PnaclResources::GetFullUrl(
const nacl::string& partial_url, const nacl::string& sandbox_arch) const {
nacl::string full_url;
ErrorInfo error_info;
const nacl::string& url_with_platform_prefix =
sandbox_arch + "/" + partial_url;
if (!manifest_->ResolveURL(url_with_platform_prefix,
&full_url,
&error_info)) {
PLUGIN_PRINTF(("PnaclResources::GetFullUrl failed: %s.\n",
error_info.message().c_str()));
return "";
}
return full_url;
}
void PnaclResources::StartLoad(
const pp::CompletionCallback& all_loaded_callback) {
PLUGIN_PRINTF(("PnaclResources::StartLoad\n"));
std::vector<nacl::string> resource_urls;
resource_urls.push_back(GetLlcUrl());
resource_urls.push_back(GetLdUrl());
PLUGIN_PRINTF(("PnaclResources::StartLoad -- local install of PNaCl.\n"));
int32_t result = PP_OK;
for (size_t i = 0; i < resource_urls.size(); ++i) {
nacl::string full_url = GetFullUrl(
resource_urls[i], plugin_->nacl_interface()->GetSandboxArch());
if (full_url == "") {
coordinator_->ReportNonPpapiError(
PP_NACL_ERROR_PNACL_RESOURCE_FETCH,
nacl::string("failed to resolve ") + resource_urls[i] + ".");
break;
}
nacl::string filename = PnaclUrls::PnaclComponentURLToFilename(full_url);
int32_t fd = PnaclResources::GetPnaclFD(plugin_, filename.c_str());
if (fd < 0) {
coordinator_->ReportNonPpapiError(
PP_NACL_ERROR_PNACL_RESOURCE_FETCH,
nacl::string("The Portable Native Client (pnacl) component is not "
"installed. Please consult chrome://components for more "
"information."));
result = PP_ERROR_FILENOTFOUND;
break;
} else {
resource_wrappers_[resource_urls[i]] =
plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
}
}
pp::Core* core = pp::Module::Get()->core();
core->CallOnMainThread(0, all_loaded_callback, result);
}
}