Index: components/nacl/renderer/ppb_nacl_private_impl.cc |
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc |
index 86889b7c231375381910fe5c4cfeb1d038cbe316..fd8dcc1bbc623126833849665fcd3e5705d364be 100644 |
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc |
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc |
@@ -11,6 +11,7 @@ |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/command_line.h" |
+#include "base/containers/scoped_ptr_hash_map.h" |
#include "base/cpu.h" |
#include "base/files/file.h" |
#include "base/lazy_instance.h" |
@@ -88,6 +89,8 @@ bool InitializePnaclResourceHost() { |
return true; |
} |
+// This contains state that is produced by LaunchSelLdr() and consumed |
+// by StartPpapiProxy(). |
struct InstanceInfo { |
InstanceInfo() : plugin_pid(base::kNullProcessId), plugin_child_id(0) {} |
GURL url; |
@@ -97,10 +100,39 @@ struct InstanceInfo { |
IPC::ChannelHandle channel_handle; |
}; |
-typedef std::map<PP_Instance, InstanceInfo> InstanceInfoMap; |
+class NaClPluginInstance { |
+ public: |
+ NaClPluginInstance(PP_Instance instance): nexe_load_manager(instance) {} |
+ |
+ NexeLoadManager nexe_load_manager; |
+ scoped_ptr<JsonManifest> json_manifest; |
+ scoped_ptr<InstanceInfo> instance_info; |
+}; |
+ |
+typedef base::ScopedPtrHashMap<PP_Instance, NaClPluginInstance> InstanceMap; |
+base::LazyInstance<InstanceMap> g_instance_map = LAZY_INSTANCE_INITIALIZER; |
+ |
+NaClPluginInstance* GetNaClPluginInstance(PP_Instance instance) { |
+ InstanceMap& map = g_instance_map.Get(); |
+ InstanceMap::iterator iter = map.find(instance); |
+ if (iter == map.end()) |
+ return NULL; |
+ return iter->second; |
+} |
-base::LazyInstance<InstanceInfoMap> g_instance_info = |
- LAZY_INSTANCE_INITIALIZER; |
+NexeLoadManager* GetNexeLoadManager(PP_Instance instance) { |
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
+ if (!nacl_plugin_instance) |
+ return NULL; |
+ return &nacl_plugin_instance->nexe_load_manager; |
+} |
+ |
+JsonManifest* GetJsonManifest(PP_Instance instance) { |
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
+ if (!nacl_plugin_instance) |
+ return NULL; |
+ return nacl_plugin_instance->json_manifest.get(); |
+} |
static const PP_NaClFileInfo kInvalidNaClFileInfo = { |
PP_kInvalidFileHandle, |
@@ -169,7 +201,7 @@ class ManifestServiceProxy : public ManifestServiceChannel::Delegate { |
void StartupInitializationComplete() override { |
if (StartPpapiProxy(pp_instance_) == PP_TRUE) { |
JsonManifest* manifest = GetJsonManifest(pp_instance_); |
- NexeLoadManager* load_manager = NexeLoadManager::Get(pp_instance_); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(pp_instance_); |
if (load_manager && manifest) { |
std::string full_url; |
PP_PNaClOptions pnacl_options; |
@@ -376,7 +408,7 @@ void LaunchSelLdr(PP_Instance instance, |
return; |
} |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) { |
PostPPCompletionCallback(callback, PP_ERROR_FAILED); |
@@ -403,8 +435,10 @@ void LaunchSelLdr(PP_Instance instance, |
instance_info.plugin_child_id = launch_result.plugin_child_id; |
// Don't save instance_info if channel handle is invalid. |
- if (IsValidChannelHandle(instance_info.channel_handle)) |
- g_instance_info.Get()[instance] = instance_info; |
+ if (IsValidChannelHandle(instance_info.channel_handle)) { |
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
+ nacl_plugin_instance->instance_info.reset(new InstanceInfo(instance_info)); |
+ } |
*(static_cast<NaClHandle*>(imc_handle)) = ToNativeHandle(result_socket); |
@@ -452,7 +486,7 @@ void LaunchSelLdr(PP_Instance instance, |
} |
PP_Bool StartPpapiProxy(PP_Instance instance) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) |
return PP_FALSE; |
@@ -464,21 +498,20 @@ PP_Bool StartPpapiProxy(PP_Instance instance) { |
return PP_FALSE; |
} |
- InstanceInfoMap& map = g_instance_info.Get(); |
- InstanceInfoMap::iterator it = map.find(instance); |
- if (it == map.end()) { |
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
+ if (!nacl_plugin_instance->instance_info) { |
DLOG(ERROR) << "Could not find instance ID"; |
return PP_FALSE; |
} |
- InstanceInfo instance_info = it->second; |
- map.erase(it); |
+ scoped_ptr<InstanceInfo> instance_info = |
+ nacl_plugin_instance->instance_info.Pass(); |
PP_ExternalPluginResult result = plugin_instance->SwitchToOutOfProcessProxy( |
- base::FilePath().AppendASCII(instance_info.url.spec()), |
- instance_info.permissions, |
- instance_info.channel_handle, |
- instance_info.plugin_pid, |
- instance_info.plugin_child_id); |
+ base::FilePath().AppendASCII(instance_info->url.spec()), |
+ instance_info->permissions, |
+ instance_info->channel_handle, |
+ instance_info->plugin_pid, |
+ instance_info->plugin_child_id); |
if (result == PP_EXTERNAL_PLUGIN_OK) { |
// Log the amound of time that has passed between the trusted plugin being |
@@ -644,7 +677,7 @@ void ReportTranslationFinished(PP_Instance instance, |
compile_time_us); |
HistogramSizeKB("NaCl.Perf.Size.Pexe", pexe_size / 1024); |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) { |
base::TimeDelta total_time = base::Time::Now() - |
load_manager->pnacl_start_time(); |
@@ -672,7 +705,7 @@ PP_FileHandle OpenNaClExecutable(PP_Instance instance, |
if (!gurl.SchemeIs("chrome-extension")) |
return PP_kInvalidFileHandle; |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) |
return PP_kInvalidFileHandle; |
@@ -729,7 +762,7 @@ void DispatchEvent(PP_Instance instance, |
void ReportLoadSuccess(PP_Instance instance, |
uint64_t loaded_bytes, |
uint64_t total_bytes) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) { |
load_manager->ReportLoadSuccess(load_manager->program_url(), |
loaded_bytes, |
@@ -740,18 +773,29 @@ void ReportLoadSuccess(PP_Instance instance, |
void ReportLoadError(PP_Instance instance, |
PP_NaClError error, |
const char* error_message) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) |
load_manager->ReportLoadError(error, error_message); |
} |
void InstanceCreated(PP_Instance instance) { |
- NexeLoadManager::Create(instance); |
+ InstanceMap& map = g_instance_map.Get(); |
+ CHECK(map.find(instance) == map.end()); // Sanity check. |
+ scoped_ptr<NaClPluginInstance> new_instance(new NaClPluginInstance(instance)); |
+ map.add(instance, new_instance.Pass()); |
} |
void InstanceDestroyed(PP_Instance instance) { |
- DeleteJsonManifest(instance); |
- NexeLoadManager::Delete(instance); |
+ InstanceMap& map = g_instance_map.Get(); |
+ InstanceMap::iterator iter = map.find(instance); |
+ CHECK(iter != map.end()); |
+ // The erase may call NexeLoadManager's destructor prior to removing it from |
+ // the map. In that case, it is possible for the trusted Plugin to re-enter |
+ // the NexeLoadManager (e.g., by calling ReportLoadError). Passing out the |
+ // NexeLoadManager to a local scoped_ptr just ensures that its entry is gone |
+ // from the map prior to the destructor being invoked. |
+ scoped_ptr<NaClPluginInstance> temp(map.take(instance)); |
+ map.erase(iter); |
} |
PP_Bool NaClDebugEnabledForURL(const char* alleged_nmf_url) { |
@@ -775,7 +819,7 @@ void InitializePlugin(PP_Instance instance, |
uint32_t argc, |
const char* argn[], |
const char* argv[]) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (load_manager) |
load_manager->InitializePlugin(argc, argn, argv); |
@@ -790,7 +834,7 @@ bool CreateJsonManifest(PP_Instance instance, |
void RequestNaClManifest(PP_Instance instance, |
PP_CompletionCallback callback) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) { |
ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
@@ -837,7 +881,7 @@ void RequestNaClManifest(PP_Instance instance, |
} |
PP_Var GetManifestBaseURL(PP_Instance instance) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) |
return PP_MakeUndefined(); |
@@ -848,13 +892,13 @@ PP_Var GetManifestBaseURL(PP_Instance instance) { |
} |
void ProcessNaClManifest(PP_Instance instance, const char* program_url) { |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) |
load_manager->ProcessNaClManifest(program_url); |
} |
PP_Bool DevInterfacesEnabled(PP_Instance instance) { |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) |
return PP_FromBool(load_manager->DevInterfacesEnabled()); |
return PP_FALSE; |
@@ -868,7 +912,7 @@ void DownloadManifestToBufferCompletion(PP_Instance instance, |
void DownloadManifestToBuffer(PP_Instance instance, |
struct PP_CompletionCallback callback) { |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
content::PepperPluginInstance* plugin_instance = |
content::PepperPluginInstance::Get(instance); |
@@ -904,7 +948,7 @@ void DownloadManifestToBufferCompletion(PP_Instance instance, |
HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload", |
download_time.InMilliseconds()); |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (!load_manager) { |
callback.func(callback.user_data, PP_ERROR_ABORTED); |
return; |
@@ -951,7 +995,7 @@ bool CreateJsonManifest(PP_Instance instance, |
HistogramSizeKB("NaCl.Perf.Size.Manifest", |
static_cast<int32_t>(manifest_data.length() / 1024)); |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (!load_manager) |
return false; |
@@ -969,7 +1013,7 @@ bool CreateJsonManifest(PP_Instance instance, |
PP_ToBool(NaClDebugEnabledForURL(manifest_url.c_str())))); |
JsonManifest::ErrorInfo error_info; |
if (j->Init(manifest_data.c_str(), &error_info)) { |
- AddJsonManifest(instance, j.Pass()); |
+ GetNaClPluginInstance(instance)->json_manifest.reset(j.release()); |
return true; |
} |
load_manager->ReportLoadError(error_info.error, error_info.string); |
@@ -980,7 +1024,7 @@ PP_Bool ManifestGetProgramURL(PP_Instance instance, |
PP_Var* pp_full_url, |
PP_PNaClOptions* pnacl_options, |
PP_Bool* pp_uses_nonsfi_mode) { |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
JsonManifest* manifest = GetJsonManifest(instance); |
if (manifest == NULL) |
@@ -1013,7 +1057,7 @@ bool ManifestResolveKey(PP_Instance instance, |
// We can only resolve keys in the files/ namespace. |
const std::string kFilesPrefix = "files/"; |
if (key.find(kFilesPrefix) == std::string::npos) { |
- nacl::NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) |
load_manager->ReportLoadError(PP_NACL_ERROR_MANIFEST_RESOLVE_URL, |
"key did not start with files/"); |
@@ -1036,7 +1080,7 @@ PP_Bool GetPNaClResourceInfo(PP_Instance instance, |
PP_Var* llc_tool_name, |
PP_Var* ld_tool_name) { |
static const char kFilename[] = "chrome://pnacl-translator/pnacl.json"; |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) |
return PP_FALSE; |
@@ -1249,7 +1293,7 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request, |
base::TimeDelta download_time = base::Time::Now() - request.start_time; |
- NexeLoadManager* load_manager = NexeLoadManager::Get(request.instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(request.instance); |
if (load_manager) { |
load_manager->NexeFileDidOpen(pp_error, |
target_file, |
@@ -1291,7 +1335,7 @@ void DownloadFile(PP_Instance instance, |
DCHECK(ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()-> |
BelongsToCurrentThread()); |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) { |
base::MessageLoop::current()->PostTask( |
@@ -1391,7 +1435,7 @@ void ReportSelLdrStatus(PP_Instance instance, |
int32_t load_status, |
int32_t max_status) { |
HistogramEnumerate("NaCl.LoadStatus.SelLdr", load_status, max_status); |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
if (!load_manager) |
return; |
@@ -1446,7 +1490,7 @@ void OpenManifestEntry(PP_Instance instance, |
} |
void SetPNaClStartTime(PP_Instance instance) { |
- NexeLoadManager* load_manager = NexeLoadManager::Get(instance); |
+ NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
if (load_manager) |
load_manager->set_pnacl_start_time(base::Time::Now()); |
} |