#include <limits>
#include "base/command_line.h"
+#include "base/cpu.h"
#include "base/debug/crash_logging.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/sandbox_util.h"
#include "content/ppapi_plugin/broker_process_dispatcher.h"
#include "content/ppapi_plugin/plugin_process_dispatcher.h"
-#include "content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h"
+#include "content/ppapi_plugin/ppapi_blink_platform_impl.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/interface_list.h"
#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/plugin_message_filter.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/shared_impl/api_id.h"
+#include "ppapi/proxy/resource_reply_thread_registrar.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "ui/base/ui_base_switches.h"
#endif
#if defined(OS_WIN)
+const char kWidevineCdmAdapterFileName[] = "widevinecdmadapter.dll";
+
extern sandbox::TargetServices* g_target_services;
+
+// Used by EnumSystemLocales for warming up.
+static BOOL CALLBACK EnumLocalesProc(LPTSTR lpLocaleString) {
+ return TRUE;
+}
+
+static BOOL CALLBACK EnumLocalesProcEx(
+ LPWSTR lpLocaleString,
+ DWORD dwFlags,
+ LPARAM lParam) {
+ return TRUE;
+}
+
+// Warm up language subsystems before the sandbox is turned on.
+static void WarmupWindowsLocales(const ppapi::PpapiPermissions& permissions) {
+ ::GetUserDefaultLangID();
+ ::GetUserDefaultLCID();
+
+ if (permissions.HasPermission(ppapi::PERMISSION_FLASH)) {
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ typedef BOOL (WINAPI *PfnEnumSystemLocalesEx)
+ (LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
+
+ HMODULE handle_kern32 = GetModuleHandleW(L"Kernel32.dll");
+ PfnEnumSystemLocalesEx enum_sys_locales_ex =
+ reinterpret_cast<PfnEnumSystemLocalesEx>
+ (GetProcAddress(handle_kern32, "EnumSystemLocalesEx"));
+
+ enum_sys_locales_ex(EnumLocalesProcEx, LOCALE_WINDOWS, 0, 0);
+ } else {
+ EnumSystemLocalesW(EnumLocalesProc, LCID_INSTALLED);
+ }
+ }
+}
#else
extern void* g_target_services;
#endif
typedef int32_t (*InitializeBrokerFunc)
(PP_ConnectInstance_Func* connect_instance_func);
-PpapiThread::DispatcherMessageListener::DispatcherMessageListener(
- PpapiThread* owner) : owner_(owner) {
-}
-
-PpapiThread::DispatcherMessageListener::~DispatcherMessageListener() {
-}
-
-bool PpapiThread::DispatcherMessageListener::OnMessageReceived(
- const IPC::Message& msg) {
- // The first parameter should be a plugin dispatcher ID.
- PickleIterator iter(msg);
- uint32 id = 0;
- if (!msg.ReadUInt32(&iter, &id)) {
- NOTREACHED();
- return false;
- }
- std::map<uint32, ppapi::proxy::PluginDispatcher*>::iterator dispatcher =
- owner_->plugin_dispatchers_.find(id);
- if (dispatcher != owner_->plugin_dispatchers_.end())
- return dispatcher->second->OnMessageReceived(msg);
-
- return false;
-}
-
PpapiThread::PpapiThread(const CommandLine& command_line, bool is_broker)
: is_broker_(is_broker),
connect_instance_func_(NULL),
local_pp_module_(
base::RandInt(0, std::numeric_limits<PP_Module>::max())),
- next_plugin_dispatcher_id_(1),
- dispatcher_message_listener_(this) {
+ next_plugin_dispatcher_id_(1) {
ppapi::proxy::PluginGlobals* globals = ppapi::proxy::PluginGlobals::Get();
- globals->set_plugin_proxy_delegate(this);
+ globals->SetPluginProxyDelegate(this);
globals->set_command_line(
command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
- webkit_platform_support_.reset(new PpapiWebKitPlatformSupportImpl);
- WebKit::initialize(webkit_platform_support_.get());
+ blink_platform_impl_.reset(new PpapiBlinkPlatformImpl);
+ blink::initialize(blink_platform_impl_.get());
- // Register interfaces that expect messages from the browser process. Please
- // note that only those InterfaceProxy-based ones require registration.
- AddRoute(ppapi::API_ID_PPB_HOSTRESOLVER_PRIVATE,
- &dispatcher_message_listener_);
+ if (!is_broker_) {
+ channel()->AddFilter(
+ new ppapi::proxy::PluginMessageFilter(
+ NULL, globals->resource_reply_thread_registrar()));
+ }
}
PpapiThread::~PpapiThread() {
}
void PpapiThread::Shutdown() {
- ppapi::proxy::PluginGlobals::Get()->set_plugin_proxy_delegate(NULL);
+ ChildThread::Shutdown();
+
+ ppapi::proxy::PluginGlobals::Get()->ResetPluginProxyDelegate();
if (plugin_entry_points_.shutdown_module)
plugin_entry_points_.shutdown_module();
- WebKit::shutdown();
+ blink_platform_impl_->Shutdown();
+ blink::shutdown();
}
bool PpapiThread::Send(IPC::Message* msg) {
IPC_MESSAGE_HANDLER(PpapiMsg_SetNetworkState, OnSetNetworkState)
IPC_MESSAGE_HANDLER(PpapiMsg_Crash, OnCrash)
IPC_MESSAGE_HANDLER(PpapiMsg_Hang, OnHang)
- IPC_MESSAGE_HANDLER(PpapiPluginMsg_ResourceReply, OnResourceReply)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
#if defined(OS_WIN)
if (peer_handle_.IsValid()) {
DCHECK(is_broker_);
- return IPC::GetFileHandleForProcess(handle, peer_handle_,
+ return IPC::GetFileHandleForProcess(handle, peer_handle_.Get(),
should_close_source);
}
#endif
base::ScopedNativeLibrary library;
if (plugin_entry_points_.initialize_module == NULL) {
// Load the plugin from the specified library.
- std::string error;
+ base::NativeLibraryLoadError error;
library.Reset(base::LoadNativeLibrary(path, &error));
if (!library.is_valid()) {
- LOG(ERROR) << "Failed to load Pepper module from "
- << path.value() << " (error: " << error << ")";
+ LOG(ERROR) << "Failed to load Pepper module from " << path.value()
+ << " (error: " << error.ToString() << ")";
+ if (!base::PathExists(path)) {
+ ReportLoadResult(path, FILE_MISSING);
+ return;
+ }
ReportLoadResult(path, LOAD_FAILED);
+ // Report detailed reason for load failure.
+ ReportLoadErrorCode(path, error);
return;
}
// can be loaded. TODO(cpu): consider changing to the loading style of
// regular plugins.
if (g_target_services) {
- // Let Flash load DRM before lockdown on Vista+.
- if (permissions.HasPermission(ppapi::PERMISSION_FLASH) &&
- base::win::OSInfo::GetInstance()->version() >=
- base::win::VERSION_VISTA ) {
- LoadLibrary(L"dxva2.dll");
+ // Let Flash and Widevine CDM adapter load DXVA before lockdown on Vista+.
+ if (permissions.HasPermission(ppapi::PERMISSION_FLASH) ||
+ path.BaseName().MaybeAsASCII() == kWidevineCdmAdapterFileName) {
+ if (base::win::OSInfo::GetInstance()->version() >=
+ base::win::VERSION_VISTA) {
+ LoadLibraryA("dxva2.dll");
+ }
+ }
+
+ if (permissions.HasPermission(ppapi::PERMISSION_FLASH)) {
+ if (base::win::OSInfo::GetInstance()->version() >=
+ base::win::VERSION_WIN7) {
+ base::CPU cpu;
+ if (cpu.vendor_name() == "AuthenticAMD") {
+ // The AMD crypto acceleration is only AMD Bulldozer and above.
+#if defined(_WIN64)
+ LoadLibraryA("amdhcp64.dll");
+#else
+ LoadLibraryA("amdhcp32.dll");
+#endif
+ }
+ }
}
// Cause advapi32 to load before the sandbox is turned on.
unsigned int dummy_rand;
rand_s(&dummy_rand);
- // Warm up language subsystems before the sandbox is turned on.
- ::GetUserDefaultLangID();
- ::GetUserDefaultLCID();
+
+ WarmupWindowsLocales(permissions);
g_target_services->LowerToken();
}
Send(new PpapiHostMsg_ChannelCreated(channel_handle));
}
-void PpapiThread::OnResourceReply(
- const ppapi::proxy::ResourceMessageReplyParams& reply_params,
- const IPC::Message& nested_msg) {
- ppapi::proxy::PluginDispatcher::DispatchResourceReply(reply_params,
- nested_msg);
-}
-
void PpapiThread::OnSetNetworkState(bool online) {
// Note the browser-process side shouldn't send us these messages in the
// first unless the plugin has dev permissions, so we don't need to check
// On POSIX, transfer ownership of the renderer-side (client) FD.
// This ensures this process will be notified when it is closed even if a
// connection is not established.
- handle->socket = base::FileDescriptor(dispatcher->TakeRendererFD(), true);
+ handle->socket = base::FileDescriptor(dispatcher->TakeRendererFD());
if (handle->socket.fd == -1)
return false;
#endif
void PpapiThread::ReportLoadResult(const base::FilePath& path,
LoadResult result) {
DCHECK_LT(result, LOAD_RESULT_MAX);
-
- std::ostringstream histogram_name;
- histogram_name << "Plugin.Ppapi" << (is_broker_ ? "Broker" : "Plugin")
- << "LoadResult_" << path.BaseName().MaybeAsASCII();
+ std::string histogram_name = std::string("Plugin.Ppapi") +
+ (is_broker_ ? "Broker" : "Plugin") +
+ "LoadResult_" + path.BaseName().MaybeAsASCII();
// Note: This leaks memory, which is expected behavior.
base::HistogramBase* histogram =
base::LinearHistogram::FactoryGet(
- histogram_name.str(),
+ histogram_name,
1,
LOAD_RESULT_MAX,
LOAD_RESULT_MAX + 1,
histogram->Add(result);
}
+void PpapiThread::ReportLoadErrorCode(
+ const base::FilePath& path,
+ const base::NativeLibraryLoadError& error) {
+#if defined(OS_WIN)
+ // Only report load error code on Windows because that's the only platform
+ // that has a numerical error value.
+ std::string histogram_name =
+ std::string("Plugin.Ppapi") + (is_broker_ ? "Broker" : "Plugin") +
+ "LoadErrorCode_" + path.BaseName().MaybeAsASCII();
+
+ // For sparse histograms, we can use the macro, as it does not incorporate a
+ // static.
+ UMA_HISTOGRAM_SPARSE_SLOWLY(histogram_name, error.code);
+#endif
+}
+
} // namespace content