Home | History | Annotate | Download | only in pepper
      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_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"
     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 
     27 namespace chrome {
     28 
     29 namespace {
     30 
     31 ppapi::host::ReplyMessageContext GetPermissionOnUIThread(
     32     PP_TalkPermission permission,
     33     int render_process_id,
     34     int render_frame_id,
     35     ppapi::host::ReplyMessageContext reply) {
     36   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     37   reply.params.set_result(0);
     38 
     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.
     43 
     44 #if defined(USE_ASH)
     45   base::string16 title;
     46   base::string16 message;
     47 
     48   switch (permission) {
     49     case PP_TALKPERMISSION_SCREENCAST:
     50       title = l10n_util::GetStringUTF16(IDS_GTALK_SCREEN_SHARE_DIALOG_TITLE);
     51       message =
     52           l10n_util::GetStringUTF16(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(IDS_GTALK_REMOTING_DIALOG_MESSAGE);
     57       break;
     58     case PP_TALKPERMISSION_REMOTING_CONTINUE:
     59       title = l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_DIALOG_TITLE);
     60       message =
     61           l10n_util::GetStringUTF16(IDS_GTALK_REMOTING_CONTINUE_DIALOG_MESSAGE);
     62       break;
     63     default:
     64       NOTREACHED();
     65       return reply;
     66   }
     67 
     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));
     77 #else
     78   NOTIMPLEMENTED();
     79 #endif
     80   return reply;
     81 }
     82 
     83 #if defined(USE_ASH) && defined(OS_CHROMEOS)
     84 void OnTerminateRemotingEventOnUIThread(const base::Closure& stop_callback) {
     85   content::BrowserThread::PostTask(
     86       content::BrowserThread::IO, FROM_HERE, stop_callback);
     87 }
     88 #endif  // defined(USE_ASH) && defined(OS_CHROMEOS)
     89 
     90 ppapi::host::ReplyMessageContext StartRemotingOnUIThread(
     91     const base::Closure& stop_callback,
     92     int render_process_id,
     93     int render_frame_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.
    101   }
    102 
    103 #if defined(USE_ASH) && defined(OS_CHROMEOS)
    104   base::Closure stop_callback_ui_thread =
    105       base::Bind(&OnTerminateRemotingEventOnUIThread, 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 
    117 void 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 
    128 ppapi::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 
    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) {}
    144 
    145 PepperTalkHost::~PepperTalkHost() {
    146   if (remoting_started_) {
    147     content::BrowserThread::PostTask(content::BrowserThread::UI,
    148                                      FROM_HERE,
    149                                      base::Bind(&StopRemotingOnUIThread));
    150   }
    151 }
    152 
    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,
    158                                       OnRequestPermission)
    159     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StartRemoting,
    160                                         OnStartRemoting)
    161     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_Talk_StopRemoting,
    162                                         OnStopRemoting)
    163   PPAPI_END_MESSAGE_MAP()
    164   return PP_ERROR_FAILED;
    165 }
    166 
    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;
    173 
    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);
    178 
    179   content::BrowserThread::PostTaskAndReplyWithResult(
    180       content::BrowserThread::UI,
    181       FROM_HERE,
    182       base::Bind(&GetPermissionOnUIThread,
    183                  permission,
    184                  render_process_id,
    185                  render_frame_id,
    186                  context->MakeReplyMessageContext()),
    187       base::Bind(&PepperTalkHost::OnRequestPermissionCompleted,
    188                  weak_factory_.GetWeakPtr()));
    189   return PP_OK_COMPLETIONPENDING;
    190 }
    191 
    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);
    198 
    199   base::Closure remoting_stop_callback = base::Bind(
    200       &PepperTalkHost::OnRemotingStopEvent, weak_factory_.GetWeakPtr());
    201 
    202   content::BrowserThread::PostTaskAndReplyWithResult(
    203       content::BrowserThread::UI,
    204       FROM_HERE,
    205       base::Bind(&StartRemotingOnUIThread,
    206                  remoting_stop_callback,
    207                  render_process_id,
    208                  render_frame_id,
    209                  context->MakeReplyMessageContext()),
    210       base::Bind(&PepperTalkHost::OnStartRemotingCompleted,
    211                  weak_factory_.GetWeakPtr()));
    212   return PP_OK_COMPLETIONPENDING;
    213 }
    214 
    215 int32_t PepperTalkHost::OnStopRemoting(
    216     ppapi::host::HostMessageContext* context) {
    217   content::BrowserThread::PostTaskAndReplyWithResult(
    218       content::BrowserThread::UI,
    219       FROM_HERE,
    220       base::Bind(&StopRemotingOnUIThreadWithResult,
    221                  context->MakeReplyMessageContext()),
    222       base::Bind(&PepperTalkHost::OnStopRemotingCompleted,
    223                  weak_factory_.GetWeakPtr()));
    224   return PP_OK_COMPLETIONPENDING;
    225 }
    226 
    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));
    232 }
    233 
    234 void PepperTalkHost::OnRequestPermissionCompleted(
    235     ppapi::host::ReplyMessageContext reply) {
    236   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
    237   host()->SendReply(reply, PpapiPluginMsg_Talk_RequestPermissionReply());
    238 }
    239 
    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;
    246 
    247   host()->SendReply(reply, PpapiPluginMsg_Talk_StartRemotingReply());
    248 }
    249 
    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());
    255 }
    256 
    257 }  // namespace chrome
    258