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 char kVoucherFilename
[] = "plugin.vch";
44 // Helper class to get the UI thread which monitor is showing the
45 // window associated with the instance's render view. Since we get
46 // called by the IO thread and we cannot block, the first answer is
47 // of GetMonitor() may be NULL, but eventually it will contain the
49 class MonitorFinder
: public base::RefCountedThreadSafe
<MonitorFinder
> {
51 MonitorFinder(int process_id
, int render_frame_id
)
52 : process_id_(process_id
),
53 render_frame_id_(render_frame_id
),
57 int64_t GetMonitor() {
58 // We use |request_sent_| as an atomic boolean so that we
59 // never have more than one task posted at a given time. We
60 // do this because we don't know how often our client is going
61 // to call and we can't cache the |monitor_| value.
62 if (InterlockedCompareExchange(&request_sent_
, 1, 0) == 0) {
63 content::BrowserThread::PostTask(
64 content::BrowserThread::UI
,
66 base::Bind(&MonitorFinder::FetchMonitorFromWidget
, this));
68 return reinterpret_cast<int64_t>(monitor_
);
72 friend class base::RefCountedThreadSafe
<MonitorFinder
>;
75 void FetchMonitorFromWidget() {
76 InterlockedExchange(&request_sent_
, 0);
77 content::RenderFrameHost
* rfh
=
78 content::RenderFrameHost::FromID(process_id_
, render_frame_id_
);
81 gfx::NativeView native_view
= rfh
->GetNativeView();
83 aura::WindowTreeHost
* host
= native_view
->GetHost();
86 HWND window
= host
->GetAcceleratedWidget();
88 HWND window
= native_view
;
90 HMONITOR monitor
= ::MonitorFromWindow(window
, MONITOR_DEFAULTTONULL
);
91 InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&monitor_
),
95 const int process_id_
;
96 const int render_frame_id_
;
97 volatile HMONITOR monitor_
;
98 volatile long request_sent_
;
100 #elif !defined(OS_MACOSX)
101 // TODO(cpu): Support Linux someday.
102 class MonitorFinder
: public base::RefCountedThreadSafe
<MonitorFinder
> {
104 MonitorFinder(int, int) {}
105 int64_t GetMonitor() { return 0; }
108 friend class base::RefCountedThreadSafe
<MonitorFinder
>;
113 PepperFlashDRMHost::PepperFlashDRMHost(BrowserPpapiHost
* host
,
114 PP_Instance instance
,
115 PP_Resource resource
)
116 : ppapi::host::ResourceHost(host
->GetPpapiHost(), instance
, resource
),
117 weak_factory_(this) {
118 // Grant permissions to read the flash voucher file.
119 int render_process_id
;
121 bool success
= host
->GetRenderFrameIDsForInstance(
122 instance
, &render_process_id
, &render_frame_id
);
123 base::FilePath plugin_dir
= host
->GetPluginPath().DirName();
124 DCHECK(!plugin_dir
.empty() && success
);
125 base::FilePath voucher_file
= plugin_dir
.AppendASCII(kVoucherFilename
);
126 content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
127 render_process_id
, voucher_file
);
129 fetcher_
= new DeviceIDFetcher(render_process_id
);
130 monitor_finder_
= new MonitorFinder(render_process_id
, render_frame_id
);
131 monitor_finder_
->GetMonitor();
134 PepperFlashDRMHost::~PepperFlashDRMHost() {}
136 int32_t PepperFlashDRMHost::OnResourceMessageReceived(
137 const IPC::Message
& msg
,
138 ppapi::host::HostMessageContext
* context
) {
139 PPAPI_BEGIN_MESSAGE_MAP(PepperFlashDRMHost
, msg
)
140 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetDeviceID
,
141 OnHostMsgGetDeviceID
)
142 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetHmonitor
,
143 OnHostMsgGetHmonitor
)
144 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_MonitorIsExternal
,
145 OnHostMsgMonitorIsExternal
)
146 PPAPI_END_MESSAGE_MAP()
147 return PP_ERROR_FAILED
;
150 int32_t PepperFlashDRMHost::OnHostMsgGetDeviceID(
151 ppapi::host::HostMessageContext
* context
) {
152 if (!fetcher_
->Start(base::Bind(&PepperFlashDRMHost::GotDeviceID
,
153 weak_factory_
.GetWeakPtr(),
154 context
->MakeReplyMessageContext()))) {
155 return PP_ERROR_INPROGRESS
;
157 return PP_OK_COMPLETIONPENDING
;
160 int32_t PepperFlashDRMHost::OnHostMsgGetHmonitor(
161 ppapi::host::HostMessageContext
* context
) {
162 int64_t monitor_id
= monitor_finder_
->GetMonitor();
164 context
->reply_msg
= PpapiPluginMsg_FlashDRM_GetHmonitorReply(monitor_id
);
167 return PP_ERROR_FAILED
;
170 int32_t PepperFlashDRMHost::OnHostMsgMonitorIsExternal(
171 ppapi::host::HostMessageContext
* context
) {
172 int64_t monitor_id
= monitor_finder_
->GetMonitor();
174 return PP_ERROR_FAILED
;
176 PP_Bool is_external
= PP_FALSE
;
177 #if defined(OS_MACOSX)
178 if (!MonitorFinder::IsMonitorBuiltIn(monitor_id
))
179 is_external
= PP_TRUE
;
182 PpapiPluginMsg_FlashDRM_MonitorIsExternalReply(is_external
);
186 void PepperFlashDRMHost::GotDeviceID(
187 ppapi::host::ReplyMessageContext reply_context
,
188 const std::string
& id
,
190 if (id
.empty() && result
== PP_OK
) {
192 result
= PP_ERROR_FAILED
;
194 reply_context
.params
.set_result(result
);
195 host()->SendReply(reply_context
,
196 PpapiPluginMsg_FlashDRM_GetDeviceIDReply(id
));
199 } // namespace chrome