pnacl_resources.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "native_client/src/trusted/plugin/pnacl_resources.h" 6 7#include "native_client/src/include/portability_io.h" 8#include "native_client/src/shared/platform/nacl_check.h" 9#include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 10#include "native_client/src/trusted/plugin/manifest.h" 11#include "native_client/src/trusted/plugin/plugin.h" 12#include "native_client/src/trusted/plugin/pnacl_coordinator.h" 13#include "native_client/src/trusted/plugin/utility.h" 14 15#include "ppapi/c/pp_errors.h" 16 17namespace plugin { 18 19const char PnaclUrls::kExtensionOrigin[] = 20 "chrome-extension://gcodniebolpnpaiggndmcmmfpldlknih/"; 21const char PnaclUrls::kPnaclComponentID[] = 22 "pnacl-component://"; 23const char PnaclUrls::kLlcUrl[] = "llc"; 24const char PnaclUrls::kLdUrl[] = "ld"; 25 26bool PnaclUrls::UsePnaclExtension(const Plugin* plugin) { 27 // Use the chrome webstore extension for now, if --enable-pnacl is not 28 // explicitly requested. Eventually we will always behave as if 29 // --enable-pnacl is used and not use the chrome extension. 30 // Some UI work, etc. remains before --enable-pnacl is usable: 31 // http://code.google.com/p/nativeclient/issues/detail?id=2813 32 // TODO(jvoung): re-enable the non-extension path if we decide 33 // to use that / once we have renamed and remap some of the files. 34 return true; 35 // return !(plugin->nacl_interface()->IsPnaclEnabled()); 36} 37 38nacl::string PnaclUrls::GetBaseUrl(bool use_extension) { 39 if (use_extension) { 40 return nacl::string(kExtensionOrigin) + GetSandboxISA() + "/"; 41 } else { 42 return nacl::string(kPnaclComponentID) + GetSandboxISA() + "/"; 43 } 44} 45 46bool PnaclUrls::IsPnaclComponent(const nacl::string& full_url) { 47 return full_url.find(kPnaclComponentID, 0) == 0; 48} 49 50nacl::string PnaclUrls::StripPnaclComponentPrefix( 51 const nacl::string& full_url) { 52 return full_url.substr(nacl::string(kPnaclComponentID).length()); 53} 54 55////////////////////////////////////////////////////////////////////// 56 57PnaclResources::~PnaclResources() { 58 for (std::map<nacl::string, nacl::DescWrapper*>::iterator 59 i = resource_wrappers_.begin(), e = resource_wrappers_.end(); 60 i != e; 61 ++i) { 62 delete i->second; 63 } 64 resource_wrappers_.clear(); 65} 66 67// static 68int32_t PnaclResources::GetPnaclFD(Plugin* plugin, const char* filename) { 69 PP_FileHandle file_handle = 70 plugin->nacl_interface()->GetReadonlyPnaclFd(filename); 71 if (file_handle == PP_kInvalidFileHandle) 72 return -1; 73 74#if NACL_WINDOWS 75 //////// Now try the posix view. 76 int32_t posix_desc = _open_osfhandle(reinterpret_cast<intptr_t>(file_handle), 77 _O_RDONLY | _O_BINARY); 78 if (posix_desc == -1) { 79 PLUGIN_PRINTF(( 80 "PnaclResources::GetPnaclFD failed to convert HANDLE to posix\n")); 81 // Close the Windows HANDLE if it can't be converted. 82 CloseHandle(file_handle); 83 } 84 return posix_desc; 85#else 86 return file_handle; 87#endif 88} 89 90nacl::DescWrapper* PnaclResources::WrapperForUrl(const nacl::string& url) { 91 CHECK(resource_wrappers_.find(url) != resource_wrappers_.end()); 92 return resource_wrappers_[url]; 93} 94 95void PnaclResources::StartLoad() { 96 PLUGIN_PRINTF(("PnaclResources::StartLoad\n")); 97 98 CHECK(resource_urls_.size() > 0); 99 if (PnaclUrls::UsePnaclExtension(plugin_)) { 100 PLUGIN_PRINTF(("PnaclResources::StartLoad -- PNaCl chrome extension.\n")); 101 // Do a URL fetch. 102 // Create a counter (barrier) callback to track when all of the resources 103 // are loaded. 104 uint32_t resource_count = static_cast<uint32_t>(resource_urls_.size()); 105 delayed_callback_.reset( 106 new DelayedCallback(all_loaded_callback_, resource_count)); 107 108 // Schedule the downloads. 109 for (size_t i = 0; i < resource_urls_.size(); ++i) { 110 nacl::string full_url; 111 ErrorInfo error_info; 112 if (!manifest_->ResolveURL(resource_urls_[i], &full_url, &error_info)) { 113 coordinator_->ReportNonPpapiError(nacl::string("failed to resolve ") + 114 resource_urls_[i] + ": " + 115 error_info.message() + "."); 116 break; 117 } 118 pp::CompletionCallback ready_callback = 119 callback_factory_.NewCallback( 120 &PnaclResources::ResourceReady, 121 resource_urls_[i], 122 full_url); 123 if (!plugin_->StreamAsFile(full_url, 124 ready_callback.pp_completion_callback())) { 125 coordinator_->ReportNonPpapiError(nacl::string("failed to download ") + 126 resource_urls_[i] + "."); 127 break; 128 } 129 } 130 } else { 131 PLUGIN_PRINTF(("PnaclResources::StartLoad -- local install of PNaCl.\n")); 132 // Do a blocking load of each of the resources. 133 int32_t result = PP_OK; 134 for (size_t i = 0; i < resource_urls_.size(); ++i) { 135 const nacl::string& url = resource_urls_[i]; 136 nacl::string full_url; 137 ErrorInfo error_info; 138 if (!manifest_->ResolveURL(resource_urls_[i], &full_url, &error_info)) { 139 coordinator_->ReportNonPpapiError(nacl::string("failed to resolve ") + 140 url + ": " + 141 error_info.message() + "."); 142 break; 143 } 144 full_url = PnaclUrls::StripPnaclComponentPrefix(full_url); 145 146 int32_t fd = PnaclResources::GetPnaclFD(plugin_, full_url.c_str()); 147 if (fd < 0) { 148 coordinator_->ReportNonPpapiError( 149 nacl::string("PnaclLocalResources::StartLoad failed for: ") + 150 full_url); 151 result = PP_ERROR_FILENOTFOUND; 152 break; 153 } else { 154 resource_wrappers_[url] = 155 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY); 156 } 157 } 158 // We're done! Queue the callback. 159 pp::Core* core = pp::Module::Get()->core(); 160 core->CallOnMainThread(0, all_loaded_callback_, result); 161 } 162} 163 164void PnaclResources::ResourceReady(int32_t pp_error, 165 const nacl::string& url, 166 const nacl::string& full_url) { 167 PLUGIN_PRINTF(("PnaclResources::ResourceReady (pp_error=%" 168 NACL_PRId32", url=%s)\n", pp_error, url.c_str())); 169 // pp_error is checked by GetLoadedFileDesc. 170 int32_t fd = coordinator_->GetLoadedFileDesc(pp_error, 171 full_url, 172 "resource " + url); 173 if (fd < 0) { 174 coordinator_->ReportPpapiError(pp_error, 175 "PnaclResources::ResourceReady failed."); 176 } else { 177 resource_wrappers_[url] = 178 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY); 179 delayed_callback_->RunIfTime(); 180 } 181} 182 183} // namespace plugin 184