OLD | NEW |
---|---|
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 "native_client/src/trusted/plugin/file_downloader.h" | 5 #include "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 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE)); | 48 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE)); |
49 url_loader_trusted_interface_ = static_cast<const PPB_URLLoaderTrusted*>( | 49 url_loader_trusted_interface_ = static_cast<const PPB_URLLoaderTrusted*>( |
50 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE)); | 50 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADERTRUSTED_INTERFACE)); |
51 temp_buffer_.resize(kTempBufferSize); | 51 temp_buffer_.resize(kTempBufferSize); |
52 } | 52 } |
53 | 53 |
54 bool FileDownloader::OpenStream( | 54 bool FileDownloader::OpenStream( |
55 const nacl::string& url, | 55 const nacl::string& url, |
56 const pp::CompletionCallback& callback, | 56 const pp::CompletionCallback& callback, |
57 StreamCallbackSource* stream_callback_source) { | 57 StreamCallbackSource* stream_callback_source) { |
58 open_and_stream_ = false; | |
dmichael (off chromium)
2013/06/14 16:21:43
It looks like you never initialized open_and_strea
jvoung (off chromium)
2013/06/14 20:38:03
It is initialized to true in the constructor (.h f
| |
58 data_stream_callback_source_ = stream_callback_source; | 59 data_stream_callback_source_ = stream_callback_source; |
59 return Open(url, DOWNLOAD_STREAM, callback, true, NULL); | 60 return Open(url, DOWNLOAD_STREAM, callback, true, NULL); |
60 } | 61 } |
61 | 62 |
62 bool FileDownloader::Open( | 63 bool FileDownloader::Open( |
63 const nacl::string& url, | 64 const nacl::string& url, |
64 DownloadMode mode, | 65 DownloadMode mode, |
65 const pp::CompletionCallback& callback, | 66 const pp::CompletionCallback& callback, |
66 bool record_progress, | 67 bool record_progress, |
67 PP_URLLoaderTrusted_StatusCallback progress_callback) { | 68 PP_URLLoaderTrusted_StatusCallback progress_callback) { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 return (now - open_time_) / NACL_MICROS_PER_MILLI; | 217 return (now - open_time_) / NACL_MICROS_PER_MILLI; |
217 } | 218 } |
218 | 219 |
219 bool FileDownloader::InitialResponseIsValid(int32_t pp_error) { | 220 bool FileDownloader::InitialResponseIsValid(int32_t pp_error) { |
220 if (pp_error != PP_OK) { // Url loading failed. | 221 if (pp_error != PP_OK) { // Url loading failed. |
221 file_open_notify_callback_.Run(pp_error); | 222 file_open_notify_callback_.Run(pp_error); |
222 return false; | 223 return false; |
223 } | 224 } |
224 | 225 |
225 // Process the response, validating the headers to confirm successful loading. | 226 // Process the response, validating the headers to confirm successful loading. |
226 pp::URLResponseInfo url_response(url_loader_.GetResponseInfo()); | 227 url_response_ = url_loader_.GetResponseInfo(); |
227 if (url_response.is_null()) { | 228 if (url_response_.is_null()) { |
228 PLUGIN_PRINTF(( | 229 PLUGIN_PRINTF(( |
229 "FileDownloader::InitialResponseIsValid (url_response=NULL)\n")); | 230 "FileDownloader::InitialResponseIsValid (url_response_=NULL)\n")); |
dmichael (off chromium)
2013/06/14 16:21:43
nit: maybe == instead of = to be clearer
jvoung (off chromium)
2013/06/14 20:38:03
I think most of the PLUGIN_PRINTFs use = instead o
| |
230 file_open_notify_callback_.Run(PP_ERROR_FAILED); | 231 file_open_notify_callback_.Run(PP_ERROR_FAILED); |
231 return false; | 232 return false; |
232 } | 233 } |
233 // Note that URLs in the chrome-extension scheme produce different error | 234 |
234 // codes than other schemes. This is because chrome-extension URLs are | 235 pp::Var full_url = url_response_.GetURL(); |
235 // really a special kind of file scheme, and therefore do not produce HTTP | |
236 // status codes. | |
237 pp::Var full_url = url_response.GetURL(); | |
238 if (!full_url.is_string()) { | 236 if (!full_url.is_string()) { |
239 PLUGIN_PRINTF(( | 237 PLUGIN_PRINTF(( |
240 "FileDownloader::InitialResponseIsValid (url is not a string)\n")); | 238 "FileDownloader::InitialResponseIsValid (url is not a string)\n")); |
241 file_open_notify_callback_.Run(PP_ERROR_FAILED); | 239 file_open_notify_callback_.Run(PP_ERROR_FAILED); |
242 return false; | 240 return false; |
243 } | 241 } |
242 url_ = full_url.AsString(); | |
243 | |
244 // Note that URLs in the data-URI scheme produce different error | |
245 // codes than other schemes. This is because data-URI are really a | |
246 // special kind of file scheme, and therefore do not produce HTTP | |
247 // status codes. | |
244 bool status_ok = false; | 248 bool status_ok = false; |
245 status_code_ = url_response.GetStatusCode(); | 249 status_code_ = url_response_.GetStatusCode(); |
246 switch (url_scheme_) { | 250 switch (url_scheme_) { |
247 case SCHEME_CHROME_EXTENSION: | 251 case SCHEME_CHROME_EXTENSION: |
248 PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (chrome-extension " | 252 PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (chrome-extension " |
249 "response status_code=%"NACL_PRId32")\n", status_code_)); | 253 "response status_code=%"NACL_PRId32")\n", status_code_)); |
250 status_ok = (status_code_ == kExtensionUrlRequestStatusOk); | 254 status_ok = (status_code_ == kExtensionUrlRequestStatusOk); |
251 break; | 255 break; |
252 case SCHEME_DATA: | 256 case SCHEME_DATA: |
253 PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (data URI " | 257 PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (data URI " |
254 "response status_code=%"NACL_PRId32")\n", status_code_)); | 258 "response status_code=%"NACL_PRId32")\n", status_code_)); |
255 status_ok = (status_code_ == kDataUriRequestStatusOk); | 259 status_ok = (status_code_ == kDataUriRequestStatusOk); |
(...skipping 11 matching lines...) Expand all Loading... | |
267 } | 271 } |
268 | 272 |
269 return true; | 273 return true; |
270 } | 274 } |
271 | 275 |
272 void FileDownloader::URLLoadStartNotify(int32_t pp_error) { | 276 void FileDownloader::URLLoadStartNotify(int32_t pp_error) { |
273 PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%" | 277 PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%" |
274 NACL_PRId32")\n", pp_error)); | 278 NACL_PRId32")\n", pp_error)); |
275 | 279 |
276 if (!InitialResponseIsValid(pp_error)) | 280 if (!InitialResponseIsValid(pp_error)) |
281 // InitialResponseIsValid() calls file_open_notify_callback_ on errors. | |
277 return; | 282 return; |
dmichael (off chromium)
2013/06/14 16:21:43
style nit: use braces since it's >1 line now
jvoung (off chromium)
2013/06/14 20:38:03
Done.
| |
283 | |
284 if (open_and_stream_) | |
285 return FinishStreaming(file_open_notify_callback_); | |
286 | |
287 file_open_notify_callback_.Run(pp_error); | |
288 } | |
289 | |
290 void FileDownloader::URLBufferStartNotify(int32_t pp_error) { | |
291 PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (pp_error=%" | |
292 NACL_PRId32")\n", pp_error)); | |
293 | |
294 if (!InitialResponseIsValid(pp_error)) | |
295 // InitialResponseIsValid() calls file_open_notify_callback_ on errors. | |
296 return; | |
dmichael (off chromium)
2013/06/14 16:21:43
style nit: curly braces
jvoung (off chromium)
2013/06/14 20:38:03
Done.
| |
297 | |
298 if (open_and_stream_) | |
299 return FinishStreaming(file_open_notify_callback_); | |
300 | |
301 file_open_notify_callback_.Run(pp_error); | |
dmichael (off chromium)
2013/06/14 16:21:43
It would be nice to clear the callback after you r
jvoung (off chromium)
2013/06/14 20:38:03
Like set them to PP_BlockUntilComplete()?
I thin
dmichael (off chromium)
2013/06/14 21:09:03
Right, that's what I meant:
file_open_notify_callb
jvoung (off chromium)
2013/06/17 18:20:27
Okay, there was a RunAndClearCompletionCallback fu
| |
302 } | |
303 | |
304 void FileDownloader::FinishStreaming( | |
305 const pp::CompletionCallback& callback) { | |
306 stream_finish_callback_ = callback; | |
307 | |
278 // Finish streaming the body providing an optional callback. | 308 // Finish streaming the body providing an optional callback. |
279 pp::CompletionCallback onload_callback = | 309 if (streaming_to_file()) { |
280 callback_factory_.NewOptionalCallback( | 310 pp::CompletionCallback onload_callback = |
281 &FileDownloader::URLLoadFinishNotify); | 311 callback_factory_.NewOptionalCallback( |
282 pp_error = url_loader_.FinishStreamingToFile(onload_callback); | 312 &FileDownloader::URLLoadFinishNotify); |
283 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); | 313 int32_t pp_error = url_loader_.FinishStreamingToFile(onload_callback); |
284 PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (async_notify_ok=%d)\n", | 314 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
285 async_notify_ok)); | 315 PLUGIN_PRINTF(("FileDownloader::FinishStreaming (async_notify_ok=%d)\n", |
286 if (!async_notify_ok) { | 316 async_notify_ok)); |
287 // Call manually to free allocated memory and report errors. This calls | 317 if (!async_notify_ok) { |
288 // |file_open_notify_callback_| with |pp_error| as the parameter. | 318 // Call manually to free allocated memory and report errors. This calls |
289 onload_callback.Run(pp_error); | 319 // |stream_finish_callback_| with |pp_error| as the parameter. |
320 onload_callback.Run(pp_error); | |
321 } | |
322 } else { | |
323 pp::CompletionCallback onread_callback = | |
324 callback_factory_.NewOptionalCallback( | |
325 &FileDownloader::URLReadBodyNotify); | |
326 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); | |
327 int32_t pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], | |
328 temp_size, | |
329 onread_callback); | |
330 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); | |
331 PLUGIN_PRINTF(( | |
332 "FileDownloader::FinishStreaming (async_notify_ok=%d)\n", | |
333 async_notify_ok)); | |
334 if (!async_notify_ok) { | |
335 onread_callback.Run(pp_error); | |
336 } | |
290 } | 337 } |
291 } | 338 } |
292 | 339 |
293 void FileDownloader::URLLoadFinishNotify(int32_t pp_error) { | 340 void FileDownloader::URLLoadFinishNotify(int32_t pp_error) { |
294 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%" | 341 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%" |
295 NACL_PRId32")\n", pp_error)); | 342 NACL_PRId32")\n", pp_error)); |
296 if (pp_error != PP_OK) { // Streaming failed. | 343 if (pp_error != PP_OK) { // Streaming failed. |
297 file_open_notify_callback_.Run(pp_error); | 344 stream_finish_callback_.Run(pp_error); |
298 return; | 345 return; |
299 } | 346 } |
300 | 347 |
301 pp::URLResponseInfo url_response(url_loader_.GetResponseInfo()); | 348 // Validate response again on load (though it should be the same |
302 // Validated on load. | 349 // as it was during InitialResponseIsValid?). |
303 CHECK(url_response.GetStatusCode() == NACL_HTTP_STATUS_OK || | 350 url_response_ = url_loader_.GetResponseInfo(); |
304 url_response.GetStatusCode() == kExtensionUrlRequestStatusOk); | 351 CHECK(url_response_.GetStatusCode() == NACL_HTTP_STATUS_OK || |
352 url_response_.GetStatusCode() == kExtensionUrlRequestStatusOk); | |
305 | 353 |
306 // Record the full url from the response. | 354 // Record the full url from the response. |
307 pp::Var full_url = url_response.GetURL(); | 355 pp::Var full_url = url_response_.GetURL(); |
308 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n", | 356 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n", |
309 full_url.DebugString().c_str())); | 357 full_url.DebugString().c_str())); |
310 if (!full_url.is_string()) { | 358 if (!full_url.is_string()) { |
311 file_open_notify_callback_.Run(PP_ERROR_FAILED); | 359 stream_finish_callback_.Run(PP_ERROR_FAILED); |
312 return; | 360 return; |
313 } | 361 } |
314 url_ = full_url.AsString(); | 362 url_ = full_url.AsString(); |
315 | 363 |
316 // The file is now fully downloaded. | 364 // The file is now fully downloaded. |
317 pp::FileRef file(url_response.GetBodyAsFileRef()); | 365 pp::FileRef file(url_response_.GetBodyAsFileRef()); |
318 if (file.is_null()) { | 366 if (file.is_null()) { |
319 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n")); | 367 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n")); |
320 file_open_notify_callback_.Run(PP_ERROR_FAILED); | 368 stream_finish_callback_.Run(PP_ERROR_FAILED); |
321 return; | 369 return; |
322 } | 370 } |
323 | 371 |
324 // Open the file providing an optional callback. | 372 // Open the file providing an optional callback. |
325 pp::CompletionCallback onopen_callback = | 373 pp::CompletionCallback onopen_callback = |
326 callback_factory_.NewOptionalCallback(&FileDownloader::FileOpenNotify); | 374 callback_factory_.NewOptionalCallback( |
375 &FileDownloader::StreamFinishNotify); | |
327 pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback); | 376 pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback); |
328 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); | 377 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
329 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n", | 378 PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n", |
330 async_notify_ok)); | 379 async_notify_ok)); |
331 if (!async_notify_ok) { | 380 if (!async_notify_ok) { |
332 // Call manually to free allocated memory and report errors. This calls | 381 // Call manually to free allocated memory and report errors. This calls |
333 // |file_open_notify_callback_| with |pp_error| as the parameter. | 382 // |stream_finish_callback_| with |pp_error| as the parameter. |
334 onopen_callback.Run(pp_error); | 383 onopen_callback.Run(pp_error); |
335 } | 384 } |
336 } | 385 } |
337 | 386 |
338 void FileDownloader::URLBufferStartNotify(int32_t pp_error) { | |
339 PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (pp_error=%" | |
340 NACL_PRId32")\n", pp_error)); | |
341 | |
342 if (!InitialResponseIsValid(pp_error)) | |
343 return; | |
344 // Finish streaming the body asynchronously providing a callback. | |
345 pp::CompletionCallback onread_callback = | |
346 callback_factory_.NewOptionalCallback(&FileDownloader::URLReadBodyNotify); | |
347 | |
348 int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); | |
349 pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], | |
350 temp_size, | |
351 onread_callback); | |
352 bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); | |
353 PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (async_notify_ok=%d)\n", | |
354 async_notify_ok)); | |
355 if (!async_notify_ok) { | |
356 onread_callback.Run(pp_error); | |
357 } | |
358 } | |
359 | |
360 void FileDownloader::URLReadBodyNotify(int32_t pp_error) { | 387 void FileDownloader::URLReadBodyNotify(int32_t pp_error) { |
361 PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%" | 388 PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%" |
362 NACL_PRId32")\n", pp_error)); | 389 NACL_PRId32")\n", pp_error)); |
363 if (pp_error < PP_OK) { | 390 if (pp_error < PP_OK) { |
364 file_open_notify_callback_.Run(pp_error); | 391 stream_finish_callback_.Run(pp_error); |
365 } else if (pp_error == PP_OK) { | 392 } else if (pp_error == PP_OK) { |
366 if (streaming_to_user()) { | 393 if (streaming_to_user()) { |
367 data_stream_callback_source_->GetCallback().Run(PP_OK); | 394 data_stream_callback_source_->GetCallback().Run(PP_OK); |
368 } | 395 } |
369 FileOpenNotify(PP_OK); | 396 StreamFinishNotify(PP_OK); |
370 } else { | 397 } else { |
371 if (streaming_to_buffer()) { | 398 if (streaming_to_buffer()) { |
372 buffer_.insert(buffer_.end(), &temp_buffer_[0], &temp_buffer_[pp_error]); | 399 buffer_.insert(buffer_.end(), &temp_buffer_[0], &temp_buffer_[pp_error]); |
373 } else if (streaming_to_user()) { | 400 } else if (streaming_to_user()) { |
374 PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n", | 401 PLUGIN_PRINTF(("Running data_stream_callback, temp_buffer_=%p\n", |
375 &temp_buffer_[0])); | 402 &temp_buffer_[0])); |
376 StreamCallback cb = data_stream_callback_source_->GetCallback(); | 403 StreamCallback cb = data_stream_callback_source_->GetCallback(); |
377 *(cb.output()) = &temp_buffer_; | 404 *(cb.output()) = &temp_buffer_; |
378 cb.Run(pp_error); | 405 cb.Run(pp_error); |
379 } | 406 } |
(...skipping 11 matching lines...) Expand all Loading... | |
391 } | 418 } |
392 } | 419 } |
393 | 420 |
394 bool FileDownloader::GetDownloadProgress( | 421 bool FileDownloader::GetDownloadProgress( |
395 int64_t* bytes_received, | 422 int64_t* bytes_received, |
396 int64_t* total_bytes_to_be_received) const { | 423 int64_t* total_bytes_to_be_received) const { |
397 return url_loader_.GetDownloadProgress(bytes_received, | 424 return url_loader_.GetDownloadProgress(bytes_received, |
398 total_bytes_to_be_received); | 425 total_bytes_to_be_received); |
399 } | 426 } |
400 | 427 |
401 void FileDownloader::FileOpenNotify(int32_t pp_error) { | 428 nacl::string FileDownloader::GetResponseHeaders() const { |
402 PLUGIN_PRINTF(("FileDownloader::FileOpenNotify (pp_error=%"NACL_PRId32")\n", | 429 pp::Var headers = url_response_.GetHeaders(); |
403 pp_error)); | 430 if (!headers.is_string()) { |
404 file_open_notify_callback_.Run(pp_error); | 431 PLUGIN_PRINTF(( |
432 "FileDownloader::GetResponseHeaders (headers are not a string)\n")); | |
433 return nacl::string(); | |
434 } | |
435 return headers.AsString(); | |
436 } | |
437 | |
438 void FileDownloader::StreamFinishNotify(int32_t pp_error) { | |
439 PLUGIN_PRINTF(( | |
440 "FileDownloader::StreamFinishNotify (pp_error=%"NACL_PRId32")\n", | |
441 pp_error)); | |
442 stream_finish_callback_.Run(pp_error); | |
405 } | 443 } |
406 | 444 |
407 bool FileDownloader::streaming_to_file() const { | 445 bool FileDownloader::streaming_to_file() const { |
408 return mode_ == DOWNLOAD_TO_FILE; | 446 return mode_ == DOWNLOAD_TO_FILE; |
409 } | 447 } |
410 | 448 |
411 bool FileDownloader::streaming_to_buffer() const { | 449 bool FileDownloader::streaming_to_buffer() const { |
412 return mode_ == DOWNLOAD_TO_BUFFER; | 450 return mode_ == DOWNLOAD_TO_BUFFER; |
413 } | 451 } |
414 | 452 |
415 bool FileDownloader::streaming_to_user() const { | 453 bool FileDownloader::streaming_to_user() const { |
416 return mode_ == DOWNLOAD_STREAM; | 454 return mode_ == DOWNLOAD_STREAM; |
417 } | 455 } |
418 | 456 |
419 bool FileDownloader::not_streaming() const { | 457 bool FileDownloader::not_streaming() const { |
420 return mode_ == DOWNLOAD_NONE; | 458 return mode_ == DOWNLOAD_NONE; |
421 } | 459 } |
422 | 460 |
423 } // namespace plugin | 461 } // namespace plugin |
OLD | NEW |