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
3 // found in the LICENSE file.
5 #include "chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h"
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "content/public/browser/browser_ppapi_host.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/child_process_security_policy.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/common/pepper_plugin_info.h"
20 #include "ppapi/c/pp_errors.h"
21 #include "ppapi/host/dispatch_host_message.h"
22 #include "ppapi/host/host_message_context.h"
23 #include "ppapi/host/ppapi_host.h"
24 #include "ppapi/proxy/ppapi_messages.h"
27 #include "ui/aura/window.h"
28 #include "ui/aura/window_tree_host.h"
31 #if defined(OS_MACOSX)
32 #include "chrome/browser/renderer_host/pepper/monitor_finder_mac.h"
35 using content::BrowserPpapiHost;
40 const base::FilePath::CharType kVoucherFilename[] =
41 FILE_PATH_LITERAL("plugin.vch");
45 // Helper class to get the UI thread which monitor is showing the
46 // window associated with the instance's render view. Since we get
47 // called by the IO thread and we cannot block, the first answer is
48 // of GetMonitor() may be NULL, but eventually it will contain the
50 class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
52 MonitorFinder(int process_id, int render_frame_id)
53 : process_id_(process_id),
54 render_frame_id_(render_frame_id),
59 int64_t GetMonitor() {
60 // We use |request_sent_| as an atomic boolean so that we
61 // never have more than one task posted at a given time. We
62 // do this because we don't know how often our client is going
63 // to call and we can't cache the |monitor_| value.
64 if (InterlockedCompareExchange(&request_sent_, 1, 0) == 0) {
65 content::BrowserThread::PostTask(
66 content::BrowserThread::UI, FROM_HERE,
67 base::Bind(&MonitorFinder::FetchMonitorFromWidget, this));
69 return reinterpret_cast<int64_t>(monitor_);
73 friend class base::RefCountedThreadSafe<MonitorFinder>;
76 void FetchMonitorFromWidget() {
77 InterlockedExchange(&request_sent_, 0);
78 content::RenderFrameHost* rfh =
79 content::RenderFrameHost::FromID(process_id_, render_frame_id_);
82 gfx::NativeView native_view = rfh->GetNativeView();
84 aura::WindowTreeHost* host = native_view->GetHost();
87 HWND window = host->GetAcceleratedWidget();
89 HWND window = native_view;
91 HMONITOR monitor = ::MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
92 InterlockedExchangePointer(reinterpret_cast<void* volatile *>(&monitor_),
96 const int process_id_;
97 const int render_frame_id_;
98 volatile HMONITOR monitor_;
99 volatile long request_sent_;
101 #elif !defined(OS_MACOSX)
102 // TODO(cpu): Support Linux someday.
103 class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
105 MonitorFinder(int, int) { }
106 int64_t GetMonitor() { return 0; }
109 friend class base::RefCountedThreadSafe<MonitorFinder>;
114 PepperFlashDRMHost::PepperFlashDRMHost(BrowserPpapiHost* host,
115 PP_Instance instance,
116 PP_Resource resource)
117 : ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
119 // Grant permissions to read the flash voucher file.
120 int render_process_id;
123 host->GetRenderFrameIDsForInstance(
124 instance, &render_process_id, &render_frame_id);
125 base::FilePath plugin_dir = host->GetPluginPath().DirName();
126 DCHECK(!plugin_dir.empty() && success);
127 base::FilePath voucher_file = plugin_dir.Append(
128 base::FilePath(kVoucherFilename));
129 content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
130 render_process_id, voucher_file);
132 fetcher_ = new DeviceIDFetcher(render_process_id);
133 monitor_finder_ = new MonitorFinder(render_process_id, render_frame_id);
134 monitor_finder_->GetMonitor();
137 PepperFlashDRMHost::~PepperFlashDRMHost() {
140 int32_t PepperFlashDRMHost::OnResourceMessageReceived(
141 const IPC::Message& msg,
142 ppapi::host::HostMessageContext* context) {
143 IPC_BEGIN_MESSAGE_MAP(PepperFlashDRMHost, msg)
144 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetDeviceID,
145 OnHostMsgGetDeviceID)
146 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetHmonitor,
147 OnHostMsgGetHmonitor)
148 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_MonitorIsExternal,
149 OnHostMsgMonitorIsExternal)
150 IPC_END_MESSAGE_MAP()
151 return PP_ERROR_FAILED;
154 int32_t PepperFlashDRMHost::OnHostMsgGetDeviceID(
155 ppapi::host::HostMessageContext* context) {
156 if (!fetcher_->Start(base::Bind(&PepperFlashDRMHost::GotDeviceID,
157 weak_factory_.GetWeakPtr(),
158 context->MakeReplyMessageContext()))) {
159 return PP_ERROR_INPROGRESS;
161 return PP_OK_COMPLETIONPENDING;
164 int32_t PepperFlashDRMHost::OnHostMsgGetHmonitor(
165 ppapi::host::HostMessageContext* context) {
166 int64_t monitor_id = monitor_finder_->GetMonitor();
168 context->reply_msg = PpapiPluginMsg_FlashDRM_GetHmonitorReply(monitor_id);
171 return PP_ERROR_FAILED;
175 int32_t PepperFlashDRMHost::OnHostMsgMonitorIsExternal(
176 ppapi::host::HostMessageContext* context) {
177 int64_t monitor_id = monitor_finder_->GetMonitor();
179 // TODO(bbudge) get information about whether monitor is external.
181 PpapiPluginMsg_FlashDRM_MonitorIsExternalReply(PP_FALSE);
184 return PP_ERROR_FAILED;
188 void PepperFlashDRMHost::GotDeviceID(
189 ppapi::host::ReplyMessageContext reply_context,
190 const std::string& id,
192 if (id.empty() && result == PP_OK) {
194 result = PP_ERROR_FAILED;
196 reply_context.params.set_result(result);
197 host()->SendReply(reply_context,
198 PpapiPluginMsg_FlashDRM_GetDeviceIDReply(id));
201 } // namespace chrome