pepper_output_protection_message_filter.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright 2013 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_output_protection_message_filter.h"
6
7#include "build/build_config.h"
8#include "content/public/browser/browser_ppapi_host.h"
9#include "content/public/browser/browser_thread.h"
10#include "content/public/browser/render_view_host.h"
11#include "content/public/browser/web_contents.h"
12#include "ppapi/c/pp_errors.h"
13#include "ppapi/c/private/ppb_output_protection_private.h"
14#include "ppapi/host/dispatch_host_message.h"
15#include "ppapi/host/host_message_context.h"
16#include "ppapi/host/ppapi_host.h"
17#include "ppapi/proxy/ppapi_messages.h"
18
19#if defined(USE_ASH) && defined(OS_CHROMEOS)
20#include "ash/shell.h"
21#include "ash/shell_delegate.h"
22#include "chromeos/display/output_configurator.h"
23#endif
24
25namespace chrome {
26
27namespace {
28
29#if defined(OS_CHROMEOS)
30COMPILE_ASSERT(
31    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE) ==
32    static_cast<int>(chromeos::OUTPUT_TYPE_NONE),
33    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE);
34COMPILE_ASSERT(
35    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN) ==
36    static_cast<int>(chromeos::OUTPUT_TYPE_UNKNOWN),
37    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_UNKNOWN);
38COMPILE_ASSERT(
39    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL) ==
40    static_cast<int>(chromeos::OUTPUT_TYPE_INTERNAL),
41    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL);
42COMPILE_ASSERT(
43    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA) ==
44    static_cast<int>(chromeos::OUTPUT_TYPE_VGA),
45    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA);
46COMPILE_ASSERT(
47    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) ==
48    static_cast<int>(chromeos::OUTPUT_TYPE_HDMI),
49    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI);
50COMPILE_ASSERT(
51    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI) ==
52    static_cast<int>(chromeos::OUTPUT_TYPE_DVI),
53    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DVI);
54COMPILE_ASSERT(
55    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT) ==
56    static_cast<int>(chromeos::OUTPUT_TYPE_DISPLAYPORT),
57    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT);
58COMPILE_ASSERT(
59    static_cast<int>(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NETWORK) ==
60    static_cast<int>(chromeos::OUTPUT_TYPE_NETWORK),
61    PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NETWORK);
62COMPILE_ASSERT(
63    static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE) ==
64    static_cast<int>(chromeos::OUTPUT_PROTECTION_METHOD_NONE),
65    PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE);
66COMPILE_ASSERT(
67    static_cast<int>(PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) ==
68    static_cast<int>(chromeos::OUTPUT_PROTECTION_METHOD_HDCP),
69    PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP);
70#endif
71
72#if defined(OS_CHROMEOS) && defined(USE_ASH)
73void UnregisterClientOnUIThread(
74    chromeos::OutputConfigurator::OutputProtectionClientId client_id) {
75  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
76  chromeos::OutputConfigurator* configurator =
77      ash::Shell::GetInstance()->output_configurator();
78  configurator->UnregisterOutputProtectionClient(client_id);
79}
80#endif
81
82}  // namespace
83
84PepperOutputProtectionMessageFilter::PepperOutputProtectionMessageFilter(
85    content::BrowserPpapiHost* host,
86    PP_Instance instance) {
87#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
88  client_id_ = 0;
89  host->GetRenderViewIDsForInstance(
90      instance, &render_process_id_, &render_view_id_);
91#else
92  NOTIMPLEMENTED();
93#endif
94}
95
96PepperOutputProtectionMessageFilter::~PepperOutputProtectionMessageFilter() {
97#if defined(OS_CHROMEOS) && defined(USE_ASH)
98  if (client_id_ != 0) {
99    content::BrowserThread::PostTask(
100        content::BrowserThread::UI,
101        FROM_HERE,
102        base::Bind(&UnregisterClientOnUIThread, client_id_));
103  }
104#endif
105}
106
107scoped_refptr<base::TaskRunner>
108PepperOutputProtectionMessageFilter::OverrideTaskRunnerForMessage(
109    const IPC::Message& message) {
110  return content::BrowserThread::GetMessageLoopProxyForThread(
111      content::BrowserThread::UI);
112}
113
114int32_t PepperOutputProtectionMessageFilter::OnResourceMessageReceived(
115    const IPC::Message& msg,
116    ppapi::host::HostMessageContext* context) {
117  IPC_BEGIN_MESSAGE_MAP(PepperOutputProtectionMessageFilter, msg)
118    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
119        PpapiHostMsg_OutputProtection_QueryStatus,
120        OnQueryStatus);
121    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
122        PpapiHostMsg_OutputProtection_EnableProtection,
123        OnEnableProtection);
124  IPC_END_MESSAGE_MAP()
125  return PP_ERROR_FAILED;
126}
127
128#if defined(OS_CHROMEOS)
129chromeos::OutputConfigurator::OutputProtectionClientId
130PepperOutputProtectionMessageFilter::GetClientId() {
131  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
132  if (client_id_ == 0) {
133#if defined(USE_ASH) && defined(USE_X11)
134    chromeos::OutputConfigurator* configurator =
135        ash::Shell::GetInstance()->output_configurator();
136    client_id_ = configurator->RegisterOutputProtectionClient();
137#endif
138  }
139  return client_id_;
140}
141#endif
142
143int32_t PepperOutputProtectionMessageFilter::OnQueryStatus(
144    ppapi::host::HostMessageContext* context) {
145  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
146
147#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
148  ppapi::host::ReplyMessageContext reply_context =
149      context->MakeReplyMessageContext();
150  uint32_t link_mask = 0, protection_mask = 0;
151  chromeos::OutputConfigurator* configurator =
152      ash::Shell::GetInstance()->output_configurator();
153  bool result = configurator->QueryOutputProtectionStatus(
154      GetClientId(), &link_mask, &protection_mask);
155
156  // If we successfully retrieved the device level status, check for capturers.
157  if (result) {
158    // Ensure the RenderViewHost is still alive.
159    content::RenderViewHost* rvh =
160        content::RenderViewHost::FromID(render_process_id_, render_view_id_);
161    if (rvh) {
162      if (content::WebContents::FromRenderViewHost(rvh)->GetCapturerCount() > 0)
163        link_mask |= chromeos::OUTPUT_TYPE_NETWORK;
164    }
165  }
166
167  reply_context.params.set_result(result ? PP_OK : PP_ERROR_FAILED);
168  SendReply(
169      reply_context,
170      PpapiPluginMsg_OutputProtection_QueryStatusReply(
171          link_mask, protection_mask));
172  return PP_OK_COMPLETIONPENDING;
173#else
174  NOTIMPLEMENTED();
175  return PP_ERROR_NOTSUPPORTED;
176#endif
177}
178
179int32_t PepperOutputProtectionMessageFilter::OnEnableProtection(
180    ppapi::host::HostMessageContext* context,
181    uint32_t desired_method_mask) {
182  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
183
184#if defined(OS_CHROMEOS) && defined(USE_ASH) && defined(USE_X11)
185  ppapi::host::ReplyMessageContext reply_context =
186      context->MakeReplyMessageContext();
187  chromeos::OutputConfigurator* configurator =
188      ash::Shell::GetInstance()->output_configurator();
189  bool result = configurator->EnableOutputProtection(
190      GetClientId(), desired_method_mask);
191  reply_context.params.set_result(result ? PP_OK : PP_ERROR_FAILED);
192  SendReply(
193      reply_context,
194      PpapiPluginMsg_OutputProtection_EnableProtectionReply());
195  return PP_OK_COMPLETIONPENDING;
196#else
197  NOTIMPLEMENTED();
198  return PP_ERROR_NOTSUPPORTED;
199#endif
200}
201
202}  // namespace chrome
203
204