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

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

Issue 6833002: Implemented PPB_Broker_Proxy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed check for valid handle in GetHandle. Makes GetHandle behave the same whether proxied or not. Created 9 years, 8 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
(Empty)
1 // Copyright (c) 2011 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/ppb_broker_proxy.h"
6
7 #include "ppapi/c/pp_errors.h"
8 #include "ppapi/c/trusted/ppb_broker_trusted.h"
9 #include "ppapi/proxy/plugin_dispatcher.h"
10 #include "ppapi/proxy/plugin_resource.h"
11 #include "ppapi/proxy/ppapi_messages.h"
12
13 namespace pp {
14 namespace proxy {
15
16 class Broker : public PluginResource {
17 public:
18 explicit Broker(const HostResource& resource);
19 virtual ~Broker();
20
21 // Resource overrides.
22 virtual Broker* AsBroker() { return this; }
23
24 bool called_connect_;
25 PP_CompletionCallback current_connect_callback_;
26 base::SyncSocket::Handle socket_handle_;
27
28 private:
29 DISALLOW_COPY_AND_ASSIGN(Broker);
30 };
31
32 Broker::Broker(const HostResource& resource)
33 : PluginResource(resource),
34 called_connect_(false),
35 current_connect_callback_(PP_MakeCompletionCallback(NULL, NULL)),
36 socket_handle_(base::kInvalidPlatformFileValue) {
37
38 // The plugin owns the handle.
39 socket_handle_ = base::kInvalidPlatformFileValue;
brettw 2011/04/15 16:09:25 You set this above. I don't see where this handle
ddorwin 2011/04/15 18:41:32 This was supposed to be in the destructor. Moved.
40 }
41
42 Broker::~Broker() {
43 // Ensure the callback is always fired.
44 if (current_connect_callback_.func) {
45 // TODO(brettw) the callbacks at this level should be refactored with a
46 // more automatic tracking system like we have in the renderer.
47 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
48 current_connect_callback_.func, current_connect_callback_.user_data,
49 static_cast<int32_t>(PP_ERROR_ABORTED)));
50 }
51 }
52
53 namespace {
54
55 PP_Resource CreateTrusted(PP_Instance instance) {
56 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
57 if (!dispatcher)
58 return 0;
59
60 HostResource result;
61 dispatcher->Send(new PpapiHostMsg_PPBBroker_Create(
62 INTERFACE_ID_PPB_BROKER, instance, &result));
63 if (result.is_null())
64 return 0;
65
66 linked_ptr<Broker> object(new Broker(result));
67 return PluginResourceTracker::GetInstance()->AddResource(object);
68 }
69
70 PP_Bool IsBrokerTrusted(PP_Resource resource) {
71 Broker* object = PluginResource::GetAs<Broker>(resource);
72 return BoolToPPBool(!!object);
73 }
74
75 int32_t Connect(PP_Resource resource,
76 PP_CompletionCallback connect_callback) {
77 Broker* object = PluginResource::GetAs<Broker>(resource);
78 if (!object)
79 return PP_ERROR_BADRESOURCE;
80
81 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance());
82 if (!dispatcher)
83 return PP_ERROR_BADRESOURCE;
84
85 if (!connect_callback.func) {
86 // Synchronous calls are not supported.
87 return PP_ERROR_BADARGUMENT;
88 }
89
90 if (object->current_connect_callback_.func)
91 return PP_ERROR_INPROGRESS;
92 else if (object->called_connect_)
93 return PP_ERROR_FAILED;
94
95 object->current_connect_callback_ = connect_callback;
96 object->called_connect_ = true;
97
98 bool success = dispatcher->Send(new PpapiHostMsg_PPBBroker_Connect(
99 INTERFACE_ID_PPB_BROKER,
100 object->host_resource()));
101 return success ? PP_ERROR_WOULDBLOCK/*after merge: PP_OK_COMPLETIONPENDING*/ : PP_ERROR_FAILED;
brettw 2011/04/15 16:09:25 Did you mean to update this?
ddorwin 2011/04/15 18:41:32 Yes. Once I get an LGTM, I'll sync and change this
102 }
103
104 int32_t GetHandle(PP_Resource resource, int32_t* handle) {
105 Broker* object = PluginResource::GetAs<Broker>(resource);
106 if (!object)
107 return PP_ERROR_BADRESOURCE;
108 *handle = object->socket_handle_;
109 return PP_OK;
110 }
111
112 const PPB_BrokerTrusted broker_interface = {
113 &CreateTrusted,
114 &IsBrokerTrusted,
115 &Connect,
116 &GetHandle,
117 };
118
119 InterfaceProxy* CreateBrokerProxy(Dispatcher* dispatcher,
120 const void* target_interface) {
121 return new PPB_Broker_Proxy(dispatcher, target_interface);
122 }
123
124 base::PlatformFile IntToPlatformFile(int32_t handle) {
125 #if defined(OS_WIN)
126 return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
127 #elif defined(OS_POSIX)
128 return handle;
129 #else
130 #error Not implemented.
131 #endif
132 }
133
134 } // namespace
135
136 PPB_Broker_Proxy::PPB_Broker_Proxy(Dispatcher* dispatcher,
137 const void* target_interface)
138 : InterfaceProxy(dispatcher, target_interface) ,
139 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)){
140 }
141
142 PPB_Broker_Proxy::~PPB_Broker_Proxy() {
143 }
144
145 // static
146 const InterfaceProxy::Info* PPB_Broker_Proxy::GetInfo() {
147 static const Info info = {
148 &broker_interface,
149 PPB_BROKER_TRUSTED_INTERFACE,
150 INTERFACE_ID_PPB_BROKER,
151 true,
152 &CreateBrokerProxy,
153 };
154 return &info;
155 }
156
157 bool PPB_Broker_Proxy::OnMessageReceived(const IPC::Message& msg) {
158 bool handled = true;
159 IPC_BEGIN_MESSAGE_MAP(PPB_Broker_Proxy, msg)
160 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Create, OnMsgCreate)
161 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Connect, OnMsgConnect)
162 IPC_MESSAGE_HANDLER(PpapiMsg_PPBBroker_ConnectComplete,
163 OnMsgConnectComplete)
164 IPC_MESSAGE_UNHANDLED(handled = false)
165 IPC_END_MESSAGE_MAP()
166 return handled;
167 }
168
169 void PPB_Broker_Proxy::OnMsgCreate(PP_Instance instance,
170 HostResource* result_resource) {
171 result_resource->SetHostResource(
172 instance,
173 ppb_broker_target()->CreateTrusted(instance));
174 }
175
176 void PPB_Broker_Proxy::OnMsgConnect(const HostResource& broker) {
177 CompletionCallback callback = callback_factory_.NewCallback(
178 &PPB_Broker_Proxy::ConnectCompleteInHost, broker);
179
180 int32_t result = ppb_broker_target()->Connect(
181 broker.host_resource(),
182 callback.pp_completion_callback());
183 if (result != PP_ERROR_WOULDBLOCK/*after merge: PP_OK_COMPLETIONPENDING*/)
184 callback.Run(result);
185 }
186
187 // Called in the plugin to handle the connect callback.
188 // The proxy owns the handle and transfers it to the Broker. At that point,
189 // the plugin owns the handle and is responsible for closing it.
190 // The caller guarantees that socket_handle is not valid if result is not PP_OK.
191 void PPB_Broker_Proxy::OnMsgConnectComplete(
192 const HostResource& broker,
193 IPC::PlatformFileForTransit socket_handle,
194 int32_t result) {
195 DCHECK(result == PP_OK ||
196 socket_handle == IPC::InvalidPlatformFileForTransit());
197
198 Broker* object = NULL;
199 if (result == PP_OK) {
200 object = PluginResource::GetAs<Broker>(
201 PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
202 broker));
203 if (!object)
204 result = PP_ERROR_BADRESOURCE;
205 }
206
207 if (result == PP_OK) {
208 object->socket_handle_ =
209 IPC::PlatformFileForTransitToPlatformFile(socket_handle);
210 } else {
211 // The caller may still have given us a handle in the failure case.
212 // The easiest way to clean it up is to just put it in an object
213 // and then close them. This failure case is not performance critical.
214 base::SyncSocket temp_socket(
215 IPC::PlatformFileForTransitToPlatformFile(socket_handle));
216 }
217
218 if (!object->current_connect_callback_.func) {
219 // The handle might leak if the plugin never calls GetHandle().
220 return;
221 }
222
223 PP_CompletionCallback callback = object->current_connect_callback_;
224 object->current_connect_callback_ = PP_MakeCompletionCallback(NULL, NULL);
225 PP_RunCompletionCallback(&callback, result);
226 }
227
228 // Callback on the host side.
229 // Transfers ownership of the handle to the plugin side. This function must
230 // either successfully call the callback or close the handle.
231 void PPB_Broker_Proxy::ConnectCompleteInHost(int32_t result,
232 const HostResource& broker) {
233 IPC::PlatformFileForTransit foreign_socket_handle =
234 IPC::InvalidPlatformFileForTransit();
235 if (result == PP_OK) {
236 int32_t socket_handle = base::kInvalidPlatformFileValue;
237 result = ppb_broker_target()->GetHandle(broker.host_resource(),
238 &socket_handle);
239 DCHECK(result == PP_OK ||
240 socket_handle == base::kInvalidPlatformFileValue);
241
242 if (result == PP_OK) {
243 foreign_socket_handle =
244 dispatcher()->ShareHandleWithRemote(IntToPlatformFile(socket_handle),
245 true);
brettw 2011/04/15 16:09:25 I'm unclear on the ownership of this handle also.
ddorwin 2011/04/15 18:41:32 As I mentioned above, PPB_Broker_Impl never owns t
246 if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit()) {
247 result = PP_ERROR_FAILED;
248 // Assume the local handle was closed even if the foreign handle could
249 // not be created.
250 }
251 }
252 }
253 DCHECK(result == PP_OK ||
254 foreign_socket_handle == IPC::InvalidPlatformFileForTransit());
255
256 bool success = dispatcher()->Send(new PpapiMsg_PPBBroker_ConnectComplete(
257 INTERFACE_ID_PPB_FILE_SYSTEM, broker, foreign_socket_handle, result));
258
259 if (!success || result == PP_OK) {
260 // The plugin did not receive the handle, so it must be closed.
261 // The easiest way to clean it up is to just put it in an object
262 // and then close it. This failure case is not performance critical.
263 // The handle could still leak if Send succeeded but the IPC later failed.
264 base::SyncSocket temp_socket(
265 IPC::PlatformFileForTransitToPlatformFile(foreign_socket_handle));
266 }
267 }
268
269 } // namespace proxy
270 } // namespace pp
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698