blob: 027abd70c15ad64ab684ed45198e9327d920fa6f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/pepper/pepper_talk_host.h"
#include "base/bind.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "grit/generated_resources.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(USE_ASH)
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "ui/aura/window.h"
#endif
namespace chrome {
namespace {
ppapi::host::ReplyMessageContext GetPermissionOnUIThread(
PP_TalkPermission permission,
int render_process_id,
int render_view_id,
ppapi::host::ReplyMessageContext reply) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
reply.params.set_result(0);
content::RenderViewHost* render_view_host =
content::RenderViewHost::FromID(render_process_id, render_view_id);
if (!render_view_host)
return reply; // RVH destroyed while task was pending.
#if defined(USE_ASH)
string16 title;
string16 message;
switch (permission) {
case PP_TALKPERMISSION_SCREENCAST:
title = l10n_util::GetStringUTF16(IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE);
message = l10n_util::GetStringUTF16(
IDS_GTALK_SCREEN_SHARE_DIALOG_MESSAGE);
break;
case PP_TALKPERMISSION_REMOTING:
title = l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE);
message = l10n_util::GetStringUTF16(
IDS_GTALK_REMOTING_DIALOG_MESSAGE);
break;
case PP_TALKPERMISSION_REMOTING_CONTINUE:
title = l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE);
message = l10n_util::GetStringUTF16(
IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE);
break;
default:
NOTREACHED();
return reply;
}
// TODO(brettw). We should not be grabbing the active toplevel window, we
// should use the toplevel window associated with the render view.
aura::Window* parent = ash::Shell::GetContainer(
ash::Shell::GetTargetRootWindow(),
ash::internal::kShellWindowId_SystemModalContainer);
reply.params.set_result(static_cast<int32_t>(
chrome::ShowMessageBox(parent, title, message,
chrome::MESSAGE_BOX_TYPE_QUESTION) ==
chrome::MESSAGE_BOX_RESULT_YES));
#else
NOTIMPLEMENTED();
#endif
return reply;
}
void OnTerminateRemotingEventOnUIThread(const base::Closure& stop_callback) {
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
stop_callback);
}
ppapi::host::ReplyMessageContext StartRemotingOnUIThread(
const base::Closure& stop_callback,
int render_process_id,
int render_view_id,
ppapi::host::ReplyMessageContext reply) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
content::RenderViewHost* render_view_host =
content::RenderViewHost::FromID(render_process_id, render_view_id);
if (!render_view_host) {
reply.params.set_result(PP_ERROR_FAILED);
return reply; // RVH destroyed while task was pending.
}
#if defined(USE_ASH) && defined(OS_CHROMEOS)
base::Closure stop_callback_ui_thread = base::Bind(
&OnTerminateRemotingEventOnUIThread,
stop_callback);
ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStart(
stop_callback_ui_thread, base::string16());
reply.params.set_result(PP_OK);
#else
NOTIMPLEMENTED();
reply.params.set_result(PP_ERROR_NOTSUPPORTED);
#endif
return reply;
}
void StopRemotingOnUIThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
#if defined(USE_ASH) && defined(OS_CHROMEOS)
if (ash::Shell::GetInstance()) {
ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenShareStop();
}
#else
NOTIMPLEMENTED();
#endif
}
ppapi::host::ReplyMessageContext StopRemotingOnUIThreadWithResult(
ppapi::host::ReplyMessageContext reply) {
reply.params.set_result(PP_OK);
StopRemotingOnUIThread();
return reply;
}
} // namespace
PepperTalkHost::PepperTalkHost(content::BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource)
: ppapi::host::ResourceHost(host->GetPpapiHost(), instance, resource),
browser_ppapi_host_(host),
remoting_started_(false),
weak_factory_(this) {
}
PepperTalkHost::~PepperTalkHost() {
if (remoting_started_) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&StopRemotingOnUIThread));
}
}
int32_t PepperTalkHost::OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) {
IPC_BEGIN_MESSAGE_MAP(PepperTalkHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_Talk_RequestPermission,
OnRequestPermission)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting,
OnStartRemoting)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting,
OnStopRemoting)
IPC_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
int32_t PepperTalkHost::OnRequestPermission(
ppapi::host::HostMessageContext* context,
PP_TalkPermission permission) {
if (permission < PP_TALKPERMISSION_SCREENCAST ||
permission >= PP_TALKPERMISSION_NUM_PERMISSIONS)
return PP_ERROR_BADARGUMENT;
int render_process_id = 0;
int render_view_id = 0;
browser_ppapi_host_->GetRenderViewIDsForInstance(
pp_instance(), &render_process_id, &render_view_id);
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&GetPermissionOnUIThread, permission, render_process_id,
render_view_id, context->MakeReplyMessageContext()),
base::Bind(&PepperTalkHost::OnRequestPermissionCompleted,
weak_factory_.GetWeakPtr()));
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTalkHost::OnStartRemoting(
ppapi::host::HostMessageContext* context) {
int render_process_id = 0;
int render_view_id = 0;
browser_ppapi_host_->GetRenderViewIDsForInstance(
pp_instance(), &render_process_id, &render_view_id);
base::Closure remoting_stop_callback = base::Bind(
&PepperTalkHost::OnRemotingStopEvent,
weak_factory_.GetWeakPtr());
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&StartRemotingOnUIThread, remoting_stop_callback,
render_process_id, render_view_id,
context->MakeReplyMessageContext()),
base::Bind(&PepperTalkHost::OnStartRemotingCompleted,
weak_factory_.GetWeakPtr()));
return PP_OK_COMPLETIONPENDING;
}
int32_t PepperTalkHost::OnStopRemoting(
ppapi::host::HostMessageContext* context) {
content::BrowserThread::PostTaskAndReplyWithResult(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&StopRemotingOnUIThreadWithResult,
context->MakeReplyMessageContext()),
base::Bind(&PepperTalkHost::OnStopRemotingCompleted,
weak_factory_.GetWeakPtr()));
return PP_OK_COMPLETIONPENDING;
}
void PepperTalkHost::OnRemotingStopEvent() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
remoting_started_ = false;
host()->SendUnsolicitedReply(
pp_resource(), PpapiPluginMsg_Talk_NotifyEvent(PP_TALKEVENT_TERMINATE));
}
void PepperTalkHost::OnRequestPermissionCompleted(
ppapi::host::ReplyMessageContext reply) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
host()->SendReply(reply, PpapiPluginMsg_Talk_RequestPermissionReply());
}
void PepperTalkHost::OnStartRemotingCompleted(
ppapi::host::ReplyMessageContext reply) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
// Remember to hide remoting UI when resource is deleted.
if (reply.params.result() == PP_OK)
remoting_started_ = true;
host()->SendReply(reply, PpapiPluginMsg_Talk_StartRemotingReply());
}
void PepperTalkHost::OnStopRemotingCompleted(
ppapi::host::ReplyMessageContext reply) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
remoting_started_ = false;
host()->SendReply(reply, PpapiPluginMsg_Talk_StopRemotingReply());
}
} // namespace chrome