| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/renderer/nexe_load_manager.h" | 5 #include "components/nacl/renderer/nexe_load_manager.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_tokenizer.h" | 10 #include "base/strings/string_tokenizer.h" |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 82 |
| 83 NexeLoadManager::NexeLoadManager( | 83 NexeLoadManager::NexeLoadManager( |
| 84 PP_Instance pp_instance) | 84 PP_Instance pp_instance) |
| 85 : pp_instance_(pp_instance), | 85 : pp_instance_(pp_instance), |
| 86 nacl_ready_state_(PP_NACL_READY_STATE_UNSENT), | 86 nacl_ready_state_(PP_NACL_READY_STATE_UNSENT), |
| 87 nexe_error_reported_(false), | 87 nexe_error_reported_(false), |
| 88 is_installed_(false), | 88 is_installed_(false), |
| 89 exit_status_(-1), | 89 exit_status_(-1), |
| 90 nexe_size_(0), | 90 nexe_size_(0), |
| 91 plugin_instance_(content::PepperPluginInstance::Get(pp_instance)), | 91 plugin_instance_(content::PepperPluginInstance::Get(pp_instance)), |
| 92 crash_info_shmem_handle_(base::SharedMemory::NULLHandle()), |
| 92 weak_factory_(this) { | 93 weak_factory_(this) { |
| 93 SetLastError(""); | 94 SetLastError(""); |
| 94 HistogramEnumerateOsArch(GetSandboxArch()); | 95 HistogramEnumerateOsArch(GetSandboxArch()); |
| 95 if (plugin_instance_) { | 96 if (plugin_instance_) { |
| 96 plugin_base_url_ = | 97 plugin_base_url_ = |
| 97 plugin_instance_->GetContainer()->element().document().url(); | 98 plugin_instance_->GetContainer()->element().document().url(); |
| 98 } | 99 } |
| 99 } | 100 } |
| 100 | 101 |
| 101 NexeLoadManager::~NexeLoadManager() { | 102 NexeLoadManager::~NexeLoadManager() { |
| 102 if (!nexe_error_reported_) { | 103 if (!nexe_error_reported_) { |
| 103 base::TimeDelta uptime = base::Time::Now() - ready_time_; | 104 base::TimeDelta uptime = base::Time::Now() - ready_time_; |
| 104 HistogramTimeLarge("NaCl.ModuleUptime.Normal", uptime.InMilliseconds()); | 105 HistogramTimeLarge("NaCl.ModuleUptime.Normal", uptime.InMilliseconds()); |
| 105 } | 106 } |
| 107 if (base::SharedMemory::IsHandleValid(crash_info_shmem_handle_)) |
| 108 base::SharedMemory::CloseHandle(crash_info_shmem_handle_); |
| 106 } | 109 } |
| 107 | 110 |
| 108 void NexeLoadManager::NexeFileDidOpen(int32_t pp_error, | 111 void NexeLoadManager::NexeFileDidOpen(int32_t pp_error, |
| 109 const base::File& file, | 112 const base::File& file, |
| 110 int32_t http_status, | 113 int32_t http_status, |
| 111 int64_t nexe_bytes_read, | 114 int64_t nexe_bytes_read, |
| 112 const std::string& url, | 115 const std::string& url, |
| 113 base::TimeDelta time_since_open) { | 116 base::TimeDelta time_since_open) { |
| 114 // Check that we are on the main renderer thread. | 117 // Check that we are on the main renderer thread. |
| 115 DCHECK(content::RenderThread::Get()); | 118 DCHECK(content::RenderThread::Get()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 SetLastError(error_string); | 227 SetLastError(error_string); |
| 225 | 228 |
| 226 // Inform JavaScript that loading was aborted and is complete. | 229 // Inform JavaScript that loading was aborted and is complete. |
| 227 DispatchProgressEvent(pp_instance_, ProgressEvent(PP_NACL_EVENT_ABORT)); | 230 DispatchProgressEvent(pp_instance_, ProgressEvent(PP_NACL_EVENT_ABORT)); |
| 228 DispatchProgressEvent(pp_instance_, ProgressEvent(PP_NACL_EVENT_LOADEND)); | 231 DispatchProgressEvent(pp_instance_, ProgressEvent(PP_NACL_EVENT_LOADEND)); |
| 229 | 232 |
| 230 HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_ABORTED, is_installed_); | 233 HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_ABORTED, is_installed_); |
| 231 LogToConsole(error_string); | 234 LogToConsole(error_string); |
| 232 } | 235 } |
| 233 | 236 |
| 234 void NexeLoadManager::NexeDidCrash(const char* crash_log) { | 237 void NexeLoadManager::NexeDidCrash() { |
| 235 VLOG(1) << "Plugin::NexeDidCrash: crash event!"; | 238 VLOG(1) << "Plugin::NexeDidCrash: crash event!"; |
| 236 // The NaCl module voluntarily exited. However, this is still a | 239 // The NaCl module voluntarily exited. However, this is still a |
| 237 // crash from the point of view of Pepper, since PPAPI plugins are | 240 // crash from the point of view of Pepper, since PPAPI plugins are |
| 238 // event handlers and should never exit. | 241 // event handlers and should never exit. |
| 239 VLOG_IF(1, exit_status_ != -1) | 242 VLOG_IF(1, exit_status_ != -1) |
| 240 << "Plugin::NexeDidCrash: nexe exited with status " << exit_status_ | 243 << "Plugin::NexeDidCrash: nexe exited with status " << exit_status_ |
| 241 << " so this is a \"controlled crash\"."; | 244 << " so this is a \"controlled crash\"."; |
| 242 // If the crash occurs during load, we just want to report an error | 245 // If the crash occurs during load, we just want to report an error |
| 243 // that fits into our load progress event grammar. If the crash | 246 // that fits into our load progress event grammar. If the crash |
| 244 // occurs after loaded/loadend, then we use ReportDeadNexe to send a | 247 // occurs after loaded/loadend, then we use ReportDeadNexe to send a |
| 245 // "crash" event. | 248 // "crash" event. |
| 246 if (nexe_error_reported_) { | 249 if (nexe_error_reported_) { |
| 247 VLOG(1) << "Plugin::NexeDidCrash: error already reported; suppressing"; | 250 VLOG(1) << "Plugin::NexeDidCrash: error already reported; suppressing"; |
| 248 } else { | 251 } else { |
| 249 if (nacl_ready_state_ == PP_NACL_READY_STATE_DONE) { | 252 if (nacl_ready_state_ == PP_NACL_READY_STATE_DONE) { |
| 250 ReportDeadNexe(); | 253 ReportDeadNexe(); |
| 251 } else { | 254 } else { |
| 252 ReportLoadError(PP_NACL_ERROR_START_PROXY_CRASH, | 255 ReportLoadError(PP_NACL_ERROR_START_PROXY_CRASH, |
| 253 "Nexe crashed during startup"); | 256 "Nexe crashed during startup"); |
| 254 } | 257 } |
| 255 } | 258 } |
| 256 // In all cases, try to grab the crash log. The first error | 259 // In all cases, try to grab the crash log. The first error |
| 257 // reported may have come from the start_module RPC reply indicating | 260 // reported may have come from the start_module RPC reply indicating |
| 258 // a validation error or something similar, which wouldn't grab the | 261 // a validation error or something similar, which wouldn't grab the |
| 259 // crash log. In the event that this is called twice, the second | 262 // crash log. In the event that this is called twice, the second |
| 260 // invocation will just be a no-op, since the entire crash log will | 263 // invocation will just be a no-op, since the entire crash log will |
| 261 // have been received and we'll just get an EOF indication. | 264 // have been received and we'll just get an EOF indication. |
| 262 CopyCrashLogToJsConsole(crash_log); | 265 |
| 266 base::SharedMemory shmem(crash_info_shmem_handle_, true); |
| 267 if (shmem.Map(kNaClCrashInfoShmemSize)) { |
| 268 uint32_t crash_log_length; |
| 269 // We cast the length value to volatile here to prevent the compiler from |
| 270 // reordering instructions in a way that could introduce a TOCTTOU race. |
| 271 crash_log_length = *(static_cast<volatile uint32_t*>(shmem.memory())); |
| 272 crash_log_length = std::min<uint32_t>(crash_log_length, |
| 273 kNaClCrashInfoMaxLogSize); |
| 274 |
| 275 scoped_ptr<char[]> crash_log_data(new char[kNaClCrashInfoShmemSize]); |
| 276 memcpy(crash_log_data.get(), |
| 277 static_cast<char*>(shmem.memory()) + sizeof(uint32_t), |
| 278 crash_log_length); |
| 279 std::string crash_log(crash_log_data.get(), crash_log_length); |
| 280 CopyCrashLogToJsConsole(crash_log); |
| 281 } |
| 263 } | 282 } |
| 264 | 283 |
| 265 void NexeLoadManager::set_trusted_plugin_channel( | 284 void NexeLoadManager::set_trusted_plugin_channel( |
| 266 scoped_ptr<TrustedPluginChannel> channel) { | 285 scoped_ptr<TrustedPluginChannel> channel) { |
| 267 trusted_plugin_channel_ = channel.Pass(); | 286 trusted_plugin_channel_ = channel.Pass(); |
| 268 } | 287 } |
| 269 | 288 |
| 270 void NexeLoadManager::set_manifest_service_channel( | 289 void NexeLoadManager::set_manifest_service_channel( |
| 271 scoped_ptr<ManifestServiceChannel> channel) { | 290 scoped_ptr<ManifestServiceChannel> channel) { |
| 272 manifest_service_channel_ = channel.Pass(); | 291 manifest_service_channel_ = channel.Pass(); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 // to provide error handling. | 436 // to provide error handling. |
| 418 } | 437 } |
| 419 | 438 |
| 420 void NexeLoadManager::CopyCrashLogToJsConsole(const std::string& crash_log) { | 439 void NexeLoadManager::CopyCrashLogToJsConsole(const std::string& crash_log) { |
| 421 base::StringTokenizer t(crash_log, "\n"); | 440 base::StringTokenizer t(crash_log, "\n"); |
| 422 while (t.GetNext()) | 441 while (t.GetNext()) |
| 423 LogToConsole(t.token()); | 442 LogToConsole(t.token()); |
| 424 } | 443 } |
| 425 | 444 |
| 426 } // namespace nacl | 445 } // namespace nacl |
| OLD | NEW |