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 "chrome/grit/generated_resources.h"
9 #include "content/public/browser/browser_ppapi_host.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_frame_host.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
);
52 l10n_util::GetStringUTF16(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(IDS_GTALK_REMOTING_DIALOG_MESSAGE
);
58 case PP_TALKPERMISSION_REMOTING_CONTINUE
:
59 title
= l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE
);
61 l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE
);
68 // TODO(brettw). We should not be grabbing the active toplevel window, we
69 // should use the toplevel window associated with the render view.
70 aura::Window
* parent
=
71 ash::Shell::GetContainer(ash::Shell::GetTargetRootWindow(),
72 ash::kShellWindowId_SystemModalContainer
);
73 reply
.params
.set_result(static_cast<int32_t>(
74 chrome::ShowMessageBox(
75 parent
, title
, message
, chrome::MESSAGE_BOX_TYPE_QUESTION
) ==
76 chrome::MESSAGE_BOX_RESULT_YES
));
83 #if defined(OS_CHROMEOS)
84 void OnTerminateRemotingEventOnUIThread(const base::Closure
& stop_callback
) {
85 content::BrowserThread::PostTask(
86 content::BrowserThread::IO
, FROM_HERE
, stop_callback
);
88 #endif // defined(USE_ASH) && defined(OS_CHROMEOS)
90 ppapi::host::ReplyMessageContext
StartRemotingOnUIThread(
91 const base::Closure
& stop_callback
,
92 int render_process_id
,
94 ppapi::host::ReplyMessageContext reply
) {
95 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
96 content::RenderFrameHost
* render_frame_host
=
97 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
98 if (!render_frame_host
) {
99 reply
.params
.set_result(PP_ERROR_FAILED
);
100 return reply
; // RFH destroyed while task was pending.
103 #if defined(OS_CHROMEOS)
104 base::Closure stop_callback_ui_thread
=
105 base::Bind(&OnTerminateRemotingEventOnUIThread
, stop_callback
);
107 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart(
108 stop_callback_ui_thread
, base::string16());
109 reply
.params
.set_result(PP_OK
);
112 reply
.params
.set_result(PP_ERROR_NOTSUPPORTED
);
117 void StopRemotingOnUIThread() {
118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
119 #if defined(OS_CHROMEOS)
120 if (ash::Shell::GetInstance()) {
121 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStop();
128 ppapi::host::ReplyMessageContext
StopRemotingOnUIThreadWithResult(
129 ppapi::host::ReplyMessageContext reply
) {
130 reply
.params
.set_result(PP_OK
);
131 StopRemotingOnUIThread();
137 PepperTalkHost::PepperTalkHost(content::BrowserPpapiHost
* host
,
138 PP_Instance instance
,
139 PP_Resource resource
)
140 : ppapi::host::ResourceHost(host
->GetPpapiHost(), instance
, resource
),
141 browser_ppapi_host_(host
),
142 remoting_started_(false),
143 weak_factory_(this) {}
145 PepperTalkHost::~PepperTalkHost() {
146 if (remoting_started_
) {
147 content::BrowserThread::PostTask(content::BrowserThread::UI
,
149 base::Bind(&StopRemotingOnUIThread
));
153 int32_t PepperTalkHost::OnResourceMessageReceived(
154 const IPC::Message
& msg
,
155 ppapi::host::HostMessageContext
* context
) {
156 PPAPI_BEGIN_MESSAGE_MAP(PepperTalkHost
, msg
)
157 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Talk_RequestPermission
,
159 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting
,
161 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting
,
163 PPAPI_END_MESSAGE_MAP()
164 return PP_ERROR_FAILED
;
167 int32_t PepperTalkHost::OnRequestPermission(
168 ppapi::host::HostMessageContext
* context
,
169 PP_TalkPermission permission
) {
170 if (permission
< PP_TALKPERMISSION_SCREENCAST
||
171 permission
>= PP_TALKPERMISSION_NUM_PERMISSIONS
)
172 return PP_ERROR_BADARGUMENT
;
174 int render_process_id
= 0;
175 int render_frame_id
= 0;
176 browser_ppapi_host_
->GetRenderFrameIDsForInstance(
177 pp_instance(), &render_process_id
, &render_frame_id
);
179 content::BrowserThread::PostTaskAndReplyWithResult(
180 content::BrowserThread::UI
,
182 base::Bind(&GetPermissionOnUIThread
,
186 context
->MakeReplyMessageContext()),
187 base::Bind(&PepperTalkHost::OnRequestPermissionCompleted
,
188 weak_factory_
.GetWeakPtr()));
189 return PP_OK_COMPLETIONPENDING
;
192 int32_t PepperTalkHost::OnStartRemoting(
193 ppapi::host::HostMessageContext
* context
) {
194 int render_process_id
= 0;
195 int render_frame_id
= 0;
196 browser_ppapi_host_
->GetRenderFrameIDsForInstance(
197 pp_instance(), &render_process_id
, &render_frame_id
);
199 base::Closure remoting_stop_callback
= base::Bind(
200 &PepperTalkHost::OnRemotingStopEvent
, weak_factory_
.GetWeakPtr());
202 content::BrowserThread::PostTaskAndReplyWithResult(
203 content::BrowserThread::UI
,
205 base::Bind(&StartRemotingOnUIThread
,
206 remoting_stop_callback
,
209 context
->MakeReplyMessageContext()),
210 base::Bind(&PepperTalkHost::OnStartRemotingCompleted
,
211 weak_factory_
.GetWeakPtr()));
212 return PP_OK_COMPLETIONPENDING
;
215 int32_t PepperTalkHost::OnStopRemoting(
216 ppapi::host::HostMessageContext
* context
) {
217 content::BrowserThread::PostTaskAndReplyWithResult(
218 content::BrowserThread::UI
,
220 base::Bind(&StopRemotingOnUIThreadWithResult
,
221 context
->MakeReplyMessageContext()),
222 base::Bind(&PepperTalkHost::OnStopRemotingCompleted
,
223 weak_factory_
.GetWeakPtr()));
224 return PP_OK_COMPLETIONPENDING
;
227 void PepperTalkHost::OnRemotingStopEvent() {
228 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
229 remoting_started_
= false;
230 host()->SendUnsolicitedReply(
231 pp_resource(), PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_TERMINATE
));
234 void PepperTalkHost::OnRequestPermissionCompleted(
235 ppapi::host::ReplyMessageContext reply
) {
236 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
237 host()->SendReply(reply
, PpapiPluginMsg_Talk_RequestPermissionReply());
240 void PepperTalkHost::OnStartRemotingCompleted(
241 ppapi::host::ReplyMessageContext reply
) {
242 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
243 // Remember to hide remoting UI when resource is deleted.
244 if (reply
.params
.result() == PP_OK
)
245 remoting_started_
= true;
247 host()->SendReply(reply
, PpapiPluginMsg_Talk_StartRemotingReply());
250 void PepperTalkHost::OnStopRemotingCompleted(
251 ppapi::host::ReplyMessageContext reply
) {
252 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO
));
253 remoting_started_
= false;
254 host()->SendReply(reply
, PpapiPluginMsg_Talk_StopRemotingReply());
257 } // namespace chrome