Implementing URLRequest API, getting response body.

This commit is contained in:
ali.ibrahim 2016-09-21 09:23:00 +02:00
parent 81eab9887b
commit 2d9d4af98d
6 changed files with 313 additions and 76 deletions

View file

@ -8,11 +8,19 @@
#include "atom/browser/atom_browser_context.h"
#include "base/callback.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
namespace {
const int kBufferSize = 4096;
} // namespace
namespace atom {
AtomURLRequest::AtomURLRequest(base::WeakPtr<api::URLRequest> delegate)
: delegate_(delegate) {
: delegate_(delegate)
, buffer_( new net::IOBuffer(kBufferSize)) {
}
AtomURLRequest::~AtomURLRequest() {
@ -48,7 +56,7 @@ void AtomURLRequest::Write() {
}
void AtomURLRequest::End() {
// post to io thread
// Called on content::BrowserThread::UI
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&AtomURLRequest::StartOnIOThread, this));
@ -71,24 +79,15 @@ void AtomURLRequest::RemoveHeader() {
int AtomURLRequest::StatusCode() {
return url_request_->GetResponseCode();
}
void AtomURLRequest::StatusMessage() {
}
void AtomURLRequest::ResponseHeaders() {
}
void AtomURLRequest::ResponseHttpVersion() {
scoped_refptr<net::HttpResponseHeaders> AtomURLRequest::GetResponseHeaders() {
return url_request_->response_headers();
}
void AtomURLRequest::StartOnIOThread() {
// Called on content::BrowserThread::IO
url_request_->Start();
}
@ -97,24 +96,109 @@ void AtomURLRequest::set_method(const std::string& method) {
url_request_->set_method(method);
}
void AtomURLRequest::OnResponseStarted(net::URLRequest* request)
{
// post to main thread
void AtomURLRequest::OnResponseStarted(net::URLRequest* request) {
// Called on content::BrowserThread::IO
DCHECK_EQ(request, url_request_.get());
if (url_request_->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_ = url_request_->response_headers();
}
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegeteResponseStarted, this));
base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this));
ReadResponse();
}
void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read)
{
// post to main thread
void AtomURLRequest::ReadResponse() {
// Called 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 (url_request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) {
if (!url_request_->Read(buffer_.get(), kBufferSize, &bytes_read))
bytes_read = -1;
}
OnReadCompleted(url_request_.get(), bytes_read);
}
void AtomURLRequest::InformDelegeteResponseStarted() {
void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) {
// Called on content::BrowserThread::IO
DCHECK_EQ(request, url_request_.get());
do {
if (!url_request_->status().is_success() || bytes_read <= 0)
break;
const auto result = CopyAndPostBuffer(bytes_read);
if (!result) {
// Failed to transfer data to UI thread.
return;
}
} while (url_request_->Read(buffer_.get(), kBufferSize, &bytes_read));
const auto status = url_request_->status();
if (!status.is_io_pending() /* TODO || request_type_ == URLFetcher::HEAD*/ ) {
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this));
}
}
bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) {
// Called on content::BrowserThread::IO.
// data is only a wrapper for the async buffer_.
// Make a deep copy of payload and transfer ownership to the UI thread.
scoped_refptr<net::IOBufferWithSize> buffer_copy(new net::IOBufferWithSize(bytes_read));
memcpy(buffer_copy->data(), buffer_->data(), bytes_read);
return content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomURLRequest::InformDelegateResponseData, this, buffer_copy));
}
void AtomURLRequest::InformDelegateResponseStarted() {
// Called on content::BrowserThread::UI.
if (delegate_) {
delegate_->OnResponseStarted();
}
}
void AtomURLRequest::InformDelegateResponseData(scoped_refptr<net::IOBufferWithSize> data) {
// Called on content::BrowserThread::IO.
// Transfer ownership of the data buffer, data will be released
// by the delegate's OnResponseData.
if (delegate_) {
delegate_->OnResponseData(data);
}
}
void AtomURLRequest::InformDelegateResponseCompleted() {
if (delegate_) {
delegate_->OnResponseCompleted();
}
}
} // namespace atom