Implementing error, close, finish, abort events management.

This commit is contained in:
ali.ibrahim 2016-10-04 17:12:17 +02:00
parent bde30b90e8
commit ec1fc5a17b
7 changed files with 391 additions and 117 deletions

View file

@ -106,12 +106,12 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) {
}
void AtomURLRequest::Abort() const {
void AtomURLRequest::Cancel() const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
base::Bind(&AtomURLRequest::DoAbort, this));
base::Bind(&AtomURLRequest::DoCancel, this));
}
void AtomURLRequest::SetExtraHeader(const std::string& name,
@ -202,7 +202,7 @@ void AtomURLRequest::DoWriteBuffer(
}
}
void AtomURLRequest::DoAbort() const {
void AtomURLRequest::DoCancel() const {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
request_->Cancel();
}
@ -235,38 +235,32 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) {
const auto& status = request_->status();
if (status.is_success()) {
// Cache net::HttpResponseHeaders instance, a read-only objects
// so that headers and other http metainformation can be simultaneously
// read from UI thread while request data is simulataneously streaming
// on IO thread.
response_headers_ = request_->response_headers();
// Success or pending trigger a Read.
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this));
ReadResponse();
} else {
} else if (status.status() == net::URLRequestStatus::Status::FAILED) {
// Report error on Start.
DoCancel();
auto error = net::ErrorToString(status.ToNetError());
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateErrorOccured,
base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured,
this,
std::move(error)));
}
// We don't report an error is the request is canceled.
}
void AtomURLRequest::ReadResponse() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
// Some servers may treat HEAD requests as GET requests. To free up the
// network connection as soon as possible, signal that the request has
// completed immediately, without trying to read any data back (all we care
// about is the response code and headers, which we already have).
int bytes_read = 0;
if (request_->status().is_success())
if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read))
bytes_read = -1;
OnReadCompleted(request_.get(), bytes_read);
int bytes_read = -1;
if (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) {
OnReadCompleted(request_.get(), bytes_read);
}
}
@ -277,36 +271,53 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request,
DCHECK_EQ(request, request_.get());
const auto status = request_->status();
bool response_error = false;
bool data_ended = false;
bool data_transfer_error = false;
do {
if (!status.is_success() || bytes_read <= 0) {
auto error = net::ErrorToString(status.ToNetError());
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateErrorOccured,
this,
std::move(error)));
if (!status.is_success()) {
response_error = true;
break;
}
if (bytes_read == 0) {
data_ended = true;
break;
}
if (bytes_read < 0 || !CopyAndPostBuffer(bytes_read)) {
data_transfer_error = true;
break;
}
const auto result = CopyAndPostBuffer(bytes_read);
if (!result)
// Failed to transfer data to UI thread.
return;
} while (request_->Read(response_read_buffer_.get(),
kBufferSize,
&bytes_read));
if (!status.is_io_pending())
if (response_error) {
DoCancel();
auto error = net::ErrorToString(status.ToNetError());
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured,
this,
std::move(error)));
} else if (data_ended) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this));
} else if (data_transfer_error) {
// We abort the request on corrupted data transfer.
DoCancel();
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured,
this,
"Failed to transfer data from IO to UI thread."));
}
}
bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
// data is only a wrapper for the async response_read_buffer_.
// data is only a wrapper for the asynchronous response_read_buffer_.
// Make a deep copy of payload and transfer ownership to the UI thread.
auto buffer_copy = new net::IOBufferWithSize(bytes_read);
memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read);
@ -349,13 +360,20 @@ void AtomURLRequest::InformDelegateResponseCompleted() const {
delegate_->OnResponseCompleted();
}
void AtomURLRequest::InformDelegateErrorOccured(
void AtomURLRequest::InformDelegateRequestErrorOccured(
const std::string& error) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (delegate_)
delegate_->OnError(error);
delegate_->OnRequestError(error);
}
void AtomURLRequest::InformDelegateResponseErrorOccured(
const std::string& error) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (delegate_)
delegate_->OnResponseError(error);
}
} // namespace atom