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

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: Synced, changed enum after syncing, and really fixed the Windows build. 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
« no previous file with comments | « ppapi/proxy/ppb_broker_proxy.h ('k') | webkit/plugins/ppapi/ppb_broker_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
27 // The plugin module owns the handle.
28 // The host side transfers ownership of the handle to the plugin side when it
29 // sends the IPC. This member holds the handle value for the plugin module
30 // to read, but the plugin side of the proxy never takes ownership.
31 base::SyncSocket::Handle socket_handle_;
32
33 private:
34 DISALLOW_COPY_AND_ASSIGN(Broker);
35 };
36
37 Broker::Broker(const HostResource& resource)
38 : PluginResource(resource),
39 called_connect_(false),
40 current_connect_callback_(PP_MakeCompletionCallback(NULL, NULL)),
41 socket_handle_(base::kInvalidPlatformFileValue) {
42 }
43
44 Broker::~Broker() {
45 // Ensure the callback is always fired.
46 if (current_connect_callback_.func) {
47 // TODO(brettw) the callbacks at this level should be refactored with a
48 // more automatic tracking system like we have in the renderer.
49 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
50 current_connect_callback_.func, current_connect_callback_.user_data,
51 static_cast<int32_t>(PP_ERROR_ABORTED)));
52 }
53
54 socket_handle_ = base::kInvalidPlatformFileValue;
55 }
56
57 namespace {
58
59 base::PlatformFile IntToPlatformFile(int32_t handle) {
60 #if defined(OS_WIN)
61 return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
62 #elif defined(OS_POSIX)
63 return handle;
64 #else
65 #error Not implemented.
66 #endif
67 }
68
69 int32_t PlatformFileToInt(base::PlatformFile handle) {
70 #if defined(OS_WIN)
71 return static_cast<int32_t>(reinterpret_cast<intptr_t>(handle));
72 #elif defined(OS_POSIX)
73 return handle;
74 #else
75 #error Not implemented.
76 #endif
77 }
78
79 PP_Resource CreateTrusted(PP_Instance instance) {
80 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
81 if (!dispatcher)
82 return 0;
83
84 HostResource result;
85 dispatcher->Send(new PpapiHostMsg_PPBBroker_Create(
86 INTERFACE_ID_PPB_BROKER, instance, &result));
87 if (result.is_null())
88 return 0;
89
90 linked_ptr<Broker> object(new Broker(result));
91 return PluginResourceTracker::GetInstance()->AddResource(object);
92 }
93
94 PP_Bool IsBrokerTrusted(PP_Resource resource) {
95 Broker* object = PluginResource::GetAs<Broker>(resource);
96 return BoolToPPBool(!!object);
97 }
98
99 int32_t Connect(PP_Resource resource,
100 PP_CompletionCallback connect_callback) {
101 Broker* object = PluginResource::GetAs<Broker>(resource);
102 if (!object)
103 return PP_ERROR_BADRESOURCE;
104
105 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance());
106 if (!dispatcher)
107 return PP_ERROR_BADRESOURCE;
108
109 if (!connect_callback.func) {
110 // Synchronous calls are not supported.
111 return PP_ERROR_BADARGUMENT;
112 }
113
114 if (object->current_connect_callback_.func)
115 return PP_ERROR_INPROGRESS;
116 else if (object->called_connect_)
117 return PP_ERROR_FAILED;
118
119 object->current_connect_callback_ = connect_callback;
120 object->called_connect_ = true;
121
122 bool success = dispatcher->Send(new PpapiHostMsg_PPBBroker_Connect(
123 INTERFACE_ID_PPB_BROKER,
124 object->host_resource()));
125 return success ? PP_OK_COMPLETIONPENDING : PP_ERROR_FAILED;
126 }
127
128 int32_t GetHandle(PP_Resource resource, int32_t* handle) {
129 Broker* object = PluginResource::GetAs<Broker>(resource);
130 if (!object)
131 return PP_ERROR_BADRESOURCE;
132 *handle = PlatformFileToInt(object->socket_handle_);
133 return PP_OK;
134 }
135
136 const PPB_BrokerTrusted broker_interface = {
137 &CreateTrusted,
138 &IsBrokerTrusted,
139 &Connect,
140 &GetHandle,
141 };
142
143 InterfaceProxy* CreateBrokerProxy(Dispatcher* dispatcher,
144 const void* target_interface) {
145 return new PPB_Broker_Proxy(dispatcher, target_interface);
146 }
147
148 } // namespace
149
150 PPB_Broker_Proxy::PPB_Broker_Proxy(Dispatcher* dispatcher,
151 const void* target_interface)
152 : InterfaceProxy(dispatcher, target_interface) ,
153 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)){
154 }
155
156 PPB_Broker_Proxy::~PPB_Broker_Proxy() {
157 }
158
159 // static
160 const InterfaceProxy::Info* PPB_Broker_Proxy::GetInfo() {
161 static const Info info = {
162 &broker_interface,
163 PPB_BROKER_TRUSTED_INTERFACE,
164 INTERFACE_ID_PPB_BROKER,
165 true,
166 &CreateBrokerProxy,
167 };
168 return &info;
169 }
170
171 bool PPB_Broker_Proxy::OnMessageReceived(const IPC::Message& msg) {
172 bool handled = true;
173 IPC_BEGIN_MESSAGE_MAP(PPB_Broker_Proxy, msg)
174 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Create, OnMsgCreate)
175 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBroker_Connect, OnMsgConnect)
176 IPC_MESSAGE_HANDLER(PpapiMsg_PPBBroker_ConnectComplete,
177 OnMsgConnectComplete)
178 IPC_MESSAGE_UNHANDLED(handled = false)
179 IPC_END_MESSAGE_MAP()
180 return handled;
181 }
182
183 void PPB_Broker_Proxy::OnMsgCreate(PP_Instance instance,
184 HostResource* result_resource) {
185 result_resource->SetHostResource(
186 instance,
187 ppb_broker_target()->CreateTrusted(instance));
188 }
189
190 void PPB_Broker_Proxy::OnMsgConnect(const HostResource& broker) {
191 CompletionCallback callback = callback_factory_.NewCallback(
192 &PPB_Broker_Proxy::ConnectCompleteInHost, broker);
193
194 int32_t result = ppb_broker_target()->Connect(
195 broker.host_resource(),
196 callback.pp_completion_callback());
197 if (result != PP_OK_COMPLETIONPENDING)
198 callback.Run(result);
199 }
200
201 // Called in the plugin to handle the connect callback.
202 // The proxy owns the handle and transfers it to the Broker. At that point,
203 // the plugin owns the handle and is responsible for closing it.
204 // The caller guarantees that socket_handle is not valid if result is not PP_OK.
205 void PPB_Broker_Proxy::OnMsgConnectComplete(
206 const HostResource& broker,
207 IPC::PlatformFileForTransit socket_handle,
208 int32_t result) {
209 DCHECK(result == PP_OK ||
210 socket_handle == IPC::InvalidPlatformFileForTransit());
211
212 Broker* object = NULL;
213 if (result == PP_OK) {
214 object = PluginResource::GetAs<Broker>(
215 PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
216 broker));
217 if (!object)
218 result = PP_ERROR_BADRESOURCE;
219 }
220
221 if (result == PP_OK) {
222 object->socket_handle_ =
223 IPC::PlatformFileForTransitToPlatformFile(socket_handle);
224 } else {
225 // The caller may still have given us a handle in the failure case.
226 // The easiest way to clean it up is to just put it in an object
227 // and then close them. This failure case is not performance critical.
228 base::SyncSocket temp_socket(
229 IPC::PlatformFileForTransitToPlatformFile(socket_handle));
230 }
231
232 if (!object->current_connect_callback_.func) {
233 // The handle might leak if the plugin never calls GetHandle().
234 return;
235 }
236
237 PP_CompletionCallback callback = object->current_connect_callback_;
238 object->current_connect_callback_ = PP_MakeCompletionCallback(NULL, NULL);
239 PP_RunCompletionCallback(&callback, result);
240 }
241
242 // Callback on the host side.
243 // Transfers ownership of the handle to the plugin side. This function must
244 // either successfully call the callback or close the handle.
245 void PPB_Broker_Proxy::ConnectCompleteInHost(int32_t result,
246 const HostResource& broker) {
247 IPC::PlatformFileForTransit foreign_socket_handle =
248 IPC::InvalidPlatformFileForTransit();
249 if (result == PP_OK) {
250 int32_t socket_handle = PlatformFileToInt(base::kInvalidPlatformFileValue);
251 result = ppb_broker_target()->GetHandle(broker.host_resource(),
252 &socket_handle);
253 DCHECK(result == PP_OK ||
254 socket_handle == PlatformFileToInt(base::kInvalidPlatformFileValue));
255
256 if (result == PP_OK) {
257 foreign_socket_handle =
258 dispatcher()->ShareHandleWithRemote(IntToPlatformFile(socket_handle),
259 true);
260 if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit()) {
261 result = PP_ERROR_FAILED;
262 // Assume the local handle was closed even if the foreign handle could
263 // not be created.
264 }
265 }
266 }
267 DCHECK(result == PP_OK ||
268 foreign_socket_handle == IPC::InvalidPlatformFileForTransit());
269
270 bool success = dispatcher()->Send(new PpapiMsg_PPBBroker_ConnectComplete(
271 INTERFACE_ID_PPB_FILE_SYSTEM, broker, foreign_socket_handle, result));
272
273 if (!success || result == PP_OK) {
274 // The plugin did not receive the handle, so it must be closed.
275 // The easiest way to clean it up is to just put it in an object
276 // and then close it. This failure case is not performance critical.
277 // The handle could still leak if Send succeeded but the IPC later failed.
278 base::SyncSocket temp_socket(
279 IPC::PlatformFileForTransitToPlatformFile(foreign_socket_handle));
280 }
281 }
282
283 } // namespace proxy
284 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_broker_proxy.h ('k') | webkit/plugins/ppapi/ppb_broker_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698