| Index: content/browser/net/url_request_slow_download_job.cc
|
| diff --git a/content/browser/net/url_request_slow_download_job.cc b/content/browser/net/url_request_slow_download_job.cc
|
| index ee4fa1762606fed7eff0368242ce4ffb1e645c3c..d15a50c8c09d12d64e30069362a05a93b37b6240 100644
|
| --- a/content/browser/net/url_request_slow_download_job.cc
|
| +++ b/content/browser/net/url_request_slow_download_job.cc
|
| @@ -83,7 +83,7 @@ void URLRequestSlowDownloadJob::FinishPendingRequests() {
|
|
|
| URLRequestSlowDownloadJob::URLRequestSlowDownloadJob(net::URLRequest* request)
|
| : net::URLRequestJob(request),
|
| - first_download_size_remaining_(kFirstDownloadSize),
|
| + bytes_already_sent_(0),
|
| should_finish_download_(false),
|
| buffer_size_(0),
|
| ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| @@ -96,56 +96,99 @@ void URLRequestSlowDownloadJob::StartAsync() {
|
| NotifyHeadersComplete();
|
| }
|
|
|
| -bool URLRequestSlowDownloadJob::ReadRawData(net::IOBuffer* buf, int buf_size,
|
| - int *bytes_read) {
|
| - if (LowerCaseEqualsASCII(kFinishDownloadUrl,
|
| - request_->url().spec().c_str())) {
|
| - *bytes_read = 0;
|
| - return true;
|
| +// ReadRawData and CheckDoneStatus together implement a state
|
| +// machine. ReadRawData may be called arbitrarily by the network stack.
|
| +// It responds by:
|
| +// * If there are bytes remaining in the first chunk, they are
|
| +// returned.
|
| +// [No bytes remaining in first chunk. ]
|
| +// * If should_finish_download_ is not set, it returns IO_PENDING,
|
| +// and starts calling CheckDoneStatus on a regular timer.
|
| +// [should_finish_download_ set.]
|
| +// * If there are bytes remaining in the second chunk, they are filled.
|
| +// * Otherwise, return *bytes_read = 0 to indicate end of request.
|
| +// CheckDoneStatus is called on a regular basis, in the specific
|
| +// case where we have transmitted all of the first chunk and none of the
|
| +// second. If should_finish_download_ becomes set, it will "complete"
|
| +// the ReadRawData call that spawned off the CheckDoneStatus() repeated call.
|
| +//
|
| +// FillBufferHelper is a helper function that does the actual work of figuring
|
| +// out where in the state machine we are and how we should fill the buffer.
|
| +// It returns an enum indicating the state of the read.
|
| +URLRequestSlowDownloadJob::ReadStatus
|
| +URLRequestSlowDownloadJob::FillBufferHelper(
|
| + net::IOBuffer* buf, int buf_size, int* bytes_written) {
|
| + if (bytes_already_sent_ < kFirstDownloadSize) {
|
| + int bytes_to_write = std::min(kFirstDownloadSize - bytes_already_sent_,
|
| + buf_size);
|
| + for (int i = 0; i < bytes_to_write; ++i) {
|
| + buf->data()[i] = '*';
|
| + }
|
| + *bytes_written = bytes_to_write;
|
| + bytes_already_sent_ += bytes_to_write;
|
| + return BUFFER_FILLED;
|
| }
|
|
|
| - if (first_download_size_remaining_ > 0) {
|
| - int send_size = std::min(first_download_size_remaining_, buf_size);
|
| - for (int i = 0; i < send_size; ++i) {
|
| + if (!should_finish_download_)
|
| + return REQUEST_BLOCKED;
|
| +
|
| + if (bytes_already_sent_ < kFirstDownloadSize + kSecondDownloadSize) {
|
| + int bytes_to_write =
|
| + std::min(kFirstDownloadSize + kSecondDownloadSize - bytes_already_sent_,
|
| + buf_size);
|
| + for (int i = 0; i < bytes_to_write; ++i) {
|
| buf->data()[i] = '*';
|
| }
|
| - *bytes_read = send_size;
|
| - first_download_size_remaining_ -= send_size;
|
| -
|
| - DCHECK(!is_done());
|
| - return true;
|
| + *bytes_written = bytes_to_write;
|
| + bytes_already_sent_ += bytes_to_write;
|
| + return BUFFER_FILLED;
|
| }
|
|
|
| - if (should_finish_download_) {
|
| + return REQUEST_COMPLETE;
|
| +}
|
| +
|
| +bool URLRequestSlowDownloadJob::ReadRawData(net::IOBuffer* buf, int buf_size,
|
| + int* bytes_read) {
|
| + if (LowerCaseEqualsASCII(kFinishDownloadUrl,
|
| + request_->url().spec().c_str())) {
|
| + VLOG(10) << __FUNCTION__ << " called w/ kFinishDownloadUrl.";
|
| *bytes_read = 0;
|
| return true;
|
| }
|
|
|
| - // If we make it here, the first chunk has been sent and we need to wait
|
| - // until a request is made for kFinishDownloadUrl.
|
| - buffer_ = buf;
|
| - buffer_size_ = buf_size;
|
| - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
| - MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
|
| - weak_factory_.GetWeakPtr()),
|
| - 100);
|
| -
|
| - // Return false to signal there is pending data.
|
| - return false;
|
| + VLOG(10) << __FUNCTION__ << " called at position "
|
| + << bytes_already_sent_ << " in the stream.";
|
| + ReadStatus status = FillBufferHelper(buf, buf_size, bytes_read);
|
| + switch (status) {
|
| + case BUFFER_FILLED:
|
| + return true;
|
| + case REQUEST_BLOCKED:
|
| + buffer_ = buf;
|
| + buffer_size_ = buf_size;
|
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
| + MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + base::Bind(&URLRequestSlowDownloadJob::CheckDoneStatus,
|
| + weak_factory_.GetWeakPtr()),
|
| + 100);
|
| + return false;
|
| + case REQUEST_COMPLETE:
|
| + *bytes_read = 0;
|
| + return true;
|
| + }
|
| + NOTREACHED();
|
| + return true;
|
| }
|
|
|
| void URLRequestSlowDownloadJob::CheckDoneStatus() {
|
| if (should_finish_download_) {
|
| + VLOG(10) << __FUNCTION__ << " called w/ should_finish_download_ set.";
|
| DCHECK(NULL != buffer_);
|
| - // Send the rest of the data.
|
| - DCHECK_GT(buffer_size_, kSecondDownloadSize);
|
| - for (int i = 0; i < kSecondDownloadSize; ++i) {
|
| - buffer_->data()[i] = '*';
|
| - }
|
| + int bytes_written = 0;
|
| + ReadStatus status = FillBufferHelper(buffer_, buffer_size_, &bytes_written);
|
| + DCHECK_EQ(BUFFER_FILLED, status);
|
| SetStatus(net::URLRequestStatus());
|
| - NotifyReadComplete(kSecondDownloadSize); // Deletes this.
|
| + NotifyReadComplete(bytes_written);
|
| } else {
|
| MessageLoop::current()->PostDelayedTask(
|
| FROM_HERE,
|
|
|