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

Side by Side Diff: ppapi/native_client/src/trusted/plugin/file_downloader.cc

Issue 292323007: Pepper: FileDownloader cleanup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: test fix Created 6 years, 7 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/native_client/src/trusted/plugin/file_downloader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/native_client/src/trusted/plugin/file_downloader.h" 5 #include "ppapi/native_client/src/trusted/plugin/file_downloader.h"
6 6
7 #include <stdio.h> 7 #include <stdio.h>
8 #include <string.h> 8 #include <string.h>
9 #include <string> 9 #include <string>
10 10
11 #include "native_client/src/include/portability_io.h" 11 #include "native_client/src/include/portability_io.h"
12 #include "native_client/src/shared/platform/nacl_check.h" 12 #include "native_client/src/shared/platform/nacl_check.h"
13 #include "native_client/src/shared/platform/nacl_time.h" 13 #include "native_client/src/shared/platform/nacl_time.h"
14 #include "ppapi/c/pp_errors.h" 14 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/c/ppb_file_io.h"
16 #include "ppapi/cpp/file_io.h"
17 #include "ppapi/cpp/file_ref.h"
18 #include "ppapi/cpp/url_request_info.h" 15 #include "ppapi/cpp/url_request_info.h"
19 #include "ppapi/cpp/url_response_info.h" 16 #include "ppapi/cpp/url_response_info.h"
20 #include "ppapi/native_client/src/trusted/plugin/callback_source.h" 17 #include "ppapi/native_client/src/trusted/plugin/callback_source.h"
21 #include "ppapi/native_client/src/trusted/plugin/plugin.h" 18 #include "ppapi/native_client/src/trusted/plugin/plugin.h"
22 #include "ppapi/native_client/src/trusted/plugin/utility.h" 19 #include "ppapi/native_client/src/trusted/plugin/utility.h"
23 20
24 namespace {
25
26 struct NaClFileInfo NoFileInfo() {
27 struct NaClFileInfo info;
28 memset(&info, 0, sizeof(info));
29 info.desc = -1;
30 return info;
31 }
32
33 } // namespace
34
35 namespace plugin { 21 namespace plugin {
36 22
37 NaClFileInfoAutoCloser::NaClFileInfoAutoCloser()
38 : info_(NoFileInfo()) {}
39
40 NaClFileInfoAutoCloser::NaClFileInfoAutoCloser(NaClFileInfo* pass_ownership)
41 : info_(*pass_ownership) {
42 *pass_ownership = NoFileInfo();
43 }
44
45 void NaClFileInfoAutoCloser::FreeResources() {
46 if (-1 != get_desc()) {
47 PLUGIN_PRINTF(("NaClFileInfoAutoCloser::FreeResources close(%d)\n",
48 get_desc()));
49 close(get_desc());
50 }
51 info_.desc = -1;
52 }
53
54 void NaClFileInfoAutoCloser::TakeOwnership(NaClFileInfo* pass_ownership) {
55 PLUGIN_PRINTF(("NaClFileInfoAutoCloser::set: taking ownership of %d\n",
56 pass_ownership->desc));
57 CHECK(pass_ownership->desc == -1 || pass_ownership->desc != get_desc());
58 FreeResources();
59 info_ = *pass_ownership;
60 *pass_ownership = NoFileInfo();
61 }
62
63 NaClFileInfo NaClFileInfoAutoCloser::Release() {
64 NaClFileInfo info_to_return = info_;
65 info_ = NoFileInfo();
66 return info_to_return;
67 }
68
69 void FileDownloader::Initialize(Plugin* instance) { 23 void FileDownloader::Initialize(Plugin* instance) {
70 PLUGIN_PRINTF(("FileDownloader::FileDownloader (this=%p)\n", 24 PLUGIN_PRINTF(("FileDownloader::FileDownloader (this=%p)\n",
71 static_cast<void*>(this))); 25 static_cast<void*>(this)));
72 CHECK(instance != NULL); 26 CHECK(instance != NULL);
73 CHECK(instance_ == NULL); // Can only initialize once. 27 CHECK(instance_ == NULL); // Can only initialize once.
74 instance_ = instance; 28 instance_ = instance;
75 callback_factory_.Initialize(this); 29 callback_factory_.Initialize(this);
76 file_io_private_interface_ = static_cast<const PPB_FileIO_Private*>(
77 pp::Module::Get()->GetBrowserInterface(PPB_FILEIO_PRIVATE_INTERFACE));
78 url_loader_trusted_interface_ = static_cast<const PPB_URLLoaderTrusted*>(
79 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE));
80 temp_buffer_.resize(kTempBufferSize); 30 temp_buffer_.resize(kTempBufferSize);
81 file_info_.FreeResources();
82 } 31 }
83 32
84 bool FileDownloader::OpenStream( 33 bool FileDownloader::OpenStream(
85 const nacl::string& url, 34 const nacl::string& url,
86 const pp::CompletionCallback& callback, 35 const pp::CompletionCallback& callback,
87 StreamCallbackSource* stream_callback_source) { 36 StreamCallbackSource* stream_callback_source) {
88 data_stream_callback_source_ = stream_callback_source; 37 data_stream_callback_source_ = stream_callback_source;
89 return Open(url, DOWNLOAD_TO_BUFFER_AND_STREAM, callback, true, NULL);
90 }
91
92 bool FileDownloader::Open(
93 const nacl::string& url,
94 DownloadMode mode,
95 const pp::CompletionCallback& callback,
96 bool record_progress,
97 PP_URLLoaderTrusted_StatusCallback progress_callback) {
98 PLUGIN_PRINTF(("FileDownloader::Open (url=%s)\n", url.c_str())); 38 PLUGIN_PRINTF(("FileDownloader::Open (url=%s)\n", url.c_str()));
99 if (callback.pp_completion_callback().func == NULL || 39 if (callback.pp_completion_callback().func == NULL || instance_ == NULL)
100 instance_ == NULL ||
101 file_io_private_interface_ == NULL)
102 return false; 40 return false;
103 41
104 CHECK(instance_ != NULL);
105 status_code_ = -1; 42 status_code_ = -1;
106 url_ = url; 43 url_ = url;
107 file_open_notify_callback_ = callback; 44 file_open_notify_callback_ = callback;
108 mode_ = mode; 45 mode_ = DOWNLOAD_TO_BUFFER_AND_STREAM;
109 file_info_.FreeResources();
110 pp::URLRequestInfo url_request(instance_); 46 pp::URLRequestInfo url_request(instance_);
111 47
112 // Allow CORS. 48 // Allow CORS.
113 // Note that "SetAllowCrossOriginRequests" (currently) has the side effect of 49 // Note that "SetAllowCrossOriginRequests" (currently) has the side effect of
114 // preventing credentials from being sent on same-origin requests. We 50 // preventing credentials from being sent on same-origin requests. We
115 // therefore avoid setting this flag unless we know for sure it is a 51 // therefore avoid setting this flag unless we know for sure it is a
116 // cross-origin request, resulting in behavior similar to XMLHttpRequest. 52 // cross-origin request, resulting in behavior similar to XMLHttpRequest.
117 if (!instance_->DocumentCanRequest(url)) 53 if (!instance_->DocumentCanRequest(url))
118 url_request.SetAllowCrossOriginRequests(true); 54 url_request.SetAllowCrossOriginRequests(true);
119 55
120 if (!extra_request_headers_.empty()) 56 if (!extra_request_headers_.empty())
121 url_request.SetHeaders(extra_request_headers_); 57 url_request.SetHeaders(extra_request_headers_);
122 58
123 // Reset the url loader and file reader. 59 // Reset the url loader and file reader.
124 // Note that we have the only reference to the underlying objects, so 60 // Note that we have the only reference to the underlying objects, so
125 // this will implicitly close any pending IO and destroy them. 61 // this will implicitly close any pending IO and destroy them.
126 url_loader_ = pp::URLLoader(instance_); 62 url_loader_ = pp::URLLoader(instance_);
127 63 url_request.SetRecordDownloadProgress(true);
128 url_request.SetRecordDownloadProgress(record_progress);
129
130 if (url_loader_trusted_interface_ != NULL) {
131 if (progress_callback != NULL) {
132 url_loader_trusted_interface_->RegisterStatusCallback(
133 url_loader_.pp_resource(), progress_callback);
134 }
135 }
136 64
137 // Prepare the url request. 65 // Prepare the url request.
138 url_request.SetURL(url_); 66 url_request.SetURL(url_);
139 67
140 if (mode_ == DOWNLOAD_TO_FILE) {
141 file_reader_ = pp::FileIO(instance_);
142 url_request.SetStreamToFile(true);
143 }
144
145 // Request asynchronous download of the url providing an on-load callback. 68 // Request asynchronous download of the url providing an on-load callback.
146 // As long as this step is guaranteed to be asynchronous, we can call 69 // As long as this step is guaranteed to be asynchronous, we can call
147 // synchronously all other internal callbacks that eventually result in the 70 // synchronously all other internal callbacks that eventually result in the
148 // invocation of the user callback. The user code will not be reentered. 71 // invocation of the user callback. The user code will not be reentered.
149 pp::CompletionCallback onload_callback = 72 pp::CompletionCallback onload_callback =
150 callback_factory_.NewCallback(&FileDownloader::URLLoadStartNotify); 73 callback_factory_.NewCallback(&FileDownloader::URLLoadStartNotify);
151 int32_t pp_error = url_loader_.Open(url_request, onload_callback); 74 int32_t pp_error = url_loader_.Open(url_request, onload_callback);
152 PLUGIN_PRINTF(("FileDownloader::Open (pp_error=%" NACL_PRId32 ")\n", 75 PLUGIN_PRINTF(("FileDownloader::Open (pp_error=%" NACL_PRId32 ")\n",
153 pp_error)); 76 pp_error));
154 CHECK(pp_error == PP_OK_COMPLETIONPENDING); 77 CHECK(pp_error == PP_OK_COMPLETIONPENDING);
(...skipping 29 matching lines...) Expand all
184 if (pp_error != PP_OK) { 107 if (pp_error != PP_OK) {
185 file_open_notify_callback_.RunAndClear(pp_error); 108 file_open_notify_callback_.RunAndClear(pp_error);
186 return; 109 return;
187 } 110 }
188 111
189 if (!InitialResponseIsValid()) { 112 if (!InitialResponseIsValid()) {
190 file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED); 113 file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED);
191 return; 114 return;
192 } 115 }
193 116
194 if (mode_ != DOWNLOAD_TO_BUFFER_AND_STREAM) {
195 FinishStreaming(file_open_notify_callback_);
196 return;
197 }
198
199 file_open_notify_callback_.RunAndClear(PP_OK); 117 file_open_notify_callback_.RunAndClear(PP_OK);
200 } 118 }
201 119
202 void FileDownloader::FinishStreaming( 120 void FileDownloader::FinishStreaming(
203 const pp::CompletionCallback& callback) { 121 const pp::CompletionCallback& callback) {
204 stream_finish_callback_ = callback; 122 stream_finish_callback_ = callback;
205 123
206 // Finish streaming the body providing an optional callback. 124 // Finish streaming the body providing an optional callback.
207 if (mode_ == DOWNLOAD_TO_FILE) { 125 pp::CompletionCallback onread_callback =
208 pp::CompletionCallback onload_callback =
209 callback_factory_.NewOptionalCallback(
210 &FileDownloader::URLLoadFinishNotify);
211 int32_t pp_error = url_loader_.FinishStreamingToFile(onload_callback);
212 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING);
213 PLUGIN_PRINTF(("FileDownloader::FinishStreaming (async_notify_ok=%d)\n",
214 async_notify_ok));
215 if (!async_notify_ok) {
216 // Call manually to free allocated memory and report errors. This calls
217 // |stream_finish_callback_| with |pp_error| as the parameter.
218 onload_callback.RunAndClear(pp_error);
219 }
220 } else {
221 pp::CompletionCallback onread_callback =
222 callback_factory_.NewOptionalCallback(
223 &FileDownloader::URLReadBodyNotify);
224 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size());
225 int32_t pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0],
226 temp_size,
227 onread_callback);
228 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING);
229 PLUGIN_PRINTF((
230 "FileDownloader::FinishStreaming (async_notify_ok=%d)\n",
231 async_notify_ok));
232 if (!async_notify_ok) {
233 onread_callback.RunAndClear(pp_error);
234 }
235 }
236 }
237
238 void FileDownloader::URLLoadFinishNotify(int32_t pp_error) {
239 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%"
240 NACL_PRId32")\n", pp_error));
241 if (pp_error != PP_OK) { // Streaming failed.
242 stream_finish_callback_.RunAndClear(pp_error);
243 return;
244 }
245
246 // Validate response again on load (though it should be the same
247 // as it was during InitialResponseIsValid?).
248 url_response_ = url_loader_.GetResponseInfo();
249 CHECK(url_response_.GetStatusCode() == NACL_HTTP_STATUS_OK);
250
251 // Record the full url from the response.
252 pp::Var full_url = url_response_.GetURL();
253 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n",
254 full_url.DebugString().c_str()));
255 if (!full_url.is_string()) {
256 stream_finish_callback_.RunAndClear(PP_ERROR_FAILED);
257 return;
258 }
259 full_url_ = full_url.AsString();
260
261 // The file is now fully downloaded.
262 pp::FileRef file(url_response_.GetBodyAsFileRef());
263 if (file.is_null()) {
264 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n"));
265 stream_finish_callback_.RunAndClear(PP_ERROR_FAILED);
266 return;
267 }
268
269 // Open the file providing an optional callback.
270 pp::CompletionCallback onopen_callback =
271 callback_factory_.NewOptionalCallback( 126 callback_factory_.NewOptionalCallback(
272 &FileDownloader::StreamFinishNotify); 127 &FileDownloader::URLReadBodyNotify);
273 pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback); 128 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size());
274 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); 129 int32_t pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0],
275 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n", 130 temp_size,
276 async_notify_ok)); 131 onread_callback);
277 if (!async_notify_ok) { 132 if (pp_error != PP_OK_COMPLETIONPENDING)
278 // Call manually to free allocated memory and report errors. This calls 133 onread_callback.RunAndClear(pp_error);
279 // |stream_finish_callback_| with |pp_error| as the parameter.
280 onopen_callback.RunAndClear(pp_error);
281 }
282 } 134 }
283 135
284 void FileDownloader::URLReadBodyNotify(int32_t pp_error) { 136 void FileDownloader::URLReadBodyNotify(int32_t pp_error) {
285 PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%" 137 PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%"
286 NACL_PRId32")\n", pp_error)); 138 NACL_PRId32")\n", pp_error));
287 if (pp_error < PP_OK) { 139 if (pp_error < PP_OK) {
288 stream_finish_callback_.RunAndClear(pp_error); 140 stream_finish_callback_.RunAndClear(pp_error);
289 } else if (pp_error == PP_OK) { 141 } else if (pp_error == PP_OK) {
290 if (mode_ == DOWNLOAD_TO_BUFFER_AND_STREAM) { 142 data_stream_callback_source_->GetCallback().RunAndClear(PP_OK);
291 data_stream_callback_source_->GetCallback().RunAndClear(PP_OK); 143 stream_finish_callback_.RunAndClear(PP_OK);
292 }
293 StreamFinishNotify(PP_OK);
294 } else { 144 } else {
295 if (mode_ == DOWNLOAD_TO_BUFFER_AND_STREAM) { 145 PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n",
296 PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n", 146 &temp_buffer_[0]));
297 &temp_buffer_[0])); 147 StreamCallback cb = data_stream_callback_source_->GetCallback();
298 StreamCallback cb = data_stream_callback_source_->GetCallback(); 148 *(cb.output()) = &temp_buffer_;
299 *(cb.output()) = &temp_buffer_; 149 cb.RunAndClear(pp_error);
300 cb.RunAndClear(pp_error); 150
301 }
302 pp::CompletionCallback onread_callback = 151 pp::CompletionCallback onread_callback =
303 callback_factory_.NewOptionalCallback( 152 callback_factory_.NewOptionalCallback(
304 &FileDownloader::URLReadBodyNotify); 153 &FileDownloader::URLReadBodyNotify);
305 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); 154 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size());
306 pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], 155 pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0],
307 temp_size, 156 temp_size,
308 onread_callback); 157 onread_callback);
309 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); 158 if (pp_error != PP_OK_COMPLETIONPENDING)
310 if (!async_notify_ok) {
311 onread_callback.RunAndClear(pp_error); 159 onread_callback.RunAndClear(pp_error);
312 }
313 } 160 }
314 } 161 }
315 162
316 bool FileDownloader::GetDownloadProgress( 163 bool FileDownloader::GetDownloadProgress(
317 int64_t* bytes_received, 164 int64_t* bytes_received,
318 int64_t* total_bytes_to_be_received) const { 165 int64_t* total_bytes_to_be_received) const {
319 return url_loader_.GetDownloadProgress(bytes_received, 166 return url_loader_.GetDownloadProgress(bytes_received,
320 total_bytes_to_be_received); 167 total_bytes_to_be_received);
321 } 168 }
322 169
323 nacl::string FileDownloader::GetResponseHeaders() const { 170 nacl::string FileDownloader::GetResponseHeaders() const {
324 pp::Var headers = url_response_.GetHeaders(); 171 pp::Var headers = url_response_.GetHeaders();
325 if (!headers.is_string()) { 172 if (!headers.is_string()) {
326 PLUGIN_PRINTF(( 173 PLUGIN_PRINTF((
327 "FileDownloader::GetResponseHeaders (headers are not a string)\n")); 174 "FileDownloader::GetResponseHeaders (headers are not a string)\n"));
328 return nacl::string(); 175 return nacl::string();
329 } 176 }
330 return headers.AsString(); 177 return headers.AsString();
331 } 178 }
332 179
333 void FileDownloader::StreamFinishNotify(int32_t pp_error) {
334 PLUGIN_PRINTF((
335 "FileDownloader::StreamFinishNotify (pp_error=%" NACL_PRId32 ")\n",
336 pp_error));
337
338 // Run the callback if we have an error, or if we don't have a file_reader_
339 // to get a file handle for.
340 if (pp_error != PP_OK || file_reader_.pp_resource() == 0) {
341 stream_finish_callback_.RunAndClear(pp_error);
342 return;
343 }
344
345 pp::CompletionCallbackWithOutput<PP_FileHandle> cb =
346 callback_factory_.NewCallbackWithOutput(
347 &FileDownloader::GotFileHandleNotify);
348 file_io_private_interface_->RequestOSFileHandle(
349 file_reader_.pp_resource(), cb.output(), cb.pp_completion_callback());
350 }
351
352 void FileDownloader::GotFileHandleNotify(int32_t pp_error,
353 PP_FileHandle handle) {
354 PLUGIN_PRINTF((
355 "FileDownloader::GotFileHandleNotify (pp_error=%" NACL_PRId32 ")\n",
356 pp_error));
357 if (pp_error == PP_OK) {
358 NaClFileInfo tmp_info = NoFileInfo();
359 tmp_info.desc = ConvertFileDescriptor(handle, false);
360 file_info_.TakeOwnership(&tmp_info);
361 }
362
363 stream_finish_callback_.RunAndClear(pp_error);
364 }
365
366 } // namespace plugin 180 } // namespace plugin
OLDNEW
« no previous file with comments | « ppapi/native_client/src/trusted/plugin/file_downloader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698