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

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

Issue 11417145: Provide a safer URLLoader ReadResponseBody API (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ppb_url_loader_proxy.h" 5 #include "ppapi/proxy/ppb_url_loader_proxy.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "build/build_config.h" 13 #include "build/build_config.h"
14 #include "ppapi/c/pp_completion_callback.h" 14 #include "ppapi/c/pp_completion_callback.h"
15 #include "ppapi/c/pp_errors.h" 15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/pp_resource.h" 16 #include "ppapi/c/pp_resource.h"
17 #include "ppapi/c/ppb_url_loader.h" 17 #include "ppapi/c/ppb_url_loader.h"
18 #include "ppapi/c/private/ppb_proxy_private.h" 18 #include "ppapi/c/private/ppb_proxy_private.h"
19 #include "ppapi/c/trusted/ppb_url_loader_trusted.h" 19 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
20 #include "ppapi/proxy/enter_proxy.h" 20 #include "ppapi/proxy/enter_proxy.h"
21 #include "ppapi/proxy/host_dispatcher.h" 21 #include "ppapi/proxy/host_dispatcher.h"
22 #include "ppapi/proxy/plugin_dispatcher.h" 22 #include "ppapi/proxy/plugin_dispatcher.h"
23 #include "ppapi/proxy/plugin_resource_tracker.h" 23 #include "ppapi/proxy/plugin_resource_tracker.h"
24 #include "ppapi/proxy/ppapi_messages.h" 24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "ppapi/proxy/ppb_file_ref_proxy.h" 25 #include "ppapi/proxy/ppb_file_ref_proxy.h"
26 #include "ppapi/shared_impl/array_writer.h"
26 #include "ppapi/shared_impl/scoped_pp_resource.h" 27 #include "ppapi/shared_impl/scoped_pp_resource.h"
27 #include "ppapi/shared_impl/tracked_callback.h" 28 #include "ppapi/shared_impl/tracked_callback.h"
28 #include "ppapi/thunk/enter.h" 29 #include "ppapi/thunk/enter.h"
29 #include "ppapi/thunk/ppb_url_loader_api.h" 30 #include "ppapi/thunk/ppb_url_loader_api.h"
30 #include "ppapi/thunk/ppb_url_request_info_api.h" 31 #include "ppapi/thunk/ppb_url_request_info_api.h"
31 #include "ppapi/thunk/resource_creation_api.h" 32 #include "ppapi/thunk/resource_creation_api.h"
32 #include "ppapi/thunk/thunk.h" 33 #include "ppapi/thunk/thunk.h"
33 34
34 #if defined(OS_LINUX) 35 #if defined(OS_LINUX)
35 #include <sys/shm.h> 36 #include <sys/shm.h>
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 params.total_bytes_to_be_received = total_bytes_to_be_received; 72 params.total_bytes_to_be_received = total_bytes_to_be_received;
72 dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress( 73 dispatcher->Send(new PpapiMsg_PPBURLLoader_UpdateProgress(
73 API_ID_PPB_URL_LOADER, params)); 74 API_ID_PPB_URL_LOADER, params));
74 } 75 }
75 #endif // !defined(OS_NACL) 76 #endif // !defined(OS_NACL)
76 77
77 InterfaceProxy* CreateURLLoaderProxy(Dispatcher* dispatcher) { 78 InterfaceProxy* CreateURLLoaderProxy(Dispatcher* dispatcher) {
78 return new PPB_URLLoader_Proxy(dispatcher); 79 return new PPB_URLLoader_Proxy(dispatcher);
79 } 80 }
80 81
82 // An adapter to let ReadResponseBody() share the same implementation with
83 // ReadResponseBodyToArray().
84 void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
85 return user_data;
86 }
87
81 } // namespace 88 } // namespace
82 89
83 // URLLoader ------------------------------------------------------------------- 90 // URLLoader -------------------------------------------------------------------
84 91
85 class URLLoader : public Resource, public PPB_URLLoader_API { 92 class URLLoader : public Resource, public PPB_URLLoader_API {
86 public: 93 public:
87 URLLoader(const HostResource& resource); 94 URLLoader(const HostResource& resource);
88 virtual ~URLLoader(); 95 virtual ~URLLoader();
89 96
90 // Resource overrides. 97 // Resource overrides.
(...skipping 10 matching lines...) Expand all
101 virtual PP_Bool GetUploadProgress(int64_t* bytes_sent, 108 virtual PP_Bool GetUploadProgress(int64_t* bytes_sent,
102 int64_t* total_bytes_to_be_sent) OVERRIDE; 109 int64_t* total_bytes_to_be_sent) OVERRIDE;
103 virtual PP_Bool GetDownloadProgress( 110 virtual PP_Bool GetDownloadProgress(
104 int64_t* bytes_received, 111 int64_t* bytes_received,
105 int64_t* total_bytes_to_be_received) OVERRIDE; 112 int64_t* total_bytes_to_be_received) OVERRIDE;
106 virtual PP_Resource GetResponseInfo() OVERRIDE; 113 virtual PP_Resource GetResponseInfo() OVERRIDE;
107 virtual int32_t ReadResponseBody( 114 virtual int32_t ReadResponseBody(
108 void* buffer, 115 void* buffer,
109 int32_t bytes_to_read, 116 int32_t bytes_to_read,
110 scoped_refptr<TrackedCallback> callback) OVERRIDE; 117 scoped_refptr<TrackedCallback> callback) OVERRIDE;
118 virtual int32_t ReadResponseBodyToArray(
119 int32_t max_read_length,
120 PP_ArrayOutput* array_output,
121 scoped_refptr<TrackedCallback> callback) OVERRIDE;
111 virtual int32_t FinishStreamingToFile( 122 virtual int32_t FinishStreamingToFile(
112 scoped_refptr<TrackedCallback> callback) OVERRIDE; 123 scoped_refptr<TrackedCallback> callback) OVERRIDE;
113 virtual void Close() OVERRIDE; 124 virtual void Close() OVERRIDE;
114 virtual void GrantUniversalAccess() OVERRIDE; 125 virtual void GrantUniversalAccess() OVERRIDE;
115 virtual void SetStatusCallback( 126 virtual void SetStatusCallback(
116 PP_URLLoaderTrusted_StatusCallback cb) OVERRIDE; 127 PP_URLLoaderTrusted_StatusCallback cb) OVERRIDE;
117 virtual bool GetResponseInfoData(URLResponseInfoData* data) OVERRIDE; 128 virtual bool GetResponseInfoData(URLResponseInfoData* data) OVERRIDE;
118 129
130 int32_t ReadResponseBodyInternal(const PP_ArrayOutput& output,
131 int32_t max_read_length,
132 scoped_refptr<TrackedCallback> callback);
133
119 // Called when the browser has new up/download progress to report. 134 // Called when the browser has new up/download progress to report.
120 void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params); 135 void UpdateProgress(const PPBURLLoader_UpdateProgress_Params& params);
121 136
122 // Called when the browser responds to our ReadResponseBody request. 137 // Called when the browser responds to our ReadResponseBody request.
123 void ReadResponseBodyAck(int32_t result, const char* data); 138 void ReadResponseBodyAck(int32_t result, const char* data);
124 139
125 // Called when any callback other than the read callback has been executed. 140 // Called when any callback other than the read callback has been executed.
126 void CallbackComplete(int32_t result); 141 void CallbackComplete(int32_t result);
127 142
128 private: 143 private:
129 // Reads the give bytes out of the buffer_, placing them in the given output 144 // Reads the give bytes out of the buffer_, placing them in the given output
130 // buffer, and removes the bytes from the buffer. 145 // buffer, and removes the bytes from the buffer.
131 // 146 //
132 // The size must be not more than the current size of the buffer. 147 // The size must be not more than the current size of the buffer.
133 void PopBuffer(void* output_buffer, int32_t output_size); 148 void PopBuffer(const PP_ArrayOutput& output_buffer, int32_t output_size);
134 149
135 PluginDispatcher* GetDispatcher() const { 150 PluginDispatcher* GetDispatcher() const {
136 return PluginDispatcher::GetForResource(this); 151 return PluginDispatcher::GetForResource(this);
137 } 152 }
138 153
139 // Initialized to -1. Will be set to nonnegative values by the UpdateProgress 154 // Initialized to -1. Will be set to nonnegative values by the UpdateProgress
140 // message when the values are known. 155 // message when the values are known.
141 int64_t bytes_sent_; 156 int64_t bytes_sent_;
142 int64_t total_bytes_to_be_sent_; 157 int64_t total_bytes_to_be_sent_;
143 int64_t bytes_received_; 158 int64_t bytes_received_;
144 int64_t total_bytes_to_be_received_; 159 int64_t total_bytes_to_be_received_;
145 160
146 // Current completion callback for the current phase of loading. We have only 161 // Current completion callback for the current phase of loading. We have only
147 // one thing (open, follow redirect, read, etc.) outstanding at once. 162 // one thing (open, follow redirect, read, etc.) outstanding at once.
148 scoped_refptr<TrackedCallback> current_callback_; 163 scoped_refptr<TrackedCallback> current_callback_;
149 164
150 // When an asynchronous read is pending, this will contain the buffer to put 165 // When an asynchronous read is pending, this will contain the buffer to put
151 // the data. The current_callback_ will identify the read callback. 166 // the data. The current_callback_ will identify the read callback.
152 void* current_read_buffer_; 167 PP_ArrayOutput current_array_output_;
153 int32_t current_read_buffer_size_; 168 int32_t current_max_read_length_;
154 169
155 // A buffer of all the data that's been sent to us from the host that we 170 // A buffer of all the data that's been sent to us from the host that we
156 // have yet to send out to the plugin. 171 // have yet to send out to the plugin.
157 std::deque<char> buffer_; 172 std::deque<char> buffer_;
158 173
159 // Cached copy of the response info. When nonzero, we're holding a reference 174 // Cached copy of the response info. When nonzero, we're holding a reference
160 // to this resource. 175 // to this resource.
161 PP_Resource response_info_; 176 PP_Resource response_info_;
162 177
163 private: 178 private:
164 DISALLOW_COPY_AND_ASSIGN(URLLoader); 179 DISALLOW_COPY_AND_ASSIGN(URLLoader);
165 }; 180 };
166 181
167 URLLoader::URLLoader(const HostResource& resource) 182 URLLoader::URLLoader(const HostResource& resource)
168 : Resource(OBJECT_IS_PROXY, resource), 183 : Resource(OBJECT_IS_PROXY, resource),
169 bytes_sent_(-1), 184 bytes_sent_(-1),
170 total_bytes_to_be_sent_(-1), 185 total_bytes_to_be_sent_(-1),
171 bytes_received_(-1), 186 bytes_received_(-1),
172 total_bytes_to_be_received_(-1), 187 total_bytes_to_be_received_(-1),
173 current_read_buffer_(NULL), 188 current_max_read_length_(0),
174 current_read_buffer_size_(0),
175 response_info_(0) { 189 response_info_(0) {
176 } 190 }
177 191
178 URLLoader::~URLLoader() { 192 URLLoader::~URLLoader() {
179 if (response_info_) 193 if (response_info_)
180 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(response_info_); 194 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(response_info_);
181 } 195 }
182 196
183 PPB_URLLoader_API* URLLoader::AsPPB_URLLoader_API() { 197 PPB_URLLoader_API* URLLoader::AsPPB_URLLoader_API() {
184 return this; 198 return this;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 } 285 }
272 286
273 // The caller expects to get a ref, and we want to keep holding ours. 287 // The caller expects to get a ref, and we want to keep holding ours.
274 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(response_info_); 288 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(response_info_);
275 return response_info_; 289 return response_info_;
276 } 290 }
277 291
278 int32_t URLLoader::ReadResponseBody(void* buffer, 292 int32_t URLLoader::ReadResponseBody(void* buffer,
279 int32_t bytes_to_read, 293 int32_t bytes_to_read,
280 scoped_refptr<TrackedCallback> callback) { 294 scoped_refptr<TrackedCallback> callback) {
281 if (!buffer || bytes_to_read <= 0) 295 if (!buffer)
282 return PP_ERROR_BADARGUMENT; // Must specify an output buffer. 296 return PP_ERROR_BADARGUMENT;
283 if (TrackedCallback::IsPending(current_callback_)) 297 PP_ArrayOutput output_adapter = { &DummyGetDataBuffer, buffer };
284 return PP_ERROR_INPROGRESS; // Can only have one request pending. 298 return ReadResponseBodyInternal(output_adapter, bytes_to_read, callback);
299 }
285 300
286 if (buffer_.size()) { 301 int32_t URLLoader::ReadResponseBodyToArray(
287 // Special case: we've already buffered some data that we can synchronously 302 int32_t max_read_length,
288 // return to the caller. Do so without making IPCs. 303 PP_ArrayOutput* array_output,
289 int32_t bytes_to_return = 304 scoped_refptr<TrackedCallback> callback) {
290 std::min(bytes_to_read, static_cast<int32_t>(buffer_.size())); 305 if (!array_output)
291 PopBuffer(buffer, bytes_to_return); 306 return PP_ERROR_BADARGUMENT;
292 return bytes_to_return; 307 return ReadResponseBodyInternal(*array_output, max_read_length, callback);
293 }
294
295 current_callback_ = callback;
296 current_read_buffer_ = buffer;
297 current_read_buffer_size_ = bytes_to_read;
298
299 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
300 API_ID_PPB_URL_LOADER, host_resource(), bytes_to_read));
301 return PP_OK_COMPLETIONPENDING;
302 } 308 }
303 309
304 int32_t URLLoader::FinishStreamingToFile( 310 int32_t URLLoader::FinishStreamingToFile(
305 scoped_refptr<TrackedCallback> callback) { 311 scoped_refptr<TrackedCallback> callback) {
306 if (TrackedCallback::IsPending(current_callback_)) 312 if (TrackedCallback::IsPending(current_callback_))
307 return PP_ERROR_INPROGRESS; 313 return PP_ERROR_INPROGRESS;
308 314
309 current_callback_ = callback; 315 current_callback_ = callback;
310 316
311 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile( 317 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_FinishStreamingToFile(
(...skipping 26 matching lines...) Expand all
338 344
339 void URLLoader::UpdateProgress( 345 void URLLoader::UpdateProgress(
340 const PPBURLLoader_UpdateProgress_Params& params) { 346 const PPBURLLoader_UpdateProgress_Params& params) {
341 bytes_sent_ = params.bytes_sent; 347 bytes_sent_ = params.bytes_sent;
342 total_bytes_to_be_sent_ = params.total_bytes_to_be_sent; 348 total_bytes_to_be_sent_ = params.total_bytes_to_be_sent;
343 bytes_received_ = params.bytes_received; 349 bytes_received_ = params.bytes_received;
344 total_bytes_to_be_received_ = params.total_bytes_to_be_received; 350 total_bytes_to_be_received_ = params.total_bytes_to_be_received;
345 } 351 }
346 352
347 void URLLoader::ReadResponseBodyAck(int32 result, const char* data) { 353 void URLLoader::ReadResponseBodyAck(int32 result, const char* data) {
348 if (!TrackedCallback::IsPending(current_callback_) || !current_read_buffer_) { 354 if (!TrackedCallback::IsPending(current_callback_)) {
349 NOTREACHED(); 355 NOTREACHED();
350 return; 356 return;
351 } 357 }
352 358
353 if (result >= 0) { 359 if (result >= 0) {
354 DCHECK_EQ(0U, buffer_.size()); 360 DCHECK_EQ(0U, buffer_.size());
355 361
356 int32_t bytes_to_return = std::min(current_read_buffer_size_, result); 362 int32_t bytes_to_return = std::min(current_max_read_length_, result);
357 std::copy(data, 363 ArrayWriter output;
358 data + bytes_to_return, 364 output.set_pp_array_output(current_array_output_);
359 static_cast<char*>(current_read_buffer_)); 365 if (output.is_valid())
366 output.StoreArray(data, bytes_to_return);
360 367
361 if (result > bytes_to_return) { 368 if (result > bytes_to_return) {
362 // Save what remains to be copied when ReadResponseBody is called again. 369 // Save what remains to be copied when ReadResponseBody is called again.
363 buffer_.insert(buffer_.end(), 370 buffer_.insert(buffer_.end(),
364 data + bytes_to_return, 371 data + bytes_to_return,
365 data + result); 372 data + result);
366 } 373 }
367 374
368 result = bytes_to_return; 375 result = bytes_to_return;
369 } 376 }
370 377
371 current_callback_->Run(result); 378 current_callback_->Run(result);
372 } 379 }
373 380
374 void URLLoader::CallbackComplete(int32_t result) { 381 void URLLoader::CallbackComplete(int32_t result) {
375 current_callback_->Run(result); 382 current_callback_->Run(result);
376 } 383 }
377 384
378 void URLLoader::PopBuffer(void* output_buffer, int32_t output_size) { 385 void URLLoader::PopBuffer(const PP_ArrayOutput& output_buffer,
386 int32_t output_size) {
379 CHECK(output_size <= static_cast<int32_t>(buffer_.size())); 387 CHECK(output_size <= static_cast<int32_t>(buffer_.size()));
380 std::copy(buffer_.begin(), 388
381 buffer_.begin() + output_size, 389 ArrayWriter output;
382 static_cast<char*>(output_buffer)); 390 output.set_pp_array_output(output_buffer);
383 buffer_.erase(buffer_.begin(), 391 if (output.is_valid() && !buffer_.empty()) {
384 buffer_.begin() + output_size); 392 output.StoreArray(&buffer_[0], output_size);
393 buffer_.erase(buffer_.begin(), buffer_.begin() + output_size);
394 }
385 } 395 }
386 396
387 // PPB_URLLoader_Proxy --------------------------------------------------------- 397 // PPB_URLLoader_Proxy ---------------------------------------------------------
388 398
389 PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher) 399 PPB_URLLoader_Proxy::PPB_URLLoader_Proxy(Dispatcher* dispatcher)
390 : InterfaceProxy(dispatcher), 400 : InterfaceProxy(dispatcher),
391 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 401 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
392 } 402 }
393 403
394 PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() { 404 PPB_URLLoader_Proxy::~PPB_URLLoader_Proxy() {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 dispatcher()->Send(message); 648 dispatcher()->Send(message);
639 } 649 }
640 650
641 void PPB_URLLoader_Proxy::OnCallback(int32_t result, 651 void PPB_URLLoader_Proxy::OnCallback(int32_t result,
642 const HostResource& resource) { 652 const HostResource& resource) {
643 dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete( 653 dispatcher()->Send(new PpapiMsg_PPBURLLoader_CallbackComplete(
644 API_ID_PPB_URL_LOADER, resource, result)); 654 API_ID_PPB_URL_LOADER, resource, result));
645 } 655 }
646 #endif // !defined(OS_NACL) 656 #endif // !defined(OS_NACL)
647 657
658 int32_t URLLoader::ReadResponseBodyInternal(
659 const PP_ArrayOutput& output,
660 int32_t max_read_length,
661 scoped_refptr<TrackedCallback> callback) {
662 if (max_read_length <= 0)
663 return PP_ERROR_BADARGUMENT; // Must specify an output buffer.
664 if (TrackedCallback::IsPending(current_callback_))
665 return PP_ERROR_INPROGRESS; // Can only have one request pending.
666
667 if (buffer_.size()) {
668 // Special case: we've already buffered some data that we can synchronously
669 // return to the caller. Do so without making IPCs.
670 int32_t bytes_to_return =
671 std::min(max_read_length, static_cast<int32_t>(buffer_.size()));
672 PopBuffer(output, bytes_to_return);
673 return bytes_to_return;
674 }
675
676 current_callback_ = callback;
677 current_array_output_ = output;
678 current_max_read_length_ = max_read_length;
679
680 GetDispatcher()->Send(new PpapiHostMsg_PPBURLLoader_ReadResponseBody(
681 API_ID_PPB_URL_LOADER, host_resource(), max_read_length));
682 return PP_OK_COMPLETIONPENDING;
683 }
684
648 } // namespace proxy 685 } // namespace proxy
649 } // namespace ppapi 686 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c ('k') | ppapi/tests/test_url_loader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698