Home | History | Annotate | Download | only in proxy
      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 "ppapi/proxy/ppp_messaging_proxy.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "ppapi/c/ppp_messaging.h"
     10 #include "ppapi/proxy/host_dispatcher.h"
     11 #include "ppapi/proxy/message_handler.h"
     12 #include "ppapi/proxy/plugin_dispatcher.h"
     13 #include "ppapi/proxy/plugin_resource_tracker.h"
     14 #include "ppapi/proxy/plugin_var_tracker.h"
     15 #include "ppapi/proxy/ppapi_messages.h"
     16 #include "ppapi/proxy/serialized_var.h"
     17 #include "ppapi/shared_impl/ppapi_globals.h"
     18 #include "ppapi/shared_impl/proxy_lock.h"
     19 #include "ppapi/shared_impl/scoped_pp_var.h"
     20 #include "ppapi/shared_impl/var_tracker.h"
     21 
     22 namespace ppapi {
     23 namespace proxy {
     24 
     25 namespace {
     26 
     27 MessageHandler* GetMessageHandler(Dispatcher* dispatcher,
     28                                   PP_Instance instance) {
     29   if (!dispatcher || !dispatcher->IsPlugin()) {
     30     NOTREACHED();
     31     return NULL;
     32   }
     33   PluginDispatcher* plugin_dispatcher =
     34       static_cast<PluginDispatcher*>(dispatcher);
     35   InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance);
     36   if (!instance_data)
     37     return NULL;
     38 
     39   return instance_data->message_handler.get();
     40 }
     41 
     42 void ResetMessageHandler(Dispatcher* dispatcher, PP_Instance instance) {
     43   if (!dispatcher || !dispatcher->IsPlugin()) {
     44     NOTREACHED();
     45     return;
     46   }
     47   PluginDispatcher* plugin_dispatcher =
     48       static_cast<PluginDispatcher*>(dispatcher);
     49   InstanceData* instance_data = plugin_dispatcher->GetInstanceData(instance);
     50   if (!instance_data)
     51     return;
     52 
     53   instance_data->message_handler.reset();
     54 }
     55 
     56 }  // namespace
     57 
     58 PPP_Messaging_Proxy::PPP_Messaging_Proxy(Dispatcher* dispatcher)
     59     : InterfaceProxy(dispatcher),
     60       ppp_messaging_impl_(NULL) {
     61   if (dispatcher->IsPlugin()) {
     62     ppp_messaging_impl_ = static_cast<const PPP_Messaging*>(
     63         dispatcher->local_get_interface()(PPP_MESSAGING_INTERFACE));
     64   }
     65 }
     66 
     67 PPP_Messaging_Proxy::~PPP_Messaging_Proxy() {
     68 }
     69 
     70 bool PPP_Messaging_Proxy::OnMessageReceived(const IPC::Message& msg) {
     71   if (!dispatcher()->IsPlugin())
     72     return false;
     73 
     74   bool handled = true;
     75   IPC_BEGIN_MESSAGE_MAP(PPP_Messaging_Proxy, msg)
     76     IPC_MESSAGE_HANDLER(PpapiMsg_PPPMessaging_HandleMessage,
     77                         OnMsgHandleMessage)
     78     IPC_MESSAGE_HANDLER_DELAY_REPLY(
     79         PpapiMsg_PPPMessageHandler_HandleBlockingMessage,
     80         OnMsgHandleBlockingMessage)
     81     IPC_MESSAGE_UNHANDLED(handled = false)
     82   IPC_END_MESSAGE_MAP()
     83   return handled;
     84 }
     85 
     86 void PPP_Messaging_Proxy::OnMsgHandleMessage(
     87     PP_Instance instance, SerializedVarReceiveInput message_data) {
     88   PP_Var received_var(message_data.GetForInstance(dispatcher(), instance));
     89   MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance);
     90   if (message_handler) {
     91     if (message_handler->LoopIsValid()) {
     92       message_handler->HandleMessage(ScopedPPVar(received_var));
     93       return;
     94     } else {
     95       // If the MessageHandler's loop has been quit, then we should treat it as
     96       // though it has been unregistered and start sending messages to the
     97       // default handler. This might mean the plugin has lost messages, but
     98       // there's not really anything sane we can do about it. They should have
     99       // used UnregisterMessageHandler.
    100       ResetMessageHandler(dispatcher(), instance);
    101     }
    102   }
    103   // If we reach this point, then there's no message handler registered, so
    104   // we send to the default PPP_Messaging one for the instance.
    105 
    106   // SerializedVarReceiveInput will decrement the reference count, but we want
    107   // to give the recipient a reference in the legacy API.
    108   PpapiGlobals::Get()->GetVarTracker()->AddRefVar(received_var);
    109   CallWhileUnlocked(ppp_messaging_impl_->HandleMessage,
    110                     instance,
    111                     received_var);
    112 }
    113 
    114 void PPP_Messaging_Proxy::OnMsgHandleBlockingMessage(
    115     PP_Instance instance,
    116     SerializedVarReceiveInput message_data,
    117     IPC::Message* reply_msg) {
    118   ScopedPPVar received_var(message_data.GetForInstance(dispatcher(), instance));
    119   MessageHandler* message_handler = GetMessageHandler(dispatcher(), instance);
    120   if (message_handler) {
    121     if (message_handler->LoopIsValid()) {
    122       message_handler->HandleBlockingMessage(
    123           received_var, scoped_ptr<IPC::Message>(reply_msg));
    124       return;
    125     } else {
    126       // If the MessageHandler's loop has been quit, then we should treat it as
    127       // though it has been unregistered. Also see the note for PostMessage.
    128       ResetMessageHandler(dispatcher(), instance);
    129     }
    130   }
    131   // We have no handler, but we still need to respond to unblock the renderer
    132   // and inform the JavaScript caller.
    133   PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams(
    134       reply_msg,
    135       SerializedVarReturnValue::Convert(dispatcher(), PP_MakeUndefined()),
    136       false /* was_handled */);
    137   dispatcher()->Send(reply_msg);
    138 }
    139 
    140 
    141 }  // namespace proxy
    142 }  // namespace ppapi
    143