Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / renderer_host / pepper / pepper_flash_drm_host.cc
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.
4
5 #include "chrome/browser/renderer_host/pepper/pepper_flash_drm_host.h"
6
7 #if defined(OS_WIN)
8 #include <Windows.h>
9 #endif
10
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"
25
26 #if defined(USE_AURA)
27 #include "ui/aura/window.h"
28 #include "ui/aura/window_tree_host.h"
29 #endif
30
31 #if defined(OS_MACOSX)
32 #include "chrome/browser/renderer_host/pepper/monitor_finder_mac.h"
33 #endif
34
35 using content::BrowserPpapiHost;
36
37 namespace chrome {
38
39 namespace {
40 const char kVoucherFilename[] = "plugin.vch";
41 }
42
43 #if defined(OS_WIN)
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
48 // right monitor.
49 class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
50  public:
51   MonitorFinder(int process_id, int render_frame_id)
52       : process_id_(process_id),
53         render_frame_id_(render_frame_id),
54         monitor_(NULL),
55         request_sent_(0) {}
56
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,
65           FROM_HERE,
66           base::Bind(&MonitorFinder::FetchMonitorFromWidget, this));
67     }
68     return reinterpret_cast<int64_t>(monitor_);
69   }
70
71  private:
72   friend class base::RefCountedThreadSafe<MonitorFinder>;
73   ~MonitorFinder() {}
74
75   void FetchMonitorFromWidget() {
76     InterlockedExchange(&request_sent_, 0);
77     content::RenderFrameHost* rfh =
78         content::RenderFrameHost::FromID(process_id_, render_frame_id_);
79     if (!rfh)
80       return;
81     gfx::NativeView native_view = rfh->GetNativeView();
82 #if defined(USE_AURA)
83     aura::WindowTreeHost* host = native_view->GetHost();
84     if (!host)
85       return;
86     HWND window = host->GetAcceleratedWidget();
87 #else
88     HWND window = native_view;
89 #endif
90     HMONITOR monitor = ::MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
91     InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&monitor_),
92                                monitor);
93   }
94
95   const int process_id_;
96   const int render_frame_id_;
97   volatile HMONITOR monitor_;
98   volatile long request_sent_;
99 };
100 #elif !defined(OS_MACOSX)
101 // TODO(cpu): Support Linux someday.
102 class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> {
103  public:
104   MonitorFinder(int, int) {}
105   int64_t GetMonitor() { return 0; }
106
107  private:
108   friend class base::RefCountedThreadSafe<MonitorFinder>;
109   ~MonitorFinder() {}
110 };
111 #endif
112
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;
120   int render_frame_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);
128
129   fetcher_ = new DeviceIDFetcher(render_process_id);
130   monitor_finder_ = new MonitorFinder(render_process_id, render_frame_id);
131   monitor_finder_->GetMonitor();
132 }
133
134 PepperFlashDRMHost::~PepperFlashDRMHost() {}
135
136 int32_t PepperFlashDRMHost::OnResourceMessageReceived(
137     const IPC::Message& msg,
138     ppapi::host::HostMessageContext* context) {
139   IPC_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   IPC_END_MESSAGE_MAP()
147   return PP_ERROR_FAILED;
148 }
149
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;
156   }
157   return PP_OK_COMPLETIONPENDING;
158 }
159
160 int32_t PepperFlashDRMHost::OnHostMsgGetHmonitor(
161     ppapi::host::HostMessageContext* context) {
162   int64_t monitor_id = monitor_finder_->GetMonitor();
163   if (monitor_id) {
164     context->reply_msg = PpapiPluginMsg_FlashDRM_GetHmonitorReply(monitor_id);
165     return PP_OK;
166   }
167   return PP_ERROR_FAILED;
168 }
169
170 int32_t PepperFlashDRMHost::OnHostMsgMonitorIsExternal(
171     ppapi::host::HostMessageContext* context) {
172   int64_t monitor_id = monitor_finder_->GetMonitor();
173   if (monitor_id) {
174     // TODO(bbudge) get information about whether monitor is external.
175     context->reply_msg =
176         PpapiPluginMsg_FlashDRM_MonitorIsExternalReply(PP_FALSE);
177     return PP_OK;
178   }
179   return PP_ERROR_FAILED;
180 }
181
182 void PepperFlashDRMHost::GotDeviceID(
183     ppapi::host::ReplyMessageContext reply_context,
184     const std::string& id,
185     int32_t result) {
186   if (id.empty() && result == PP_OK) {
187     NOTREACHED();
188     result = PP_ERROR_FAILED;
189   }
190   reply_context.params.set_result(result);
191   host()->SendReply(reply_context,
192                     PpapiPluginMsg_FlashDRM_GetDeviceIDReply(id));
193 }
194
195 }  // namespace chrome