Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/ppapi_plugin/ppapi_thread.h" | 5 #include "content/ppapi_plugin/ppapi_thread.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/crash_logging.h" | 10 #include "base/debug/crash_logging.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram.h" | |
| 12 #include "base/process_util.h" | 13 #include "base/process_util.h" |
| 13 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 14 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
| 15 #include "base/threading/platform_thread.h" | 16 #include "base/threading/platform_thread.h" |
| 16 #include "base/time.h" | 17 #include "base/time.h" |
| 17 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
| 18 #include "content/common/child_process.h" | 19 #include "content/common/child_process.h" |
| 19 #include "content/common/child_process_messages.h" | 20 #include "content/common/child_process_messages.h" |
| 20 #include "content/common/sandbox_util.h" | 21 #include "content/common/sandbox_util.h" |
| 21 #include "content/ppapi_plugin/broker_process_dispatcher.h" | 22 #include "content/ppapi_plugin/broker_process_dispatcher.h" |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 | 253 |
| 253 // If the plugin isn't internal then load it from |path|. | 254 // If the plugin isn't internal then load it from |path|. |
| 254 base::ScopedNativeLibrary library; | 255 base::ScopedNativeLibrary library; |
| 255 if (plugin_entry_points_.initialize_module == NULL) { | 256 if (plugin_entry_points_.initialize_module == NULL) { |
| 256 // Load the plugin from the specified library. | 257 // Load the plugin from the specified library. |
| 257 std::string error; | 258 std::string error; |
| 258 library.Reset(base::LoadNativeLibrary(path, &error)); | 259 library.Reset(base::LoadNativeLibrary(path, &error)); |
| 259 if (!library.is_valid()) { | 260 if (!library.is_valid()) { |
| 260 LOG(ERROR) << "Failed to load Pepper module from " | 261 LOG(ERROR) << "Failed to load Pepper module from " |
| 261 << path.value() << " (error: " << error << ")"; | 262 << path.value() << " (error: " << error << ")"; |
| 263 ReportLoadResult(path, LOAD_FAILED); | |
| 262 return; | 264 return; |
| 263 } | 265 } |
| 264 | 266 |
| 265 // Get the GetInterface function (required). | 267 // Get the GetInterface function (required). |
| 266 plugin_entry_points_.get_interface = | 268 plugin_entry_points_.get_interface = |
| 267 reinterpret_cast<PP_GetInterface_Func>( | 269 reinterpret_cast<PP_GetInterface_Func>( |
| 268 library.GetFunctionPointer("PPP_GetInterface")); | 270 library.GetFunctionPointer("PPP_GetInterface")); |
| 269 if (!plugin_entry_points_.get_interface) { | 271 if (!plugin_entry_points_.get_interface) { |
| 270 LOG(WARNING) << "No PPP_GetInterface in plugin library"; | 272 LOG(WARNING) << "No PPP_GetInterface in plugin library"; |
| 273 ReportLoadResult(path, ENTRY_POINT_MISSING); | |
| 271 return; | 274 return; |
| 272 } | 275 } |
| 273 | 276 |
| 274 // The ShutdownModule/ShutdownBroker function is optional. | 277 // The ShutdownModule/ShutdownBroker function is optional. |
| 275 plugin_entry_points_.shutdown_module = | 278 plugin_entry_points_.shutdown_module = |
| 276 is_broker_ ? | 279 is_broker_ ? |
| 277 reinterpret_cast<PP_ShutdownModule_Func>( | 280 reinterpret_cast<PP_ShutdownModule_Func>( |
| 278 library.GetFunctionPointer("PPP_ShutdownBroker")) : | 281 library.GetFunctionPointer("PPP_ShutdownBroker")) : |
| 279 reinterpret_cast<PP_ShutdownModule_Func>( | 282 reinterpret_cast<PP_ShutdownModule_Func>( |
| 280 library.GetFunctionPointer("PPP_ShutdownModule")); | 283 library.GetFunctionPointer("PPP_ShutdownModule")); |
| 281 | 284 |
| 282 if (!is_broker_) { | 285 if (!is_broker_) { |
| 283 // Get the InitializeModule function (required for non-broker code). | 286 // Get the InitializeModule function (required for non-broker code). |
| 284 plugin_entry_points_.initialize_module = | 287 plugin_entry_points_.initialize_module = |
| 285 reinterpret_cast<PP_InitializeModule_Func>( | 288 reinterpret_cast<PP_InitializeModule_Func>( |
| 286 library.GetFunctionPointer("PPP_InitializeModule")); | 289 library.GetFunctionPointer("PPP_InitializeModule")); |
| 287 if (!plugin_entry_points_.initialize_module) { | 290 if (!plugin_entry_points_.initialize_module) { |
| 288 LOG(WARNING) << "No PPP_InitializeModule in plugin library"; | 291 LOG(WARNING) << "No PPP_InitializeModule in plugin library"; |
| 292 ReportLoadResult(path, ENTRY_POINT_MISSING); | |
| 289 return; | 293 return; |
| 290 } | 294 } |
| 291 } | 295 } |
| 292 } | 296 } |
| 293 | 297 |
| 294 #if defined(OS_WIN) | 298 #if defined(OS_WIN) |
| 295 // If code subsequently tries to exit using abort(), force a crash (since | 299 // If code subsequently tries to exit using abort(), force a crash (since |
| 296 // otherwise these would be silent terminations and fly under the radar). | 300 // otherwise these would be silent terminations and fly under the radar). |
| 297 base::win::SetAbortBehaviorForCrashReporting(); | 301 base::win::SetAbortBehaviorForCrashReporting(); |
| 298 if (permissions.HasPermission(ppapi::PERMISSION_FLASH)) { | 302 if (permissions.HasPermission(ppapi::PERMISSION_FLASH)) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 316 } | 320 } |
| 317 #endif | 321 #endif |
| 318 | 322 |
| 319 if (is_broker_) { | 323 if (is_broker_) { |
| 320 // Get the InitializeBroker function (required). | 324 // Get the InitializeBroker function (required). |
| 321 InitializeBrokerFunc init_broker = | 325 InitializeBrokerFunc init_broker = |
| 322 reinterpret_cast<InitializeBrokerFunc>( | 326 reinterpret_cast<InitializeBrokerFunc>( |
| 323 library.GetFunctionPointer("PPP_InitializeBroker")); | 327 library.GetFunctionPointer("PPP_InitializeBroker")); |
| 324 if (!init_broker) { | 328 if (!init_broker) { |
| 325 LOG(WARNING) << "No PPP_InitializeBroker in plugin library"; | 329 LOG(WARNING) << "No PPP_InitializeBroker in plugin library"; |
| 330 ReportLoadResult(path, ENTRY_POINT_MISSING); | |
| 326 return; | 331 return; |
| 327 } | 332 } |
| 328 | 333 |
| 329 int32_t init_error = init_broker(&connect_instance_func_); | 334 int32_t init_error = init_broker(&connect_instance_func_); |
| 330 if (init_error != PP_OK) { | 335 if (init_error != PP_OK) { |
| 331 LOG(WARNING) << "InitBroker failed with error " << init_error; | 336 LOG(WARNING) << "InitBroker failed with error " << init_error; |
| 337 ReportLoadResult(path, INIT_FAILED); | |
| 332 return; | 338 return; |
| 333 } | 339 } |
| 334 if (!connect_instance_func_) { | 340 if (!connect_instance_func_) { |
| 335 LOG(WARNING) << "InitBroker did not provide PP_ConnectInstance_Func"; | 341 LOG(WARNING) << "InitBroker did not provide PP_ConnectInstance_Func"; |
| 342 ReportLoadResult(path, INIT_FAILED); | |
| 336 return; | 343 return; |
| 337 } | 344 } |
| 338 } else { | 345 } else { |
| 339 #if defined(OS_MACOSX) | 346 #if defined(OS_MACOSX) |
| 340 // We need to do this after getting |PPP_GetInterface()| (or presumably | 347 // We need to do this after getting |PPP_GetInterface()| (or presumably |
| 341 // doing something nontrivial with the library), else the sandbox | 348 // doing something nontrivial with the library), else the sandbox |
| 342 // intercedes. | 349 // intercedes. |
| 343 CHECK(InitializeSandbox()); | 350 CHECK(InitializeSandbox()); |
| 344 #endif | 351 #endif |
| 345 | 352 |
| 346 int32_t init_error = plugin_entry_points_.initialize_module( | 353 int32_t init_error = plugin_entry_points_.initialize_module( |
| 347 local_pp_module_, | 354 local_pp_module_, |
| 348 &ppapi::proxy::PluginDispatcher::GetBrowserInterface); | 355 &ppapi::proxy::PluginDispatcher::GetBrowserInterface); |
| 349 if (init_error != PP_OK) { | 356 if (init_error != PP_OK) { |
| 350 LOG(WARNING) << "InitModule failed with error " << init_error; | 357 LOG(WARNING) << "InitModule failed with error " << init_error; |
| 358 ReportLoadResult(path, INIT_FAILED); | |
| 351 return; | 359 return; |
| 352 } | 360 } |
| 353 } | 361 } |
| 354 | 362 |
| 363 ReportLoadResult(path, LOAD_SUCCESS); | |
|
ddorwin
2013/04/15 20:54:50
nit: I meant this should probably be the last line
xhwang
2013/04/15 20:56:46
Done.
| |
| 364 | |
| 355 // Initialization succeeded, so keep the plugin DLL loaded. | 365 // Initialization succeeded, so keep the plugin DLL loaded. |
| 356 library_.Reset(library.Release()); | 366 library_.Reset(library.Release()); |
| 357 } | 367 } |
| 358 | 368 |
| 359 void PpapiThread::OnCreateChannel(base::ProcessId renderer_pid, | 369 void PpapiThread::OnCreateChannel(base::ProcessId renderer_pid, |
| 360 int renderer_child_id, | 370 int renderer_child_id, |
| 361 bool incognito) { | 371 bool incognito) { |
| 362 IPC::ChannelHandle channel_handle; | 372 IPC::ChannelHandle channel_handle; |
| 363 | 373 |
| 364 if (!plugin_entry_points_.get_interface || // Plugin couldn't be loaded. | 374 if (!plugin_entry_points_.get_interface || // Plugin couldn't be loaded. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 | 462 |
| 453 // From here, the dispatcher will manage its own lifetime according to the | 463 // From here, the dispatcher will manage its own lifetime according to the |
| 454 // lifetime of the attached channel. | 464 // lifetime of the attached channel. |
| 455 return true; | 465 return true; |
| 456 } | 466 } |
| 457 | 467 |
| 458 void PpapiThread::SavePluginName(const base::FilePath& path) { | 468 void PpapiThread::SavePluginName(const base::FilePath& path) { |
| 459 ppapi::proxy::PluginGlobals::Get()->set_plugin_name( | 469 ppapi::proxy::PluginGlobals::Get()->set_plugin_name( |
| 460 path.BaseName().AsUTF8Unsafe()); | 470 path.BaseName().AsUTF8Unsafe()); |
| 461 | 471 |
| 462 // plugin() is NULL when in-process. Which is fine, because this is | 472 // plugin() is NULL when in-process, which is fine, because this is |
| 463 // just a hook for setting the process name. | 473 // just a hook for setting the process name. |
| 464 if (GetContentClient()->plugin()) { | 474 if (GetContentClient()->plugin()) { |
| 465 GetContentClient()->plugin()->PluginProcessStarted( | 475 GetContentClient()->plugin()->PluginProcessStarted( |
| 466 path.BaseName().RemoveExtension().LossyDisplayName()); | 476 path.BaseName().RemoveExtension().LossyDisplayName()); |
| 467 } | 477 } |
| 468 } | 478 } |
| 469 | 479 |
| 480 void PpapiThread::ReportLoadResult(const base::FilePath& path, | |
| 481 LoadResult result) { | |
| 482 DCHECK_LT(result, LOAD_RESULT_MAX); | |
| 483 | |
| 484 std::ostringstream histogram_name; | |
| 485 histogram_name << "Plugin.Ppapi" << (is_broker_ ? "Broker" : "Plugin") | |
| 486 << "LoadResult." << path.BaseName().MaybeAsASCII(); | |
| 487 | |
| 488 // Note: This leaks memory, which is expected behavior. | |
| 489 base::HistogramBase* histogram = | |
| 490 base::LinearHistogram::FactoryGet( | |
| 491 histogram_name.str(), | |
| 492 1, | |
| 493 LOAD_RESULT_MAX, | |
| 494 LOAD_RESULT_MAX + 1, | |
| 495 base::HistogramBase::kUmaTargetedHistogramFlag); | |
| 496 | |
| 497 histogram->Add(result); | |
| 498 } | |
| 499 | |
| 470 } // namespace content | 500 } // namespace content |
| OLD | NEW |