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_talk_host.h"
8 #include "content/public/browser/browser_ppapi_host.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "grit/generated_resources.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/host/dispatch_host_message.h"
14 #include "ppapi/host/host_message_context.h"
15 #include "ppapi/host/ppapi_host.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ui/base/l10n/l10n_util.h"
20 #include "ash/shell.h"
21 #include "ash/shell_window_ids.h"
22 #include "ash/system/tray/system_tray_notifier.h"
23 #include "chrome/browser/ui/simple_message_box.h"
24 #include "ui/aura/window.h"
31 ppapi::host::ReplyMessageContext
GetPermissionOnUIThread(
32 PP_TalkPermission permission
,
33 int render_process_id
,
35 ppapi::host::ReplyMessageContext reply
) {
36 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
37 reply
.params
.set_result(0);
39 content::RenderFrameHost
* render_frame_host
=
40 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
41 if (!render_frame_host
)
42 return reply
; // RFH destroyed while task was pending.
46 base::string16 message
;
49 case PP_TALKPERMISSION_SCREENCAST
:
50 title
= l10n_util::GetStringUTF16(IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE
);
51 message
= l10n_util::GetStringUTF16(
52 IDS_GTALK_SCREEN_SHARE_DIALOG_MESSAGE
);
54 case PP_TALKPERMISSION_REMOTING
:
55 title
= l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE
);
56 message
= l10n_util::GetStringUTF16(
57 IDS_GTALK_REMOTING_DIALOG_MESSAGE
);
59 case PP_TALKPERMISSION_REMOTING_CONTINUE
:
60 title
= l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE
);
61 message
= l10n_util::GetStringUTF16(
62 IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE
);
69 // TODO(brettw). We should not be grabbing the active toplevel window, we
70 // should use the toplevel window associated with the render view.
71 aura::Window
* parent
= ash::Shell::GetContainer(
72 ash::Shell::GetTargetRootWindow(),
73 ash::internal::kShellWindowId_SystemModalContainer
);
74 reply
.params
.set_result(static_cast<int32_t>(
75 chrome::ShowMessageBox(parent
, title
, message
,
76 chrome::MESSAGE_BOX_TYPE_QUESTION
) ==
77 chrome::MESSAGE_BOX_RESULT_YES
));
84 #if defined(USE_ASH) && defined(OS_CHROMEOS)
85 void OnTerminateRemotingEventOnUIThread(const base::Closure
& stop_callback
) {
86 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
89 #endif // defined(USE_ASH) && defined(OS_CHROMEOS)
91 ppapi::host::ReplyMessageContext
StartRemotingOnUIThread(
92 const base::Closure
& stop_callback
,
93 int render_process_id
,
95 ppapi::host::ReplyMessageContext reply
) {
96 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
97 content::RenderFrameHost
* render_frame_host
=
98 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
99 if (!render_frame_host
) {
100 reply
.params
.set_result(PP_ERROR_FAILED
);
101 return reply
; // RFH destroyed while task was pending.
104 #if defined(USE_ASH) && defined(OS_CHROMEOS)
105 base::Closure stop_callback_ui_thread
= base::Bind(
106 &OnTerminateRemotingEventOnUIThread
,
109 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart(
110 stop_callback_ui_thread
, base::string16());
111 reply
.params
.set_result(PP_OK
);
114 reply
.params
.set_result(PP_ERROR_NOTSUPPORTED
);
119 void StopRemotingOnUIThread() {
120 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
121 #if defined(USE_ASH) && defined(OS_CHROMEOS)
122 if (ash::Shell::GetInstance()) {
123 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStop();
130 ppapi::host::ReplyMessageContext
StopRemotingOnUIThreadWithResult(
131 ppapi::host::ReplyMessageContext reply
) {
132 reply
.params
.set_result(PP_OK
);
133 StopRemotingOnUIThread();
139 PepperTalkHost::PepperTalkHost(content::BrowserPpapiHost
* host
,
140 PP_Instance instance
,
141 PP_Resource resource
)
142 : ppapi::host::ResourceHost(host
->GetPpapiHost(), instance
, resource
),
143 browser_ppapi_host_(host
),
144 remoting_started_(false),
145 weak_factory_(this) {
148 PepperTalkHost::~PepperTalkHost() {
149 if (remoting_started_
) {
150 content::BrowserThread::PostTask(
151 content::BrowserThread::UI
, FROM_HERE
,
152 base::Bind(&StopRemotingOnUIThread
));
156 int32_t PepperTalkHost::OnResourceMessageReceived(
157 const IPC::Message
& msg
,
158 ppapi::host::HostMessageContext
* context
) {
159 IPC_BEGIN_MESSAGE_MAP(PepperTalkHost
, msg
)
160 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Talk_RequestPermission
,
162 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting
,
164 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting
,
166 IPC_END_MESSAGE_MAP()
167 return PP_ERROR_FAILED
;
170 int32_t PepperTalkHost::OnRequestPermission(
171 ppapi::host::HostMessageContext
* context
,
172 PP_TalkPermission permission
) {
173 if (permission
< PP_TALKPERMISSION_SCREENCAST
||
174 permission
>= PP_TALKPERMISSION_NUM_PERMISSIONS
)
175 return PP_ERROR_BADARGUMENT
;
177 int render_process_id
= 0;
178 int render_frame_id
= 0;
179 browser_ppapi_host_
->GetRenderFrameIDsForInstance(
180 pp_instance(), &render_process_id
, &render_frame_id
);
182 content::BrowserThread::PostTaskAndReplyWithResult(
183 content::BrowserThread::UI
, FROM_HERE
,
184 base::Bind(&GetPermissionOnUIThread
, permission
, render_process_id
,
185 render_frame_id
, context
->MakeReplyMessageContext()),
186 base::Bind(&PepperTalkHost::OnRequestPermissionCompleted
,
187 weak_factory_
.GetWeakPtr()));
188 return PP_OK_COMPLETIONPENDING
;
191 int32_t PepperTalkHost::OnStartRemoting(
192 ppapi::host::HostMessageContext
* context
) {
193 int render_process_id
= 0;
194 int render_frame_id
= 0;
195 browser_ppapi_host_
->GetRenderFrameIDsForInstance(
196 pp_instance(), &render_process_id
, &render_frame_id
);
198 base::Closure remoting_stop_callback
= base::Bind(
199 &PepperTalkHost::OnRemotingStopEvent
,
200 weak_factory_
.GetWeakPtr());
202 content::BrowserThread::PostTaskAndReplyWithResult(
203 content::BrowserThread::UI
, FROM_HERE
,
204 base::Bind(&StartRemotingOnUIThread
, remoting_stop_callback
,
205 render_process_id
, render_frame_id
,
206 context
->MakeReplyMessageContext()),
207 base::Bind(&PepperTalkHost::OnStartRemotingCompleted
,
208 weak_factory_
.GetWeakPtr()));
209 return PP_OK_COMPLETIONPENDING
;
212 int32_t PepperTalkHost::OnStopRemoting(
213 ppapi::host::HostMessageContext
* context
) {
214 content::BrowserThread::PostTaskAndReplyWithResult(
215 content::BrowserThread::UI
, FROM_HERE
,
216 base::Bind(&StopRemotingOnUIThreadWithResult
,
217 context
->MakeReplyMessageContext()),
218 base::Bind(&PepperTalkHost::OnStopRemotingCompleted
,
219 weak_factory_
.GetWeakPtr()));
220 return PP_OK_COMPLETIONPENDING
;
223 void PepperTalkHost::OnRemotingStopEvent() {
224 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
225 remoting_started_
= false;
226 host()->SendUnsolicitedReply(
227 pp_resource(), PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_TERMINATE
));
230 void PepperTalkHost::OnRequestPermissionCompleted(
231 ppapi::host::ReplyMessageContext reply
) {
232 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
233 host()->SendReply(reply
, PpapiPluginMsg_Talk_RequestPermissionReply());
236 void PepperTalkHost::OnStartRemotingCompleted(
237 ppapi::host::ReplyMessageContext reply
) {
238 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
239 // Remember to hide remoting UI when resource is deleted.
240 if (reply
.params
.result() == PP_OK
)
241 remoting_started_
= true;
243 host()->SendReply(reply
, PpapiPluginMsg_Talk_StartRemotingReply());
246 void PepperTalkHost::OnStopRemotingCompleted(
247 ppapi::host::ReplyMessageContext reply
) {
248 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
249 remoting_started_
= false;
250 host()->SendReply(reply
, PpapiPluginMsg_Talk_StopRemotingReply());
253 } // namespace chrome