| Index: content/browser/streams/stream_url_request_job.cc
|
| diff --git a/content/browser/streams/stream_url_request_job.cc b/content/browser/streams/stream_url_request_job.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6809b97291c4b080f6757d8c217028eeef87d735
|
| --- /dev/null
|
| +++ b/content/browser/streams/stream_url_request_job.cc
|
| @@ -0,0 +1,198 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/streams/stream_url_request_job.h"
|
| +
|
| +#include "base/string_number_conversions.h"
|
| +#include "content/browser/streams/stream.h"
|
| +#include "net/base/io_buffer.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/http/http_response_headers.h"
|
| +#include "net/http/http_response_info.h"
|
| +#include "net/url_request/url_request.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +const int kHTTPOk = 200;
|
| +const int kHTTPNotAllowed = 403;
|
| +const int kHTTPNotFound = 404;
|
| +const int kHTTPMethodNotAllow = 405;
|
| +const int kHTTPInternalError = 500;
|
| +
|
| +const char kHTTPOKText[] = "OK";
|
| +const char kHTTPNotAllowedText[] = "Not Allowed";
|
| +const char kHTTPNotFoundText[] = "Not Found";
|
| +const char kHTTPMethodNotAllowText[] = "Method Not Allowed";
|
| +const char kHTTPInternalErrorText[] = "Internal Server Error";
|
| +
|
| +} // namespace
|
| +
|
| +StreamURLRequestJob::StreamURLRequestJob(
|
| + net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate,
|
| + scoped_refptr<Stream> stream)
|
| + : net::URLRequestJob(request, network_delegate),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
|
| + stream_(stream),
|
| + headers_set_(false),
|
| + pending_buffer_size_(0) {
|
| + stream_->AddReadObserver(this);
|
| +}
|
| +
|
| +StreamURLRequestJob::~StreamURLRequestJob() {
|
| + stream_->RemoveReadObserver(this);
|
| +}
|
| +
|
| +void StreamURLRequestJob::OnDataAvailable(Stream* stream) {
|
| + // Clear the IO_PENDING status
|
| + SetStatus(net::URLRequestStatus());
|
| + if (pending_buffer_) {
|
| + int bytes_read;
|
| + stream_->ReadRawData(pending_buffer_, pending_buffer_size_, &bytes_read);
|
| +
|
| + pending_buffer_ = NULL;
|
| + pending_buffer_size_ = 0;
|
| +
|
| + NotifyReadComplete(bytes_read);
|
| + }
|
| +}
|
| +
|
| +void StreamURLRequestJob::OnStreamConsumed(Stream* stream) {
|
| + if (pending_buffer_) {
|
| + // Clear the IO_PENDING status
|
| + SetStatus(net::URLRequestStatus());
|
| + pending_buffer_ = NULL;
|
| + pending_buffer_size_ = 0;
|
| + NotifyReadComplete(0);
|
| + }
|
| +}
|
| +
|
| +// net::URLRequestJob methods.
|
| +void StreamURLRequestJob::Start() {
|
| + // Continue asynchronously.
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&StreamURLRequestJob::DidStart, weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void StreamURLRequestJob::Kill() {
|
| + net::URLRequestJob::Kill();
|
| + weak_factory_.InvalidateWeakPtrs();
|
| +}
|
| +
|
| +bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf,
|
| + int buf_size,
|
| + int* bytes_read) {
|
| + if (stream_->ReadRawData(buf, buf_size, bytes_read)) {
|
| + return true;
|
| + } else {
|
| + pending_buffer_ = buf;
|
| + pending_buffer_size_ = buf_size;
|
| + SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const {
|
| + if (!response_info_.get())
|
| + return false;
|
| +
|
| + return response_info_->headers->GetMimeType(mime_type);
|
| +}
|
| +
|
| +void StreamURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
| + if (response_info_.get())
|
| + *info = *response_info_;
|
| +}
|
| +
|
| +int StreamURLRequestJob::GetResponseCode() const {
|
| + if (!response_info_.get())
|
| + return -1;
|
| +
|
| + return response_info_->headers->response_code();
|
| +}
|
| +
|
| +void StreamURLRequestJob::SetExtraRequestHeaders(
|
| + const net::HttpRequestHeaders& headers) {
|
| +}
|
| +
|
| +void StreamURLRequestJob::DidStart() {
|
| + // We only support GET request.
|
| + if (request()->method() != "GET") {
|
| + NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
|
| + return;
|
| + }
|
| +
|
| + if (!stream_) {
|
| + NotifyFailure(net::ERR_FILE_NOT_FOUND);
|
| + return;
|
| + }
|
| +
|
| + HeadersCompleted(kHTTPOk, kHTTPOKText);
|
| +}
|
| +
|
| +void StreamURLRequestJob::NotifyFailure(int error_code) {
|
| + // If we already return the headers on success, we can't change the headers
|
| + // now. Instead, we just error out.
|
| + if (headers_set_) {
|
| + NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
|
| + error_code));
|
| + return;
|
| + }
|
| +
|
| + int status_code = 0;
|
| + std::string status_txt;
|
| + switch (error_code) {
|
| + case net::ERR_ACCESS_DENIED:
|
| + status_code = kHTTPNotAllowed;
|
| + status_txt = kHTTPNotAllowedText;
|
| + break;
|
| + case net::ERR_FILE_NOT_FOUND:
|
| + status_code = kHTTPNotFound;
|
| + status_txt = kHTTPNotFoundText;
|
| + break;
|
| + case net::ERR_METHOD_NOT_SUPPORTED:
|
| + status_code = kHTTPMethodNotAllow;
|
| + status_txt = kHTTPMethodNotAllowText;
|
| + break;
|
| + case net::ERR_FAILED:
|
| + status_code = kHTTPInternalError;
|
| + status_txt = kHTTPInternalErrorText;
|
| + break;
|
| + default:
|
| + DCHECK(false);
|
| + status_code = kHTTPInternalError;
|
| + status_txt = kHTTPInternalErrorText;
|
| + break;
|
| + }
|
| + HeadersCompleted(status_code, status_txt);
|
| +}
|
| +
|
| +void StreamURLRequestJob::HeadersCompleted(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);
|
| + status.append("\0\0", 2);
|
| + net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
|
| +
|
| + if (status_code == kHTTPOk) {
|
| + std::string content_type_header(net::HttpRequestHeaders::kContentType);
|
| + content_type_header.append(": ");
|
| + content_type_header.append("plain/text");
|
| + headers->AddHeader(content_type_header);
|
| + }
|
| +
|
| + response_info_.reset(new net::HttpResponseInfo());
|
| + response_info_->headers = headers;
|
| +
|
| + headers_set_ = true;
|
| +
|
| + NotifyHeadersComplete();
|
| +}
|
| +
|
| +} // namespace content
|
|
|