pepper_talk_host.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_talk_host.h" 6 7#include "base/bind.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 "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" 18 19#if defined(USE_ASH) 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" 25#endif 26 27namespace chrome { 28 29namespace { 30 31ppapi::host::ReplyMessageContext GetPermissionOnUIThread( 32 PP_TalkPermission permission, 33 int render_process_id, 34 int render_view_id, 35 ppapi::host::ReplyMessageContext reply) { 36 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 37 reply.params.set_result(0); 38 39 content::RenderViewHost* render_view_host = 40 content::RenderViewHost::FromID(render_process_id, render_view_id); 41 if (!render_view_host) 42 return reply; // RVH destroyed while task was pending. 43 44#if defined(USE_ASH) 45 string16 title; 46 string16 message; 47 48 switch (permission) { 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); 53 break; 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); 58 break; 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); 63 break; 64 default: 65 NOTREACHED(); 66 return reply; 67 } 68 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)); 78#else 79 NOTIMPLEMENTED(); 80#endif 81 return reply; 82} 83 84#if defined(USE_ASH) && defined(OS_CHROMEOS) 85void OnTerminateRemotingEventOnUIThread(const base::Closure& stop_callback) { 86 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, 87 stop_callback); 88} 89#endif // defined(USE_ASH) && defined(OS_CHROMEOS) 90 91ppapi::host::ReplyMessageContext StartRemotingOnUIThread( 92 const base::Closure& stop_callback, 93 int render_process_id, 94 int render_view_id, 95 ppapi::host::ReplyMessageContext reply) { 96 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 97 content::RenderViewHost* render_view_host = 98 content::RenderViewHost::FromID(render_process_id, render_view_id); 99 if (!render_view_host) { 100 reply.params.set_result(PP_ERROR_FAILED); 101 return reply; // RVH destroyed while task was pending. 102 } 103 104#if defined(USE_ASH) && defined(OS_CHROMEOS) 105 base::Closure stop_callback_ui_thread = base::Bind( 106 &OnTerminateRemotingEventOnUIThread, 107 stop_callback); 108 109 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart( 110 stop_callback_ui_thread, base::string16()); 111 reply.params.set_result(PP_OK); 112#else 113 NOTIMPLEMENTED(); 114 reply.params.set_result(PP_ERROR_NOTSUPPORTED); 115#endif 116 return reply; 117} 118 119void 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(); 124 } 125#else 126 NOTIMPLEMENTED(); 127#endif 128} 129 130ppapi::host::ReplyMessageContext StopRemotingOnUIThreadWithResult( 131 ppapi::host::ReplyMessageContext reply) { 132 reply.params.set_result(PP_OK); 133 StopRemotingOnUIThread(); 134 return reply; 135} 136 137} // namespace 138 139PepperTalkHost::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) { 146} 147 148PepperTalkHost::~PepperTalkHost() { 149 if (remoting_started_) { 150 content::BrowserThread::PostTask( 151 content::BrowserThread::UI, FROM_HERE, 152 base::Bind(&StopRemotingOnUIThread)); 153 } 154} 155 156int32_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, 161 OnRequestPermission) 162 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting, 163 OnStartRemoting) 164 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting, 165 OnStopRemoting) 166 IPC_END_MESSAGE_MAP() 167 return PP_ERROR_FAILED; 168} 169 170int32_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; 176 177 int render_process_id = 0; 178 int render_view_id = 0; 179 browser_ppapi_host_->GetRenderViewIDsForInstance( 180 pp_instance(), &render_process_id, &render_view_id); 181 182 content::BrowserThread::PostTaskAndReplyWithResult( 183 content::BrowserThread::UI, FROM_HERE, 184 base::Bind(&GetPermissionOnUIThread, permission, render_process_id, 185 render_view_id, context->MakeReplyMessageContext()), 186 base::Bind(&PepperTalkHost::OnRequestPermissionCompleted, 187 weak_factory_.GetWeakPtr())); 188 return PP_OK_COMPLETIONPENDING; 189} 190 191int32_t PepperTalkHost::OnStartRemoting( 192 ppapi::host::HostMessageContext* context) { 193 int render_process_id = 0; 194 int render_view_id = 0; 195 browser_ppapi_host_->GetRenderViewIDsForInstance( 196 pp_instance(), &render_process_id, &render_view_id); 197 198 base::Closure remoting_stop_callback = base::Bind( 199 &PepperTalkHost::OnRemotingStopEvent, 200 weak_factory_.GetWeakPtr()); 201 202 content::BrowserThread::PostTaskAndReplyWithResult( 203 content::BrowserThread::UI, FROM_HERE, 204 base::Bind(&StartRemotingOnUIThread, remoting_stop_callback, 205 render_process_id, render_view_id, 206 context->MakeReplyMessageContext()), 207 base::Bind(&PepperTalkHost::OnStartRemotingCompleted, 208 weak_factory_.GetWeakPtr())); 209 return PP_OK_COMPLETIONPENDING; 210} 211 212int32_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; 221} 222 223void 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)); 228} 229 230void PepperTalkHost::OnRequestPermissionCompleted( 231 ppapi::host::ReplyMessageContext reply) { 232 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 233 host()->SendReply(reply, PpapiPluginMsg_Talk_RequestPermissionReply()); 234} 235 236void 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; 242 243 host()->SendReply(reply, PpapiPluginMsg_Talk_StartRemotingReply()); 244} 245 246void 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()); 251} 252 253} // namespace chrome 254