Index: ppapi/proxy/plugin_dispatcher.cc |
=================================================================== |
--- ppapi/proxy/plugin_dispatcher.cc (revision 100753) |
+++ ppapi/proxy/plugin_dispatcher.cc (working copy) |
@@ -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" |
@@ -50,6 +49,11 @@ |
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); |
} |
@@ -75,21 +79,15 @@ |
} |
// static |
-const void* PluginDispatcher::GetBrowserInterface(const char* interface) { |
- return InterfaceList::GetInstance()->GetInterfaceForPPB(interface); |
+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; |
} |
-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; |
-} |
- |
bool PluginDispatcher::InitPluginWithChannel( |
PluginDelegate* delegate, |
const IPC::ChannelHandle& channel_handle, |
@@ -129,18 +127,56 @@ |
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() { |
@@ -198,7 +234,23 @@ |
} |
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() { |
@@ -222,7 +274,26 @@ |
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) { |