summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/plugin_dispatcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/proxy/plugin_dispatcher.cc')
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc109
1 files changed, 90 insertions, 19 deletions
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 7afd3d6..bb42fcb7 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -13,7 +13,6 @@
#include "ipc/ipc_sync_channel.h"
#include "base/debug/trace_event.h"
#include "ppapi/c/pp_errors.h"
-#include "ppapi/proxy/interface_list.h"
#include "ppapi/proxy/interface_proxy.h"
#include "ppapi/proxy/plugin_message_filter.h"
#include "ppapi/proxy/plugin_resource_tracker.h"
@@ -54,6 +53,11 @@ PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
received_preferences_(false),
plugin_dispatcher_id_(0) {
SetSerializationRules(new PluginVarSerializationRules);
+
+ // As a plugin, we always support the PPP_Class interface. There's no
+ // GetInterface call or name for it, so we insert it into our table now.
+ target_proxies_[INTERFACE_ID_PPP_CLASS].reset(new PPP_Class_Proxy(this));
+
TrackerBase::Init(&PluginResourceTracker::GetTrackerBaseInstance);
}
@@ -79,19 +83,13 @@ PluginDispatcher* PluginDispatcher::GetForResource(const Resource* resource) {
}
// static
-const void* PluginDispatcher::GetBrowserInterface(const char* interface_name) {
- return InterfaceList::GetInstance()->GetInterfaceForPPB(interface_name);
-}
-
-const void* PluginDispatcher::GetPluginInterface(
- const std::string& interface_name) {
- InterfaceMap::iterator found = plugin_interfaces_.find(interface_name);
- if (found == plugin_interfaces_.end()) {
- const void* ret = local_get_interface()(interface_name.c_str());
- plugin_interfaces_.insert(std::make_pair(interface_name, ret));
- return ret;
- }
- return found->second;
+const void* PluginDispatcher::GetInterfaceFromDispatcher(
+ const char* dispatcher_interface) {
+ // All interfaces the plugin requests of the browser are "PPB".
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(dispatcher_interface);
+ if (!info)
+ return NULL;
+ return info->interface_ptr;
}
bool PluginDispatcher::InitPluginWithChannel(
@@ -133,18 +131,56 @@ bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
TRACE_EVENT2("ppapi proxy", "PluginDispatcher::OnMessageReceived",
"Class", IPC_MESSAGE_ID_CLASS(msg.type()),
"Line", IPC_MESSAGE_ID_LINE(msg.type()));
+ // Handle common control messages.
+ if (Dispatcher::OnMessageReceived(msg))
+ return true;
+
if (msg.routing_id() == MSG_ROUTING_CONTROL) {
// Handle some plugin-specific control messages.
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
IPC_MESSAGE_HANDLER(PpapiMsg_SetPreferences, OnMsgSetPreferences)
- IPC_MESSAGE_UNHANDLED(handled = false);
IPC_END_MESSAGE_MAP()
- if (handled)
+ return handled;
+ }
+
+ if (msg.routing_id() <= 0 || msg.routing_id() >= INTERFACE_ID_COUNT) {
+ // Host is sending us garbage. Since it's supposed to be trusted, this
+ // isn't supposed to happen. Crash here in all builds in case the renderer
+ // is compromised.
+ CHECK(false);
+ return true;
+ }
+
+ // There are two cases:
+ //
+ // * The first case is that the host is calling a PPP interface. It will
+ // always do a check for the interface before sending messages, and this
+ // will create the necessary interface proxy at that time. So when we
+ // actually receive a message, we know such a proxy will exist.
+ //
+ // * The second case is that the host is sending a response to the plugin
+ // side of a PPB interface (some, like the URL loader, have complex
+ // response messages). Since the host is trusted and not supposed to be
+ // doing silly things, we can just create a PPB proxy project on demand the
+ // first time it's needed.
+
+ InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get();
+ if (!proxy) {
+ // Handle the first time the host calls a PPB reply interface by
+ // autocreating it.
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(
+ static_cast<InterfaceID>(msg.routing_id()));
+ if (!info) {
+ NOTREACHED();
return true;
+ }
+ proxy = info->create_proxy(this, NULL);
+ target_proxies_[info->id].reset(proxy);
}
- return Dispatcher::OnMessageReceived(msg);
+
+ return proxy->OnMessageReceived(msg);
}
void PluginDispatcher::OnChannelError() {
@@ -202,7 +238,23 @@ WebKitForwarding* PluginDispatcher::GetWebKitForwarding() {
}
FunctionGroupBase* PluginDispatcher::GetFunctionAPI(InterfaceID id) {
- return GetInterfaceProxy(id);
+ scoped_ptr<FunctionGroupBase >& proxy = function_proxies_[id];
+
+ if (proxy.get())
+ return proxy.get();
+
+ if (id == INTERFACE_ID_PPB_CHAR_SET)
+ proxy.reset(new PPB_CharSet_Proxy(this, NULL));
+ else if(id == INTERFACE_ID_PPB_CURSORCONTROL)
+ proxy.reset(new PPB_CursorControl_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_PPB_FONT)
+ proxy.reset(new PPB_Font_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_PPB_INSTANCE)
+ proxy.reset(new PPB_Instance_Proxy(this, NULL));
+ else if (id == INTERFACE_ID_RESOURCE_CREATION)
+ proxy.reset(new ResourceCreationProxy(this));
+
+ return proxy.get();
}
void PluginDispatcher::ForceFreeAllInstances() {
@@ -226,7 +278,26 @@ void PluginDispatcher::ForceFreeAllInstances() {
void PluginDispatcher::OnMsgSupportsInterface(
const std::string& interface_name,
bool* result) {
- *result = !!GetPluginInterface(interface_name);
+ *result = false;
+
+ // Setup a proxy for receiving the messages from this interface.
+ const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface_name);
+ if (!info)
+ return; // Interface not supported by proxy.
+
+ // Check for a cached result.
+ if (target_proxies_[info->id].get()) {
+ *result = true;
+ return;
+ }
+
+ // Query the plugin & cache the result.
+ const void* interface_functions = GetLocalInterface(interface_name.c_str());
+ if (!interface_functions)
+ return;
+ target_proxies_[info->id].reset(
+ info->create_proxy(this, interface_functions));
+ *result = true;
}
void PluginDispatcher::OnMsgSetPreferences(const Preferences& prefs) {