Merge pull request #4070 from atom/flash-drm

Respond to GetDeviceID message from pepper plugin
This commit is contained in:
Cheng Zhao 2016-01-12 23:45:59 +08:00
commit 630cd091a0
6 changed files with 394 additions and 0 deletions

View file

@ -8,6 +8,7 @@
#include "chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h"
#include "chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h"
#include "chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h"
#include "chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h"
#include "chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "ppapi/host/message_filter_host.h"
@ -65,6 +66,9 @@ scoped_ptr<ResourceHost> ChromeBrowserPepperHostFactory::CreateResourceHost(
return scoped_ptr<ResourceHost>(new MessageFilterHost(
host_->GetPpapiHost(), instance, resource, clipboard_filter));
}
case PpapiHostMsg_FlashDRM_Create::ID:
return scoped_ptr<ResourceHost>(
new chrome::PepperFlashDRMHost(host_, instance, resource));
}
}

View file

@ -0,0 +1,52 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_MONITOR_FINDER_MAC_H_
#define CHROME_BROWSER_RENDERER_HOST_PEPPER_MONITOR_FINDER_MAC_H_
#include <ApplicationServices/ApplicationServices.h>
#include <stdint.h>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
namespace chrome {
// MonitorFinder maps a RenderFrameHost to the display ID on which the widget
// is painting. This class operates on the IO thread while the RenderFrameHost
// is on the UI thread, so the value returned by GetMonitor() may be 0 until
// the information can be retrieved asynchronously.
class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
public:
MonitorFinder(int process_id, int render_frame_id);
// Gets the native display ID for the <process_id, render_frame_id> tuple.
int64_t GetMonitor();
// Checks if the given |monitor_id| represents a built-in display.
static bool IsMonitorBuiltIn(int64_t monitor_id);
private:
friend class base::RefCountedThreadSafe<MonitorFinder>;
~MonitorFinder();
// Method run on the UI thread to get the display information.
void FetchMonitorFromWidget();
const int process_id_;
const int render_frame_id_;
base::Lock mutex_; // Protects the two members below.
// Whether one request to FetchMonitorFromWidget() has been made already.
bool request_sent_;
// The native display ID for the RenderFrameHost.
CGDirectDisplayID display_id_;
DISALLOW_COPY_AND_ASSIGN(MonitorFinder);
};
} // namespace chrome
#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_MONITOR_FINDER_H_

View file

@ -0,0 +1,62 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/pepper/monitor_finder_mac.h"
#import <Cocoa/Cocoa.h>
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
namespace chrome {
MonitorFinder::MonitorFinder(int process_id, int render_frame_id)
: process_id_(process_id),
render_frame_id_(render_frame_id),
request_sent_(false),
display_id_(kCGNullDirectDisplay) {}
MonitorFinder::~MonitorFinder() {}
int64_t MonitorFinder::GetMonitor() {
{
// The plugin may call this method several times, so avoid spamming the UI
// thread with requests by only allowing one outstanding request at a time.
base::AutoLock lock(mutex_);
if (request_sent_)
return display_id_;
request_sent_ = true;
}
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&MonitorFinder::FetchMonitorFromWidget, this));
return display_id_;
}
// static
bool MonitorFinder::IsMonitorBuiltIn(int64_t display_id) {
return CGDisplayIsBuiltin(display_id);
}
void MonitorFinder::FetchMonitorFromWidget() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(process_id_, render_frame_id_);
if (!rfh)
return;
gfx::NativeView native_view = rfh->GetNativeView();
NSWindow* window = [native_view window];
NSScreen* screen = [window screen];
CGDirectDisplayID display_id =
[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
base::AutoLock lock(mutex_);
request_sent_ = false;
display_id_ = display_id;
}
} // namespace chrome

View file

@ -0,0 +1,217 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h"
#include <cmath>
#if defined(OS_WIN)
#include <Windows.h>
#endif
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/pepper_plugin_info.h"
#include "net/base/net_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#if defined(USE_AURA)
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#endif
#if defined(OS_MACOSX)
#include "chrome/browser/renderer_host/pepper/monitor_finder_mac.h"
#endif
using content::BrowserPpapiHost;
namespace chrome {
namespace {
const char kVoucherFilename[] = "plugin.vch";
#if defined(OS_WIN)
bool GetSystemVolumeSerialNumber(std::string* number) {
// Find the system root path (e.g: C:\).
wchar_t system_path[MAX_PATH + 1];
if (!GetSystemDirectoryW(system_path, MAX_PATH))
return false;
wchar_t* first_slash = wcspbrk(system_path, L"\\/");
if (first_slash != NULL)
*(first_slash + 1) = 0;
DWORD number_local = 0;
if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL,
NULL, 0))
return false;
*number = base::IntToString(std::abs(static_cast<int>(number_local)));
return true;
}
#endif
}
#if defined(OS_WIN)
// Helper class to get the UI thread which monitor is showing the
// window associated with the instance's render view. Since we get
// called by the IO thread and we cannot block, the first answer is
// of GetMonitor() may be NULL, but eventually it will contain the
// right monitor.
class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
public:
MonitorFinder(int process_id, int render_frame_id)
: process_id_(process_id),
render_frame_id_(render_frame_id),
monitor_(NULL),
request_sent_(0) {}
int64_t GetMonitor() {
// We use |request_sent_| as an atomic boolean so that we
// never have more than one task posted at a given time. We
// do this because we don't know how often our client is going
// to call and we can't cache the |monitor_| value.
if (InterlockedCompareExchange(&request_sent_, 1, 0) == 0) {
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&MonitorFinder::FetchMonitorFromWidget, this));
}
return reinterpret_cast<int64_t>(monitor_);
}
private:
friend class base::RefCountedThreadSafe<MonitorFinder>;
~MonitorFinder() {}
void FetchMonitorFromWidget() {
InterlockedExchange(&request_sent_, 0);
content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(process_id_, render_frame_id_);
if (!rfh)
return;
gfx::NativeView native_view = rfh->GetNativeView();
#if defined(USE_AURA)
aura::WindowTreeHost* host = native_view->GetHost();
if (!host)
return;
HWND window = host->GetAcceleratedWidget();
#else
HWND window = native_view;
#endif
HMONITOR monitor = ::MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&monitor_),
monitor);
}
const int process_id_;
const int render_frame_id_;
volatile HMONITOR monitor_;
volatile long request_sent_;
};
#elif !defined(OS_MACOSX)
// TODO(cpu): Support Linux someday.
class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
public:
MonitorFinder(int, int) {}
int64_t GetMonitor() { return 0; }
private:
friend class base::RefCountedThreadSafe<MonitorFinder>;
~MonitorFinder() {}
};
#endif
PepperFlashDRMHost::PepperFlashDRMHost(BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource)
: ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
weak_factory_(this) {
// Grant permissions to read the flash voucher file.
int render_process_id;
int render_frame_id;
bool success = host->GetRenderFrameIDsForInstance(
instance, &render_process_id, &render_frame_id);
base::FilePath plugin_dir = host->GetPluginPath().DirName();
DCHECK(!plugin_dir.empty() && success);
base::FilePath voucher_file = plugin_dir.AppendASCII(kVoucherFilename);
content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
render_process_id, voucher_file);
monitor_finder_ = new MonitorFinder(render_process_id, render_frame_id);
monitor_finder_->GetMonitor();
}
PepperFlashDRMHost::~PepperFlashDRMHost() {}
int32_t PepperFlashDRMHost::OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) {
PPAPI_BEGIN_MESSAGE_MAP(PepperFlashDRMHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetDeviceID,
OnHostMsgGetDeviceID)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetHmonitor,
OnHostMsgGetHmonitor)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_MonitorIsExternal,
OnHostMsgMonitorIsExternal)
PPAPI_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
int32_t PepperFlashDRMHost::OnHostMsgGetDeviceID(
ppapi::host::HostMessageContext* context) {
static std::string id;
#if defined(OS_WIN)
if (id.empty() && !GetSystemVolumeSerialNumber(&id))
id = net::GetHostName();
#else
if (id.empty())
id = net::GetHostName();
#endif
context->reply_msg = PpapiPluginMsg_FlashDRM_GetDeviceIDReply(id);
return PP_OK;
}
int32_t PepperFlashDRMHost::OnHostMsgGetHmonitor(
ppapi::host::HostMessageContext* context) {
int64_t monitor_id = monitor_finder_->GetMonitor();
if (monitor_id) {
context->reply_msg = PpapiPluginMsg_FlashDRM_GetHmonitorReply(monitor_id);
return PP_OK;
}
return PP_ERROR_FAILED;
}
int32_t PepperFlashDRMHost::OnHostMsgMonitorIsExternal(
ppapi::host::HostMessageContext* context) {
int64_t monitor_id = monitor_finder_->GetMonitor();
if (!monitor_id)
return PP_ERROR_FAILED;
PP_Bool is_external = PP_FALSE;
#if defined(OS_MACOSX)
if (!MonitorFinder::IsMonitorBuiltIn(monitor_id))
is_external = PP_TRUE;
#endif
context->reply_msg =
PpapiPluginMsg_FlashDRM_MonitorIsExternalReply(is_external);
return PP_OK;
}
} // namespace chrome

View file

@ -0,0 +1,55 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DRM_HOST_H_
#define CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DRM_HOST_H_
#include <stdint.h>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
namespace content {
class BrowserPpapiHost;
}
namespace IPC {
class Message;
}
namespace chrome {
class MonitorFinder;
class PepperFlashDRMHost : public ppapi::host::ResourceHost {
public:
PepperFlashDRMHost(content::BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
~PepperFlashDRMHost() override;
// ResourceHost override.
int32_t OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) override;
private:
// IPC message handler.
int32_t OnHostMsgGetDeviceID(ppapi::host::HostMessageContext* context);
int32_t OnHostMsgGetHmonitor(ppapi::host::HostMessageContext* context);
int32_t OnHostMsgMonitorIsExternal(ppapi::host::HostMessageContext* context);
scoped_refptr<MonitorFinder> monitor_finder_;
base::WeakPtrFactory<PepperFlashDRMHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PepperFlashDRMHost);
};
} // namespace chrome
#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FLASH_DRM_HOST_H_

View file

@ -410,12 +410,16 @@
'chromium_src/chrome/browser/process_singleton.h',
'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.cc',
'chromium_src/chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h',
'chromium_src/chrome/browser/renderer_host/pepper/monitor_finder_mac.h',
'chromium_src/chrome/browser/renderer_host/pepper/monitor_finder_mac.mm',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.h',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_drm_host.cc',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc',
'chromium_src/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h',
'chromium_src/chrome/browser/renderer_host/pepper/widevine_cdm_message_filter.cc',