Continue resource loading asynchronously to avoid issues during ResourceScheduler stack unwinding.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1230 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-04-17 20:42:39 +00:00
parent 19d9ebd063
commit 62290279d5
1 changed files with 61 additions and 59 deletions

View File

@ -58,68 +58,15 @@ class CefResourceRequestJobCallback : public CefCallback {
dest_size_(0) {}
virtual void Continue() OVERRIDE {
if (CEF_CURRENTLY_ON_IOT()) {
// Currently on IO thread.
// Return early if the callback has already been detached.
if (!job_)
return;
if (type_ == HEADERS_AVAILABLE) {
// Callback for headers available.
if (!job_->has_response_started()) {
// Send header information.
job_->SendHeaders();
}
// This type of callback only ever needs to be called once.
Detach();
} else if (type_ == BYTES_AVAILABLE) {
// Callback for bytes available.
if (job_->has_response_started() &&
job_->GetStatus().is_io_pending()) {
// Read the bytes. They should be available but, if not, wait again.
int bytes_read = 0;
if (job_->ReadRawData(dest_, dest_size_, &bytes_read)) {
if (bytes_read > 0) {
// Clear the IO_PENDING status.
job_->SetStatus(URLRequestStatus());
// Notify about the available bytes.
job_->NotifyReadComplete(bytes_read);
dest_ = NULL;
dest_size_ = 0;
} else {
// All done.
job_->NotifyDone(URLRequestStatus());
Detach();
}
} else if (!job_->GetStatus().is_io_pending()) {
// Failed due to an error.
NOTREACHED() <<
"ReadRawData returned false without setting IO as pending";
job_->NotifyDone(URLRequestStatus());
Detach();
}
}
}
} else {
// Execute this method on the IO thread.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceRequestJobCallback::Continue, this));
}
// Continue asynchronously.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceRequestJobCallback::ContinueOnIOThread, this));
}
virtual void Cancel() OVERRIDE {
if (CEF_CURRENTLY_ON_IOT()) {
// Currently on IO thread.
if (job_)
job_->Kill();
} else {
// Execute this method on the IO thread.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceRequestJobCallback::Cancel, this));
}
// Cancel asynchronously.
CEF_POST_TASK(CEF_IOT,
base::Bind(&CefResourceRequestJobCallback::CancelOnIOThread, this));
}
void Detach() {
@ -134,6 +81,61 @@ class CefResourceRequestJobCallback : public CefCallback {
}
private:
void ContinueOnIOThread() {
CEF_REQUIRE_IOT();
// Return early if the callback has already been detached.
if (!job_)
return;
if (type_ == HEADERS_AVAILABLE) {
// Callback for headers available.
if (!job_->has_response_started()) {
// Send header information.
job_->SendHeaders();
}
// This type of callback only ever needs to be called once.
Detach();
} else if (type_ == BYTES_AVAILABLE) {
// Callback for bytes available.
if (job_->has_response_started() &&
job_->GetStatus().is_io_pending()) {
// Read the bytes. They should be available but, if not, wait again.
int bytes_read = 0;
if (job_->ReadRawData(dest_, dest_size_, &bytes_read)) {
if (bytes_read > 0) {
// Clear the IO_PENDING status.
job_->SetStatus(URLRequestStatus());
// Notify about the available bytes.
job_->NotifyReadComplete(bytes_read);
dest_ = NULL;
dest_size_ = 0;
} else {
// All done.
job_->NotifyDone(URLRequestStatus());
Detach();
}
} else if (!job_->GetStatus().is_io_pending()) {
// Failed due to an error.
NOTREACHED() <<
"ReadRawData returned false without setting IO as pending";
job_->NotifyDone(URLRequestStatus());
Detach();
}
}
}
}
void CancelOnIOThread() {
CEF_REQUIRE_IOT();
if (job_)
job_->Kill();
}
CefResourceRequestJob* job_;
Type type_;