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 |
355 // Initialization succeeded, so keep the plugin DLL loaded. | 363 // Initialization succeeded, so keep the plugin DLL loaded. |
356 library_.Reset(library.Release()); | 364 library_.Reset(library.Release()); |
| 365 |
| 366 ReportLoadResult(path, LOAD_SUCCESS); |
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. |
365 !SetupRendererChannel(renderer_pid, renderer_child_id, incognito, | 375 !SetupRendererChannel(renderer_pid, renderer_child_id, incognito, |
366 &channel_handle)) { | 376 &channel_handle)) { |
(...skipping 85 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 |