Index: android_webview/browser/net/android_stream_reader_url_request_job.cc |
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc |
index 835758b9b5ec8cf82acbd3f4e8d379113431370f..c2c478362281a0b74bafa225ffc89c3d5c1d2b65 100644 |
--- a/android_webview/browser/net/android_stream_reader_url_request_job.cc |
+++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc |
@@ -4,6 +4,8 @@ |
#include "android_webview/browser/net/android_stream_reader_url_request_job.h" |
+#include <string> |
+ |
#include "android_webview/browser/input_stream.h" |
#include "android_webview/browser/net/input_stream_reader.h" |
#include "base/android/jni_android.h" |
@@ -13,6 +15,7 @@ |
#include "base/lazy_instance.h" |
#include "base/message_loop.h" |
#include "base/message_loop_proxy.h" |
+#include "base/strings/string_number_conversions.h" |
#include "base/task_runner.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "base/threading/thread.h" |
@@ -21,6 +24,8 @@ |
#include "net/base/mime_util.h" |
#include "net/base/net_errors.h" |
#include "net/base/net_util.h" |
+#include "net/http/http_response_headers.h" |
+#include "net/http/http_response_info.h" |
#include "net/http/http_util.h" |
#include "net/url_request/url_request.h" |
#include "net/url_request/url_request_job_manager.h" |
@@ -31,6 +36,16 @@ using base::android::AttachCurrentThread; |
using base::PostTaskAndReplyWithResult; |
using content::BrowserThread; |
+namespace { |
+ |
+const int kHTTPOk = 200; |
+const int kHTTPNotFound = 404; |
+ |
+const char kHTTPOkText[] = "OK"; |
+const char kHTTPNotFoundText[] = "Not Found"; |
+ |
+} // namespace |
+ |
// The requests posted to the worker thread might outlive the job. Thread-safe |
// ref counting is used to ensure that the InputStream and InputStreamReader |
// members of this class are still there when the closure is run on the worker |
@@ -155,8 +170,9 @@ void AndroidStreamReaderURLRequestJob::OnInputStreamOpened( |
if (restart_required) { |
NotifyRestartRequired(); |
} else { |
- NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
- net::ERR_FAILED)); |
+ // Clear the IO_PENDING status set in Start(). |
+ SetStatus(net::URLRequestStatus()); |
+ HeadersComplete(kHTTPNotFound, kHTTPNotFoundText); |
} |
return; |
} |
@@ -185,7 +201,7 @@ void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) { |
SetStatus(net::URLRequestStatus()); |
if (result >= 0) { |
set_expected_content_size(result); |
- NotifyHeadersComplete(); |
+ HeadersComplete(kHTTPOk, kHTTPOkText); |
} else { |
NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); |
} |
@@ -220,7 +236,13 @@ bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, |
int dest_size, |
int* bytes_read) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(input_stream_reader_wrapper_); |
+ if (!input_stream_reader_wrapper_) { |
+ // This will happen if opening the InputStream fails in which case the |
+ // error is communicated by setting the HTTP response status header rather |
+ // than failing the request during the header fetch phase. |
+ *bytes_read = 0; |
+ return true; |
+ } |
PostTaskAndReplyWithResult( |
GetWorkerThreadRunner(), |
@@ -270,6 +292,54 @@ bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) { |
env, request(), input_stream_reader_wrapper_->input_stream(), charset); |
} |
+void AndroidStreamReaderURLRequestJob::HeadersComplete( |
+ int status_code, |
+ const std::string& status_text) { |
+ std::string status("HTTP/1.1 "); |
+ status.append(base::IntToString(status_code)); |
+ status.append(" "); |
+ status.append(status_text); |
+ // HttpResponseHeaders expects its input string to be terminated by two NULs. |
+ status.append("\0\0", 2); |
+ net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); |
+ |
+ if (status_code == kHTTPOk) { |
+ if (expected_content_size() != -1) { |
+ std::string content_length_header( |
+ net::HttpRequestHeaders::kContentLength); |
+ content_length_header.append(": "); |
+ content_length_header.append( |
+ base::Int64ToString(expected_content_size())); |
+ headers->AddHeader(content_length_header); |
+ } |
+ |
+ std::string mime_type; |
+ if (GetMimeType(&mime_type) && !mime_type.empty()) { |
+ std::string content_type_header(net::HttpRequestHeaders::kContentType); |
+ content_type_header.append(": "); |
+ content_type_header.append(mime_type); |
+ headers->AddHeader(content_type_header); |
+ } |
+ } |
+ |
+ response_info_.reset(new net::HttpResponseInfo()); |
+ response_info_->headers = headers; |
+ |
+ NotifyHeadersComplete(); |
+} |
+ |
+int AndroidStreamReaderURLRequestJob::GetResponseCode() const { |
+ if (response_info_) |
+ return response_info_->headers->response_code(); |
+ return URLRequestJob::GetResponseCode(); |
+} |
+ |
+void AndroidStreamReaderURLRequestJob::GetResponseInfo( |
+ net::HttpResponseInfo* info) { |
+ if (response_info_) |
+ *info = *response_info_; |
+} |
+ |
void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( |
const net::HttpRequestHeaders& headers) { |
std::string range_header; |