pepper_flash_drm_host.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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_widget_host.h" 19#include "content/public/browser/render_widget_host_view.h" 20#include "content/public/common/pepper_plugin_info.h" 21#include "ppapi/c/pp_errors.h" 22#include "ppapi/host/dispatch_host_message.h" 23#include "ppapi/host/host_message_context.h" 24#include "ppapi/host/ppapi_host.h" 25#include "ppapi/proxy/ppapi_messages.h" 26 27#if defined(USE_AURA) 28#include "ui/aura/root_window.h" 29#endif 30 31using content::BrowserPpapiHost; 32 33namespace chrome { 34 35namespace { 36const base::FilePath::CharType kVoucherFilename[] = 37 FILE_PATH_LITERAL("plugin.vch"); 38} 39 40#if defined (OS_WIN) 41// Helper class to get the UI thread which monitor is showing the 42// window associated with the instance's render view. Since we get 43// called by the IO thread and we cannot block, the first answer is 44// of GetMonitor() may be NULL, but eventually it will contain the 45// right monitor. 46class MonitorFinder : public base::RefCountedThreadSafe<MonitorFinder> { 47 public: 48 MonitorFinder(int process_id, int render_id) 49 : process_id_(process_id), 50 render_id_(render_id), 51 monitor_(NULL), 52 request_sent_(0) { 53 } 54 55 int64_t GetMonitor() { 56 // We use |request_sent_| as an atomic boolean so that we 57 // never have more than one task posted at a given time. We 58 // do this because we don't know how often our client is going 59 // to call and we can't cache the |monitor_| value. 60 if (InterlockedCompareExchange(&request_sent_, 1, 0) == 0) { 61 content::BrowserThread::PostTask( 62 content::BrowserThread::UI, FROM_HERE, 63 base::Bind(&MonitorFinder::FetchMonitorFromWidget, this)); 64 } 65 return reinterpret_cast<int64_t>(monitor_); 66 } 67 68 private: 69 friend class base::RefCountedThreadSafe<MonitorFinder>; 70 ~MonitorFinder() { } 71 72 void FetchMonitorFromWidget() { 73 InterlockedExchange(&request_sent_, 0); 74 content::RenderWidgetHost* rwh = 75 content::RenderWidgetHost::FromID(process_id_, render_id_); 76 if (!rwh) 77 return; 78 content::RenderWidgetHostView* view = rwh->GetView(); 79 if (!view) 80 return; 81 gfx::NativeView native_view = view->GetNativeView(); 82#if defined(USE_AURA) 83 aura::RootWindow* root = native_view->GetRootWindow(); 84 if (!root) 85 return; 86 HWND window = root->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_id_; 97 volatile HMONITOR monitor_; 98 volatile long request_sent_; 99}; 100#else 101// TODO(cpu): Support Mac and Linux someday. 102class 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 113PepperFlashDRMHost::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_view_id; 121 bool success = 122 host->GetRenderViewIDsForInstance( 123 instance, &render_process_id, &render_view_id); 124 base::FilePath plugin_dir = host->GetPluginPath().DirName(); 125 DCHECK(!plugin_dir.empty() && success); 126 base::FilePath voucher_file = plugin_dir.Append( 127 base::FilePath(kVoucherFilename)); 128 content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile( 129 render_process_id, voucher_file); 130 131 fetcher_ = new DeviceIDFetcher(render_process_id); 132 monitor_finder_ = new MonitorFinder(render_process_id, render_view_id); 133 monitor_finder_->GetMonitor(); 134} 135 136PepperFlashDRMHost::~PepperFlashDRMHost() { 137} 138 139int32_t PepperFlashDRMHost::OnResourceMessageReceived( 140 const IPC::Message& msg, 141 ppapi::host::HostMessageContext* context) { 142 IPC_BEGIN_MESSAGE_MAP(PepperFlashDRMHost, msg) 143 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetDeviceID, 144 OnHostMsgGetDeviceID) 145 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FlashDRM_GetHmonitor, 146 OnHostMsgGetHmonitor) 147 IPC_END_MESSAGE_MAP() 148 return PP_ERROR_FAILED; 149} 150 151int32_t PepperFlashDRMHost::OnHostMsgGetDeviceID( 152 ppapi::host::HostMessageContext* context) { 153 if (!fetcher_->Start(base::Bind(&PepperFlashDRMHost::GotDeviceID, 154 weak_factory_.GetWeakPtr(), 155 context->MakeReplyMessageContext()))) { 156 return PP_ERROR_INPROGRESS; 157 } 158 return PP_OK_COMPLETIONPENDING; 159} 160 161int32_t PepperFlashDRMHost::OnHostMsgGetHmonitor( 162 ppapi::host::HostMessageContext* context) { 163 int64_t monitor_id = monitor_finder_->GetMonitor(); 164 if (monitor_id) { 165 context->reply_msg = PpapiPluginMsg_FlashDRM_GetHmonitorReply(monitor_id); 166 return PP_OK; 167 } else { 168 return PP_ERROR_FAILED; 169 } 170} 171 172void PepperFlashDRMHost::GotDeviceID( 173 ppapi::host::ReplyMessageContext reply_context, 174 const std::string& id, 175 int32_t result) { 176 if (id.empty() && result == PP_OK) { 177 NOTREACHED(); 178 result = PP_ERROR_FAILED; 179 } 180 reply_context.params.set_result(result); 181 host()->SendReply(reply_context, 182 PpapiPluginMsg_FlashDRM_GetDeviceIDReply(id)); 183} 184 185} // namespace chrome 186