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

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

Issue 4289005: Instance interface implementation. These don't build by themselves, this is... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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_url_loader_proxy.h ('k') | ppapi/proxy/ppp_instance_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ppapi/proxy/ppb_url_loader_proxy.h"
6
7 #include <vector>
8
9 #include "base/logging.h"
10 #include "build/build_config.h"
11 #include "ppapi/c/pp_completion_callback.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/pp_resource.h"
14 #include "ppapi/c/dev/ppb_url_loader_dev.h"
15 #include "ppapi/proxy/host_dispatcher.h"
16 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/plugin_resource.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/proxy/ppb_url_response_info_proxy.h"
20
21 #if defined(OS_LINUX)
22 #include <sys/shm.h>
23 #endif
24
25 namespace pp {
26 namespace proxy {
27
28 class URLLoader : public PluginResource {
29 public:
30 URLLoader();
31 virtual ~URLLoader();
32
33 // Resource overrides.
34 virtual URLLoader* AsURLLoader() { return this; }
35
36 // Initialized to -1. Will be set to nonnegative values by the UpdateProgress
37 // message when the values are known.
38 int64_t bytes_sent_;
39 int64_t total_bytes_to_be_sent_;
40 int64_t bytes_received_;
41 int64_t total_bytes_to_be_received_;
42
43 // When an asynchronous read is pending, this will contain the callback and
44 // the buffer to put the data.
45 PP_CompletionCallback current_read_callback_;
46 char* current_read_buffer_;
47
48 private:
49 DISALLOW_COPY_AND_ASSIGN(URLLoader);
50 };
51
52 URLLoader::URLLoader()
53 : bytes_sent_(-1),
54 total_bytes_to_be_sent_(-1),
55 bytes_received_(-1),
56 total_bytes_to_be_received_(-1),
57 current_read_callback_(PP_MakeCompletionCallback(NULL, NULL)),
58 current_read_buffer_(NULL) {
59 }
60
61 URLLoader::~URLLoader() {
62 }
63
64 namespace {
65
66 // Plugin interface implmentation ----------------------------------------------
67
68 PP_Resource Create(PP_Instance instance_id) {
69 PluginDispatcher* dispatcher = PluginDispatcher::Get();
70 PP_Resource result = 0;
71 dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Create(
72 INTERFACE_ID_PPB_URL_LOADER, instance_id, &result));
73 if (result)
74 PPB_URLLoader_Proxy::TrackPluginResource(result);
75 return result;
76 }
77
78 bool IsURLLoader(PP_Resource resource) {
79 URLLoader* object = PluginResource::GetAs<URLLoader>(resource);
80 return !!object;
81 }
82
83 int32_t Open(PP_Resource loader_id,
84 PP_Resource request_id,
85 PP_CompletionCallback callback) {
86 Dispatcher* dispatcher = PluginDispatcher::Get();
87 dispatcher->Send(new PpapiHostMsg_PPBURLLoader_Open(
88 INTERFACE_ID_PPB_URL_LOADER, loader_id, request_id,
89 dispatcher->callback_tracker().SendCallback(callback)));
90 return PP_ERROR_WOULDBLOCK;
91 }
92
93 int32_t FollowRedirect(PP_Resource loader_id,
94 PP_CompletionCallback callback) {
95 Dispatcher* dispatcher = PluginDispatcher::Get();
96 dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FollowRedirect(
97 INTERFACE_ID_PPB_URL_LOADER, loader_id,
98 dispatcher->callback_tracker().SendCallback(callback)));
99 return PP_ERROR_WOULDBLOCK;
100 }
101
102 bool GetUploadProgress(PP_Resource loader_id,
103 int64_t* bytes_sent,
104 int64_t* total_bytes_to_be_sent) {
105 URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id);
106 if (!object || object->bytes_sent_ == -1) {
107 *bytes_sent = 0;
108 *total_bytes_to_be_sent = 0;
109 return false;
110 }
111 *bytes_sent = object->bytes_sent_;
112 *total_bytes_to_be_sent = object->total_bytes_to_be_sent_;
113 return true;
114 }
115
116 bool GetDownloadProgress(PP_Resource loader_id,
117 int64_t* bytes_received,
118 int64_t* total_bytes_to_be_received) {
119 URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id);
120 if (!object || object->bytes_received_ == -1) {
121 *bytes_received = 0;
122 *total_bytes_to_be_received = 0;
123 return false;
124 }
125 *bytes_received = object->bytes_received_;
126 *total_bytes_to_be_received = object->total_bytes_to_be_received_;
127 return true;
128 }
129
130 PP_Resource GetResponseInfo(PP_Resource loader_id) {
131 // If we find that plugins are frequently requesting the response info, we
132 // can improve performance by caching the PP_Resource in the URLLoader
133 // object. This way we only have to do IPC for the first request. However,
134 // it seems that most plugins will only call this once so there's no use
135 // optimizing this case.
136
137 PP_Resource result;
138 PluginDispatcher* dispatcher = PluginDispatcher::Get();
139 dispatcher->Send(new PpapiHostMsg_PPBURLLoader_GetResponseInfo(
140 INTERFACE_ID_PPB_URL_LOADER, loader_id, &result));
141 if (dispatcher->plugin_resource_tracker()->PreparePreviouslyTrackedResource(
142 result))
143 return result;
144
145 // Tell the response info to create a tracking object and add it to the
146 // resource tracker.
147 PPB_URLResponseInfo_Proxy::TrackPluginResource(result);
148 return result;
149 }
150
151 int32_t ReadResponseBody(PP_Resource loader_id,
152 char* buffer,
153 int32_t bytes_to_read,
154 PP_CompletionCallback callback) {
155 URLLoader* object = PluginResource::GetAs<URLLoader>(loader_id);
156 if (!object)
157 return PP_ERROR_BADRESOURCE;
158
159 if (!buffer)
160 return PP_ERROR_BADARGUMENT; // Must specify an output buffer.
161 if (object->current_read_callback_.func)
162 return PP_ERROR_INPROGRESS; // Can only have one request pending.
163
164 // Currently we don't support sync calls to read. We'll need to revisit
165 // how this works when we allow blocking calls (from background threads).
166 if (!callback.func)
167 return PP_ERROR_BADARGUMENT;
168
169 object->current_read_callback_ = callback;
170 object->current_read_buffer_ = buffer;
171
172 PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
173 INTERFACE_ID_PPB_URL_LOADER, loader_id, bytes_to_read));
174 return PP_ERROR_WOULDBLOCK;
175 }
176
177 int32_t FinishStreamingToFile(PP_Resource loader_id,
178 PP_CompletionCallback callback) {
179 Dispatcher* dispatcher = PluginDispatcher::Get();
180 dispatcher->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
181 INTERFACE_ID_PPB_URL_LOADER, loader_id,
182 dispatcher->callback_tracker().SendCallback(callback)));
183 return PP_ERROR_WOULDBLOCK;
184 }
185
186 void Close(PP_Resource loader_id) {
187 PluginDispatcher::Get()->Send(new PpapiHostMsg_PPBURLLoader_Close(
188 INTERFACE_ID_PPB_URL_LOADER, loader_id));
189 }
190
191 const PPB_URLLoader_Dev ppb_urlloader = {
192 &Create,
193 &IsURLLoader,
194 &Open,
195 &FollowRedirect,
196 &GetUploadProgress,
197 &GetDownloadProgress,
198 &GetResponseInfo,
199 &ReadResponseBody,
200 &FinishStreamingToFile,
201 &Close
202 };
203
204 // Renderer status updates -----------------------------------------------------
205
206 // Called in the renderer when the byte counts have changed. We send a message
207 // to the plugin to synchronize its counts so it can respond to status polls
208 // from the plugin.
209 void UpdateResourceLoadStatus(PP_Instance pp_instance,
210 PP_Resource pp_resource,
211 int64 bytes_sent,
212 int64 total_bytes_to_be_sent,
213 int64 bytes_received,
214 int64 total_bytes_to_be_received) {
215 Dispatcher* dispatcher = HostDispatcher::GetForInstance(pp_instance);
216 dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress(
217 INTERFACE_ID_PPB_URL_LOADER, pp_resource,
218 bytes_sent, total_bytes_to_be_sent,
219 bytes_received, total_bytes_to_be_received));
220 }
221
222 // Data associated with callbacks for ReadResponseBody.
223 struct ReadCallbackInfo {
224 base::WeakPtr<PPB_URLLoader_Proxy> loader;
225 PP_Resource pp_resource;
226 std::string read_buffer;
227 };
228
229 // Callback for renderer calls to ReadResponseBody. This function will forward
230 // the result to the plugin and clean up the callback info.
231 void ReadCallbackHandler(void* user_data, int32_t result) {
232 scoped_ptr<ReadCallbackInfo> info(static_cast<ReadCallbackInfo*>(user_data));
233 if (!info->loader)
234 return;
235
236 int32_t bytes_read = 0;
237 if (result > 0)
238 bytes_read = result; // Positive results indicate bytes read.
239 info->read_buffer.resize(bytes_read);
240
241 info->loader->dispatcher()->Send(
242 new PpapiMsg_PPBURLLoader_ReadResponseBody_Ack(
243 INTERFACE_ID_PPB_URL_LOADER, info->pp_resource,
244 result, info->read_buffer));
245 }
246
247 } // namespace
248
249 // PPB_URLLoader_Proxy ---------------------------------------------------------
250
251 PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher,
252 const void* target_interface)
253 : InterfaceProxy(dispatcher, target_interface) {
254 }
255
256 PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() {
257 }
258
259 // static
260 void PPB_URLLoader_Proxy::TrackPluginResource(PP_Resource url_loader_resource) {
261 linked_ptr<URLLoader> object(new URLLoader);
262 PluginDispatcher::Get()->plugin_resource_tracker()->AddResource(
263 url_loader_resource, object);
264 }
265
266 const void* PPB_URLLoader_Proxy::GetSourceInterface() const {
267 return &ppb_urlloader;
268 }
269
270 InterfaceID PPB_URLLoader_Proxy::GetInterfaceId() const {
271 return INTERFACE_ID_PPB_URL_LOADER;
272 }
273
274 void PPB_URLLoader_Proxy::OnMessageReceived(const IPC::Message& msg) {
275 IPC_BEGIN_MESSAGE_MAP(PPB_URLLoader_Proxy, msg)
276 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Create,
277 OnMsgCreate)
278 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Open,
279 OnMsgOpen)
280 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FollowRedirect,
281 OnMsgFollowRedirect)
282 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_GetResponseInfo,
283 OnMsgGetResponseInfo)
284 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_ReadResponseBody,
285 OnMsgReadResponseBody)
286 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_FinishStreamingToFile,
287 OnMsgFinishStreamingToFile)
288 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBURLLoader_Close,
289 OnMsgClose)
290
291 IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_UpdateProgress,
292 OnMsgUpdateProgress)
293 IPC_MESSAGE_HANDLER(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack,
294 OnMsgReadResponseBodyAck)
295 IPC_END_MESSAGE_MAP()
296 // TODO(brettw) handle bad messages!
297 }
298
299 void PPB_URLLoader_Proxy::OnMsgCreate(PP_Instance instance,
300 PP_Resource* result) {
301 *result = ppb_url_loader_target()->Create(instance);
302 }
303
304 void PPB_URLLoader_Proxy::OnMsgOpen(PP_Resource loader,
305 PP_Resource request_info,
306 uint32_t serialized_callback) {
307 PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
308 int32_t result = ppb_url_loader_target()->Open(
309 loader, request_info, callback);
310 if (result != PP_ERROR_WOULDBLOCK)
311 PP_RunCompletionCallback(&callback, result);
312 }
313
314 void PPB_URLLoader_Proxy::OnMsgFollowRedirect(
315 PP_Resource loader,
316 uint32_t serialized_callback) {
317 PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
318 int32_t result = ppb_url_loader_target()->FollowRedirect(
319 loader, callback);
320 if (result != PP_ERROR_WOULDBLOCK)
321 PP_RunCompletionCallback(&callback, result);
322 }
323
324 void PPB_URLLoader_Proxy::OnMsgGetResponseInfo(PP_Resource loader,
325 PP_Resource* result) {
326 *result = ppb_url_loader_target()->GetResponseInfo(loader);
327 }
328
329 void PPB_URLLoader_Proxy::OnMsgReadResponseBody(
330 PP_Resource loader,
331 int32_t bytes_to_read) {
332 // The plugin could be sending us malicious messages, don't accept negative
333 // sizes.
334 if (bytes_to_read < 0) {
335 // TODO(brettw) kill plugin.
336 bytes_to_read = 0;
337 }
338
339 // This heap object will get deleted by the callback handler.
340 // TODO(brettw) this will be leaked if the plugin closes the resource!
341 // (Also including the plugin unloading and having the resource implicitly
342 // destroyed. Depending on the cleanup ordering, we may not need the weak
343 // pointer here.)
344 ReadCallbackInfo* info = new ReadCallbackInfo;
345 info->loader = AsWeakPtr();
346 info->pp_resource = loader;
347 info->read_buffer.resize(bytes_to_read);
348
349 int32_t result = ppb_url_loader_target()->ReadResponseBody(
350 loader, const_cast<char*>(info->read_buffer.c_str()), bytes_to_read,
351 PP_MakeCompletionCallback(&ReadCallbackHandler, info));
352 if (result != PP_ERROR_WOULDBLOCK) {
353 // Send error (or perhaps success for synchronous reads) back to plugin.
354 // The callback function is already set up to do this and also delete the
355 // callback info.
356 ReadCallbackHandler(info, result);
357 }
358 }
359
360 void PPB_URLLoader_Proxy::OnMsgFinishStreamingToFile(
361 PP_Resource loader,
362 uint32_t serialized_callback) {
363 PP_CompletionCallback callback = ReceiveCallback(serialized_callback);
364 int32_t result = ppb_url_loader_target()->FinishStreamingToFile(
365 loader, callback);
366 if (result != PP_ERROR_WOULDBLOCK)
367 PP_RunCompletionCallback(&callback, result);
368 }
369
370 void PPB_URLLoader_Proxy::OnMsgClose(PP_Resource loader) {
371 ppb_url_loader_target()->Close(loader);
372 }
373
374 void PPB_URLLoader_Proxy::OnMsgUpdateProgress(
375 PP_Resource resource,
376 int64_t bytes_sent,
377 int64_t total_bytes_to_be_sent,
378 int64_t bytes_received,
379 int64_t total_bytes_to_be_received) {
380 URLLoader* object = PluginResource::GetAs<URLLoader>(resource);
381 if (!object) {
382 NOTREACHED();
383 return;
384 }
385
386 object->bytes_sent_ = bytes_sent;
387 object->total_bytes_to_be_sent_ = total_bytes_to_be_sent;
388 object->bytes_received_ = bytes_received;
389 object->total_bytes_to_be_received_ = total_bytes_to_be_received;
390 }
391
392 void PPB_URLLoader_Proxy::OnMsgReadResponseBodyAck(PP_Resource pp_resource,
393 int32 result,
394 const std::string& data) {
395 URLLoader* object = PluginResource::GetAs<URLLoader>(pp_resource);
396 if (!object) {
397 NOTREACHED();
398 return;
399 }
400
401 if (!object->current_read_callback_.func || !object->current_read_buffer_) {
402 NOTREACHED();
403 return;
404 }
405
406 // In the error case, the string will be empty, so we can always just copy
407 // out of it before issuing the callback.
408 memcpy(object->current_read_buffer_, data.c_str(), data.length());
409
410 // The plugin should be able to make a new request from their callback, so
411 // we have to clear our copy first.
412 PP_CompletionCallback temp_callback = object->current_read_callback_;
413 object->current_read_callback_ = PP_BlockUntilComplete();
414 object->current_read_buffer_ = NULL;
415 PP_RunCompletionCallback(&temp_callback, result);
416 }
417
418 } // namespace proxy
419 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_url_loader_proxy.h ('k') | ppapi/proxy/ppp_instance_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698