Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: ppapi/proxy/plugin_dispatcher.cc

Issue 6286070: Remove all uses of the global Dispatcher Get function. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/plugin_dispatcher.h" 5 #include "ppapi/proxy/plugin_dispatcher.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "ipc/ipc_message.h" 11 #include "ipc/ipc_message.h"
12 #include "ipc/ipc_sync_channel.h" 12 #include "ipc/ipc_sync_channel.h"
13 #include "ppapi/c/pp_errors.h" 13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/proxy/interface_proxy.h" 14 #include "ppapi/proxy/interface_proxy.h"
15 #include "ppapi/proxy/plugin_var_serialization_rules.h" 15 #include "ppapi/proxy/plugin_var_serialization_rules.h"
16 #include "ppapi/proxy/ppapi_messages.h" 16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/proxy/ppp_class_proxy.h" 17 #include "ppapi/proxy/ppp_class_proxy.h"
18 18
19 namespace pp { 19 namespace pp {
20 namespace proxy { 20 namespace proxy {
21 21
22 namespace { 22 namespace {
23 23
24 PluginDispatcher* g_dispatcher = NULL; 24 typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
25 InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
25 26
26 const void* GetInterfaceFromDispatcher(const char* interface) { 27 const void* GetInterfaceFromDispatcher(const char* interface) {
27 // TODO(brettw) need some kind of lock for multi-thread access. 28 // All interfaces the plugin requests of the browser are "PPB".
28 return pp::proxy::PluginDispatcher::Get()->GetProxiedInterface(interface); 29 const InterfaceProxy::Info* info = Dispatcher::GetPPBInterfaceInfo(interface);
30 if (!info)
31 return NULL;
32 return info->interface;
29 } 33 }
30 34
31 } // namespace 35 } // namespace
32 36
33 PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle, 37 PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
34 GetInterfaceFunc get_interface, 38 GetInterfaceFunc get_interface,
35 InitModuleFunc init_module, 39 InitModuleFunc init_module,
36 ShutdownModuleFunc shutdown_module) 40 ShutdownModuleFunc shutdown_module)
37 : Dispatcher(remote_process_handle, get_interface), 41 : Dispatcher(remote_process_handle, get_interface),
38 init_module_(init_module), 42 init_module_(init_module),
39 shutdown_module_(shutdown_module) { 43 shutdown_module_(shutdown_module) {
40 SetSerializationRules(new PluginVarSerializationRules); 44 SetSerializationRules(new PluginVarSerializationRules);
41 45
42 // As a plugin, we always support the PPP_Class interface. There's no 46 // As a plugin, we always support the PPP_Class interface. There's no
43 // GetInterface call or name for it, so we insert it into our table now. 47 // GetInterface call or name for it, so we insert it into our table now.
44 InjectProxy(INTERFACE_ID_PPP_CLASS, "$Internal_PPP_Class", 48 target_proxies_[INTERFACE_ID_PPP_CLASS].reset(new PPP_Class_Proxy(this));
45 new PPP_Class_Proxy(this));
46 } 49 }
47 50
48 PluginDispatcher::~PluginDispatcher() { 51 PluginDispatcher::~PluginDispatcher() {
49 if (shutdown_module_) 52 if (shutdown_module_)
50 shutdown_module_(); 53 shutdown_module_();
51 } 54 }
52 55
53 // static 56 // static
54 PluginDispatcher* PluginDispatcher::Get() {
55 return g_dispatcher;
56 }
57
58 // static
59 void PluginDispatcher::SetGlobal(PluginDispatcher* dispatcher) {
60 DCHECK(!dispatcher || !g_dispatcher);
61 g_dispatcher = dispatcher;
62 }
63
64 // static
65 PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) { 57 PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
66 // TODO(brettw) implement "real" per-instance dispatcher map. 58 if (!g_instance_to_dispatcher)
67 DCHECK(instance != 0); 59 return NULL;
68 return Get(); 60 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
61 instance);
62 if (found == g_instance_to_dispatcher->end())
63 return NULL;
64 return found->second;
65 }
66
67 // static
68 void PluginDispatcher::SetForInstance(PP_Instance instance,
69 PluginDispatcher* dispatcher) {
70 if (!g_instance_to_dispatcher)
71 g_instance_to_dispatcher = new InstanceToDispatcherMap;
72 (*g_instance_to_dispatcher)[instance] = dispatcher;
73 }
74
75 // static
76 void PluginDispatcher::RemoveForInstance(PP_Instance instance) {
77 if (!g_instance_to_dispatcher)
78 return;
79 InstanceToDispatcherMap::iterator found = g_instance_to_dispatcher->find(
80 instance);
81 if (found != g_instance_to_dispatcher->end())
82 g_instance_to_dispatcher->erase(found);
69 } 83 }
70 84
71 bool PluginDispatcher::IsPlugin() const { 85 bool PluginDispatcher::IsPlugin() const {
72 return true; 86 return true;
73 } 87 }
74 88
75 bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) { 89 bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
90 // Handle common control messages.
91 if (Dispatcher::OnMessageReceived(msg))
92 return true;
93
76 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 94 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
77 // Handle some plugin-specific control messages. 95 // Handle some plugin-specific control messages.
78 bool handled = true; 96 bool handled = true;
79 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg) 97 IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
98 IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
80 IPC_MESSAGE_HANDLER(PpapiMsg_InitializeModule, OnMsgInitializeModule) 99 IPC_MESSAGE_HANDLER(PpapiMsg_InitializeModule, OnMsgInitializeModule)
81 IPC_MESSAGE_HANDLER(PpapiMsg_Shutdown, OnMsgShutdown) 100 IPC_MESSAGE_HANDLER(PpapiMsg_Shutdown, OnMsgShutdown)
82
83 // Forward all other control messages to the superclass.
84 IPC_MESSAGE_UNHANDLED(handled = Dispatcher::OnMessageReceived(msg))
85 IPC_END_MESSAGE_MAP() 101 IPC_END_MESSAGE_MAP()
86 return handled; 102 return handled;
87 } 103 }
88 104
89 // All non-control messages get handled by the superclass. 105 if (msg.routing_id() <= 0 && msg.routing_id() >= INTERFACE_ID_COUNT) {
90 return Dispatcher::OnMessageReceived(msg); 106 // Host is sending us garbage. Since it's supposed to be trusted, this
107 // isn't supposed to happen.
piman 2011/02/07 21:29:22 Should we just crash here ? To prevent a compromis
brettw 2011/02/08 00:28:04 Sure.
108 NOTREACHED();
109 return true;
110 }
111
112 // There are two cases:
113 //
114 // * The first case is that the host is calling a PPP interface. It will
115 // always do a check for the interface before sending messages, and this
116 // will create the necessary interface proxy at that time. So when we
117 // actually receive a message, we know such a proxy will exist.
118 //
119 // * The second case is that the host is sending a response to the plugin
120 // side of a PPB interface (some, like the URL loader, have complex
121 // response messages). Since the host is trusted and not supposed to be
122 // doing silly things, we can just create a PPB proxy project on demand the
123 // first time it's needed.
124
125 InterfaceProxy* proxy = target_proxies_[msg.routing_id()].get();
126 if (!proxy) {
127 // Handle the first time the host calls a PPB reply interface by
128 // autocreating it.
129 const InterfaceProxy::Info* info = GetPPBInterfaceInfo(
130 static_cast<InterfaceID>(msg.routing_id()));
131 if (!info) {
132 NOTREACHED();
133 return true;
134 }
135 proxy = info->create(this, NULL);
136 target_proxies_[info->id].reset(proxy);
137 }
138
139 return proxy->OnMessageReceived(msg);
91 } 140 }
92 141
93 void PluginDispatcher::DidCreateInstance(PP_Instance instance) { 142 void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
94 instance_map_[instance] = InstanceData(); 143 instance_map_[instance] = InstanceData();
95 } 144 }
96 145
97 void PluginDispatcher::DidDestroyInstance(PP_Instance instance) { 146 void PluginDispatcher::DidDestroyInstance(PP_Instance instance) {
98 InstanceDataMap::iterator it = instance_map_.find(instance); 147 InstanceDataMap::iterator it = instance_map_.find(instance);
99 if (it != instance_map_.end()) 148 if (it != instance_map_.end())
100 instance_map_.erase(it); 149 instance_map_.erase(it);
101 } 150 }
102 151
103 InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) { 152 InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
104 InstanceDataMap::iterator it = instance_map_.find(instance); 153 InstanceDataMap::iterator it = instance_map_.find(instance);
105 return (it == instance_map_.end()) ? NULL : &it->second; 154 return (it == instance_map_.end()) ? NULL : &it->second;
106 } 155 }
107 156
108 void PluginDispatcher::OnMsgInitializeModule(PP_Module pp_module, 157 void PluginDispatcher::OnMsgInitializeModule(PP_Module pp_module,
109 bool* result) { 158 bool* result) {
110 set_pp_module(pp_module); 159 set_pp_module(pp_module);
111 *result = init_module_(pp_module, &GetInterfaceFromDispatcher) == PP_OK; 160 *result = init_module_(pp_module, &GetInterfaceFromDispatcher) == PP_OK;
112 } 161 }
113 162
114 void PluginDispatcher::OnMsgShutdown() { 163 void PluginDispatcher::OnMsgShutdown() {
115 if (shutdown_module_) 164 if (shutdown_module_)
116 shutdown_module_(); 165 shutdown_module_();
117 MessageLoop::current()->Quit(); 166 MessageLoop::current()->Quit();
118 } 167 }
119 168
169 void PluginDispatcher::OnMsgSupportsInterface(
170 const std::string& interface_name,
171 bool* result) {
172 *result = false;
173
174 // Setup a proxy for receiving the messages from this interface.
175 const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface_name);
176 if (!info)
177 return; // Interface not supported by proxy.
178
179 // Check for a cached result.
180 if (target_proxies_[info->id].get()) {
181 *result = true;
182 return;
183 }
184
185 // Query the plugin & cache the result.
186 const void* interface_functions = GetLocalInterface(interface_name.c_str());
187 if (!interface_functions)
188 return;
189 target_proxies_[info->id].reset(info->create(this, interface_functions));
190 *result = true;
191 }
192
120 } // namespace proxy 193 } // namespace proxy
121 } // namespace pp 194 } // namespace pp
122 195
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698