Index: ppapi/native_client/src/trusted/plugin/file_downloader.cc |
diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.cc b/ppapi/native_client/src/trusted/plugin/file_downloader.cc |
index 170812421cc3e2b3b1ddeebe8295aa4415917d6b..b66a267de1daaa8e8339e9a3f697abd6d3a86033 100644 |
--- a/ppapi/native_client/src/trusted/plugin/file_downloader.cc |
+++ b/ppapi/native_client/src/trusted/plugin/file_downloader.cc |
@@ -55,6 +55,7 @@ bool FileDownloader::OpenStream( |
const nacl::string& url, |
const pp::CompletionCallback& callback, |
StreamCallbackSource* stream_callback_source) { |
+ open_and_stream_ = false; |
data_stream_callback_source_ = stream_callback_source; |
return Open(url, DOWNLOAD_STREAM, callback, true, NULL); |
} |
@@ -218,31 +219,34 @@ int64_t FileDownloader::TimeSinceOpenMilliseconds() const { |
bool FileDownloader::InitialResponseIsValid(int32_t pp_error) { |
if (pp_error != PP_OK) { // Url loading failed. |
- file_open_notify_callback_.Run(pp_error); |
+ file_open_notify_callback_.RunAndClear(pp_error); |
return false; |
} |
// Process the response, validating the headers to confirm successful loading. |
- pp::URLResponseInfo url_response(url_loader_.GetResponseInfo()); |
- if (url_response.is_null()) { |
+ url_response_ = url_loader_.GetResponseInfo(); |
+ if (url_response_.is_null()) { |
PLUGIN_PRINTF(( |
- "FileDownloader::InitialResponseIsValid (url_response=NULL)\n")); |
- file_open_notify_callback_.Run(PP_ERROR_FAILED); |
+ "FileDownloader::InitialResponseIsValid (url_response_=NULL)\n")); |
+ file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED); |
return false; |
} |
- // Note that URLs in the chrome-extension scheme produce different error |
- // codes than other schemes. This is because chrome-extension URLs are |
- // really a special kind of file scheme, and therefore do not produce HTTP |
- // status codes. |
- pp::Var full_url = url_response.GetURL(); |
+ |
+ pp::Var full_url = url_response_.GetURL(); |
if (!full_url.is_string()) { |
PLUGIN_PRINTF(( |
"FileDownloader::InitialResponseIsValid (url is not a string)\n")); |
- file_open_notify_callback_.Run(PP_ERROR_FAILED); |
+ file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED); |
return false; |
} |
+ url_ = full_url.AsString(); |
+ |
+ // Note that URLs in the data-URI scheme produce different error |
+ // codes than other schemes. This is because data-URI are really a |
+ // special kind of file scheme, and therefore do not produce HTTP |
+ // status codes. |
bool status_ok = false; |
- status_code_ = url_response.GetStatusCode(); |
+ status_code_ = url_response_.GetStatusCode(); |
switch (url_scheme_) { |
case SCHEME_CHROME_EXTENSION: |
PLUGIN_PRINTF(("FileDownloader::InitialResponseIsValid (chrome-extension " |
@@ -262,7 +266,7 @@ bool FileDownloader::InitialResponseIsValid(int32_t pp_error) { |
} |
if (!status_ok) { |
- file_open_notify_callback_.Run(PP_ERROR_FAILED); |
+ file_open_notify_callback_.RunAndClear(PP_ERROR_FAILED); |
return false; |
} |
@@ -273,20 +277,65 @@ void FileDownloader::URLLoadStartNotify(int32_t pp_error) { |
PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (pp_error=%" |
NACL_PRId32")\n", pp_error)); |
- if (!InitialResponseIsValid(pp_error)) |
+ if (!InitialResponseIsValid(pp_error)) { |
+ // InitialResponseIsValid() calls file_open_notify_callback_ on errors. |
+ return; |
+ } |
+ |
+ if (open_and_stream_) |
+ return FinishStreaming(file_open_notify_callback_); |
+ |
+ file_open_notify_callback_.RunAndClear(pp_error); |
+} |
+ |
+void FileDownloader::URLBufferStartNotify(int32_t pp_error) { |
+ PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (pp_error=%" |
+ NACL_PRId32")\n", pp_error)); |
+ |
+ if (!InitialResponseIsValid(pp_error)) { |
+ // InitialResponseIsValid() calls file_open_notify_callback_ on errors. |
return; |
+ } |
+ |
+ if (open_and_stream_) |
+ return FinishStreaming(file_open_notify_callback_); |
+ |
+ file_open_notify_callback_.RunAndClear(pp_error); |
+} |
+ |
+void FileDownloader::FinishStreaming( |
+ const pp::CompletionCallback& callback) { |
+ stream_finish_callback_ = callback; |
+ |
// Finish streaming the body providing an optional callback. |
- pp::CompletionCallback onload_callback = |
- callback_factory_.NewOptionalCallback( |
- &FileDownloader::URLLoadFinishNotify); |
- pp_error = url_loader_.FinishStreamingToFile(onload_callback); |
- bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
- PLUGIN_PRINTF(("FileDownloader::URLLoadStartNotify (async_notify_ok=%d)\n", |
- async_notify_ok)); |
- if (!async_notify_ok) { |
- // Call manually to free allocated memory and report errors. This calls |
- // |file_open_notify_callback_| with |pp_error| as the parameter. |
- onload_callback.Run(pp_error); |
+ if (streaming_to_file()) { |
+ pp::CompletionCallback onload_callback = |
+ callback_factory_.NewOptionalCallback( |
+ &FileDownloader::URLLoadFinishNotify); |
+ int32_t pp_error = url_loader_.FinishStreamingToFile(onload_callback); |
+ bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
+ PLUGIN_PRINTF(("FileDownloader::FinishStreaming (async_notify_ok=%d)\n", |
+ async_notify_ok)); |
+ if (!async_notify_ok) { |
+ // Call manually to free allocated memory and report errors. This calls |
+ // |stream_finish_callback_| with |pp_error| as the parameter. |
+ onload_callback.RunAndClear(pp_error); |
+ } |
+ } else { |
+ pp::CompletionCallback onread_callback = |
+ callback_factory_.NewOptionalCallback( |
+ &FileDownloader::URLReadBodyNotify); |
+ int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); |
+ int32_t pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], |
+ temp_size, |
+ onread_callback); |
+ bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
+ PLUGIN_PRINTF(( |
+ "FileDownloader::FinishStreaming (async_notify_ok=%d)\n", |
+ async_notify_ok)); |
+ if (!async_notify_ok) { |
+ onread_callback.RunAndClear(pp_error); |
+ } |
} |
} |
@@ -294,66 +343,46 @@ void FileDownloader::URLLoadFinishNotify(int32_t pp_error) { |
PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (pp_error=%" |
NACL_PRId32")\n", pp_error)); |
if (pp_error != PP_OK) { // Streaming failed. |
- file_open_notify_callback_.Run(pp_error); |
+ stream_finish_callback_.RunAndClear(pp_error); |
return; |
} |
- pp::URLResponseInfo url_response(url_loader_.GetResponseInfo()); |
- // Validated on load. |
- CHECK(url_response.GetStatusCode() == NACL_HTTP_STATUS_OK || |
- url_response.GetStatusCode() == kExtensionUrlRequestStatusOk); |
+ // Validate response again on load (though it should be the same |
+ // as it was during InitialResponseIsValid?). |
+ url_response_ = url_loader_.GetResponseInfo(); |
+ CHECK(url_response_.GetStatusCode() == NACL_HTTP_STATUS_OK || |
+ url_response_.GetStatusCode() == kExtensionUrlRequestStatusOk); |
// Record the full url from the response. |
- pp::Var full_url = url_response.GetURL(); |
+ pp::Var full_url = url_response_.GetURL(); |
PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (full_url=%s)\n", |
full_url.DebugString().c_str())); |
if (!full_url.is_string()) { |
- file_open_notify_callback_.Run(PP_ERROR_FAILED); |
+ stream_finish_callback_.RunAndClear(PP_ERROR_FAILED); |
return; |
} |
url_ = full_url.AsString(); |
// The file is now fully downloaded. |
- pp::FileRef file(url_response.GetBodyAsFileRef()); |
+ pp::FileRef file(url_response_.GetBodyAsFileRef()); |
if (file.is_null()) { |
PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (file=NULL)\n")); |
- file_open_notify_callback_.Run(PP_ERROR_FAILED); |
+ stream_finish_callback_.RunAndClear(PP_ERROR_FAILED); |
return; |
} |
// Open the file providing an optional callback. |
pp::CompletionCallback onopen_callback = |
- callback_factory_.NewOptionalCallback(&FileDownloader::FileOpenNotify); |
+ callback_factory_.NewOptionalCallback( |
+ &FileDownloader::StreamFinishNotify); |
pp_error = file_reader_.Open(file, PP_FILEOPENFLAG_READ, onopen_callback); |
bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
PLUGIN_PRINTF(("FileDownloader::URLLoadFinishNotify (async_notify_ok=%d)\n", |
async_notify_ok)); |
if (!async_notify_ok) { |
// Call manually to free allocated memory and report errors. This calls |
- // |file_open_notify_callback_| with |pp_error| as the parameter. |
- onopen_callback.Run(pp_error); |
- } |
-} |
- |
-void FileDownloader::URLBufferStartNotify(int32_t pp_error) { |
- PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (pp_error=%" |
- NACL_PRId32")\n", pp_error)); |
- |
- if (!InitialResponseIsValid(pp_error)) |
- return; |
- // Finish streaming the body asynchronously providing a callback. |
- pp::CompletionCallback onread_callback = |
- callback_factory_.NewOptionalCallback(&FileDownloader::URLReadBodyNotify); |
- |
- int32_t temp_size = static_cast<int32_t>(temp_buffer_.size()); |
- pp_error = url_loader_.ReadResponseBody(&temp_buffer_[0], |
- temp_size, |
- onread_callback); |
- bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
- PLUGIN_PRINTF(("FileDownloader::URLBufferStartNotify (async_notify_ok=%d)\n", |
- async_notify_ok)); |
- if (!async_notify_ok) { |
- onread_callback.Run(pp_error); |
+ // |stream_finish_callback_| with |pp_error| as the parameter. |
+ onopen_callback.RunAndClear(pp_error); |
} |
} |
@@ -361,12 +390,12 @@ void FileDownloader::URLReadBodyNotify(int32_t pp_error) { |
PLUGIN_PRINTF(("FileDownloader::URLReadBodyNotify (pp_error=%" |
NACL_PRId32")\n", pp_error)); |
if (pp_error < PP_OK) { |
- file_open_notify_callback_.Run(pp_error); |
+ stream_finish_callback_.RunAndClear(pp_error); |
} else if (pp_error == PP_OK) { |
if (streaming_to_user()) { |
- data_stream_callback_source_->GetCallback().Run(PP_OK); |
+ data_stream_callback_source_->GetCallback().RunAndClear(PP_OK); |
} |
- FileOpenNotify(PP_OK); |
+ StreamFinishNotify(PP_OK); |
} else { |
if (streaming_to_buffer()) { |
buffer_.insert(buffer_.end(), &temp_buffer_[0], &temp_buffer_[pp_error]); |
@@ -375,7 +404,7 @@ void FileDownloader::URLReadBodyNotify(int32_t pp_error) { |
&temp_buffer_[0])); |
StreamCallback cb = data_stream_callback_source_->GetCallback(); |
*(cb.output()) = &temp_buffer_; |
- cb.Run(pp_error); |
+ cb.RunAndClear(pp_error); |
} |
pp::CompletionCallback onread_callback = |
callback_factory_.NewOptionalCallback( |
@@ -386,7 +415,7 @@ void FileDownloader::URLReadBodyNotify(int32_t pp_error) { |
onread_callback); |
bool async_notify_ok = (pp_error == PP_OK_COMPLETIONPENDING); |
if (!async_notify_ok) { |
- onread_callback.Run(pp_error); |
+ onread_callback.RunAndClear(pp_error); |
} |
} |
} |
@@ -398,10 +427,21 @@ bool FileDownloader::GetDownloadProgress( |
total_bytes_to_be_received); |
} |
-void FileDownloader::FileOpenNotify(int32_t pp_error) { |
- PLUGIN_PRINTF(("FileDownloader::FileOpenNotify (pp_error=%"NACL_PRId32")\n", |
- pp_error)); |
- file_open_notify_callback_.Run(pp_error); |
+nacl::string FileDownloader::GetResponseHeaders() const { |
+ pp::Var headers = url_response_.GetHeaders(); |
+ if (!headers.is_string()) { |
+ PLUGIN_PRINTF(( |
+ "FileDownloader::GetResponseHeaders (headers are not a string)\n")); |
+ return nacl::string(); |
+ } |
+ return headers.AsString(); |
+} |
+ |
+void FileDownloader::StreamFinishNotify(int32_t pp_error) { |
+ PLUGIN_PRINTF(( |
+ "FileDownloader::StreamFinishNotify (pp_error=%"NACL_PRId32")\n", |
+ pp_error)); |
+ stream_finish_callback_.RunAndClear(pp_error); |
} |
bool FileDownloader::streaming_to_file() const { |