pepper_talk_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_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 84void OnTerminateRemotingEventOnUIThread(const base::Closure& stop_callback) { 85 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, 86 stop_callback); 87} 88 89ppapi::host::ReplyMessageContext StartRemotingOnUIThread( 90 const base::Closure& stop_callback, 91 int render_process_id, 92 int render_view_id, 93 ppapi::host::ReplyMessageContext reply) { 94 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 95 content::RenderViewHost* render_view_host = 96 content::RenderViewHost::FromID(render_process_id, render_view_id); 97 if (!render_view_host) { 98 reply.params.set_result(PP_ERROR_FAILED); 99 return reply; // RVH destroyed while task was pending. 100 } 101 102#if defined(USE_ASH) && defined(OS_CHROMEOS) 103 base::Closure stop_callback_ui_thread = base::Bind( 104 &OnTerminateRemotingEventOnUIThread, 105 stop_callback); 106 107 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart( 108 stop_callback_ui_thread, base::string16()); 109 reply.params.set_result(PP_OK); 110#else 111 NOTIMPLEMENTED(); 112 reply.params.set_result(PP_ERROR_NOTSUPPORTED); 113#endif 114 return reply; 115} 116 117void StopRemotingOnUIThread() { 118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 119#if defined(USE_ASH) && defined(OS_CHROMEOS) 120 if (ash::Shell::GetInstance()) { 121 ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStop(); 122 } 123#else 124 NOTIMPLEMENTED(); 125#endif 126} 127 128ppapi::host::ReplyMessageContext StopRemotingOnUIThreadWithResult( 129 ppapi::host::ReplyMessageContext reply) { 130 reply.params.set_result(PP_OK); 131 StopRemotingOnUIThread(); 132 return reply; 133} 134 135} // namespace 136 137PepperTalkHost::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) { 144} 145 146PepperTalkHost::~PepperTalkHost() { 147 if (remoting_started_) { 148 content::BrowserThread::PostTask( 149 content::BrowserThread::UI, FROM_HERE, 150 base::Bind(&StopRemotingOnUIThread)); 151 } 152} 153 154int32_t PepperTalkHost::OnResourceMessageReceived( 155 const IPC::Message& msg, 156 ppapi::host::HostMessageContext* context) { 157 IPC_BEGIN_MESSAGE_MAP(PepperTalkHost, msg) 158 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Talk_RequestPermission, 159 OnRequestPermission) 160 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting, 161 OnStartRemoting) 162 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting, 163 OnStopRemoting) 164 IPC_END_MESSAGE_MAP() 165 return PP_ERROR_FAILED; 166} 167 168int32_t PepperTalkHost::OnRequestPermission( 169 ppapi::host::HostMessageContext* context, 170 PP_TalkPermission permission) { 171 if (permission < PP_TALKPERMISSION_SCREENCAST || 172 permission >= PP_TALKPERMISSION_NUM_PERMISSIONS) 173 return PP_ERROR_BADARGUMENT; 174 175 int render_process_id = 0; 176 int render_view_id = 0; 177 browser_ppapi_host_->GetRenderViewIDsForInstance( 178 pp_instance(), &render_process_id, &render_view_id); 179 180 content::BrowserThread::PostTaskAndReplyWithResult( 181 content::BrowserThread::UI, FROM_HERE, 182 base::Bind(&GetPermissionOnUIThread, permission, render_process_id, 183 render_view_id, context->MakeReplyMessageContext()), 184 base::Bind(&PepperTalkHost::OnRequestPermissionCompleted, 185 weak_factory_.GetWeakPtr())); 186 return PP_OK_COMPLETIONPENDING; 187} 188 189int32_t PepperTalkHost::OnStartRemoting( 190 ppapi::host::HostMessageContext* context) { 191 int render_process_id = 0; 192 int render_view_id = 0; 193 browser_ppapi_host_->GetRenderViewIDsForInstance( 194 pp_instance(), &render_process_id, &render_view_id); 195 196 base::Closure remoting_stop_callback = base::Bind( 197 &PepperTalkHost::OnRemotingStopEvent, 198 weak_factory_.GetWeakPtr()); 199 200 content::BrowserThread::PostTaskAndReplyWithResult( 201 content::BrowserThread::UI, FROM_HERE, 202 base::Bind(&StartRemotingOnUIThread, remoting_stop_callback, 203 render_process_id, render_view_id, 204 context->MakeReplyMessageContext()), 205 base::Bind(&PepperTalkHost::OnStartRemotingCompleted, 206 weak_factory_.GetWeakPtr())); 207 return PP_OK_COMPLETIONPENDING; 208} 209 210int32_t PepperTalkHost::OnStopRemoting( 211 ppapi::host::HostMessageContext* context) { 212 content::BrowserThread::PostTaskAndReplyWithResult( 213 content::BrowserThread::UI, FROM_HERE, 214 base::Bind(&StopRemotingOnUIThreadWithResult, 215 context->MakeReplyMessageContext()), 216 base::Bind(&PepperTalkHost::OnStopRemotingCompleted, 217 weak_factory_.GetWeakPtr())); 218 return PP_OK_COMPLETIONPENDING; 219} 220 221void PepperTalkHost::OnRemotingStopEvent() { 222 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 223 remoting_started_ = false; 224 host()->SendUnsolicitedReply( 225 pp_resource(), PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_TERMINATE)); 226} 227 228void PepperTalkHost::OnRequestPermissionCompleted( 229 ppapi::host::ReplyMessageContext reply) { 230 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 231 host()->SendReply(reply, PpapiPluginMsg_Talk_RequestPermissionReply()); 232} 233 234void PepperTalkHost::OnStartRemotingCompleted( 235 ppapi::host::ReplyMessageContext reply) { 236 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 237 // Remember to hide remoting UI when resource is deleted. 238 if (reply.params.result() == PP_OK) 239 remoting_started_ = true; 240 241 host()->SendReply(reply, PpapiPluginMsg_Talk_StartRemotingReply()); 242} 243 244void PepperTalkHost::OnStopRemotingCompleted( 245 ppapi::host::ReplyMessageContext reply) { 246 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 247 remoting_started_ = false; 248 host()->SendReply(reply, PpapiPluginMsg_Talk_StopRemotingReply()); 249} 250 251} // namespace chrome 252