146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/services/network/url_loader_impl.h"
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_vector.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/message_loop/message_loop.h"
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "mojo/common/common_type_converters.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/services/network/network_context.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/base/io_buffer.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/base/load_flags.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/upload_data_stream.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/http/http_response_headers.h"
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/url_request/redirect_info.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/url_request/url_request_context.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace mojo {
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace {
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const uint32_t kMaxReadSize = 64 * 1024;
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Generates an URLResponsePtr from the response state of a net::URLRequest.
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLResponsePtr MakeURLResponse(const net::URLRequest* url_request) {
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  URLResponsePtr response(URLResponse::New());
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response->url = String::From(url_request->url());
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const net::HttpResponseHeaders* headers = url_request->response_headers();
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (headers) {
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    response->status_code = headers->response_code();
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    response->status_line = headers->GetStatusLine();
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::vector<String> header_lines;
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void* iter = NULL;
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string name, value;
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value))
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      header_lines.push_back(name + ": " + value);
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!header_lines.empty())
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      response->headers.Swap(&header_lines);
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string mime_type;
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  url_request->GetMimeType(&mime_type);
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response->mime_type = mime_type;
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string charset;
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  url_request->GetCharset(&charset);
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response->charset = charset;
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return response.Pass();
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
54116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkErrorPtr MakeNetworkError(int error_code) {
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  NetworkErrorPtr error = NetworkError::New();
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  error->code = error_code;
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  error->description = net::ErrorToString(error_code);
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return error.Pass();
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Reads the request body upload data from a DataPipe.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class UploadDataPipeElementReader : public net::UploadElementReader {
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UploadDataPipeElementReader(ScopedDataPipeConsumerHandle pipe)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : pipe_(pipe.Pass()), num_bytes_(0) {}
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~UploadDataPipeElementReader() {}
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // UploadElementReader overrides:
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual int Init(const net::CompletionCallback& callback) OVERRIDE {
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    offset_ = 0;
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ReadDataRaw(pipe_.get(), NULL, &num_bytes_, MOJO_READ_DATA_FLAG_QUERY);
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return net::OK;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual uint64 GetContentLength() const OVERRIDE {
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return num_bytes_;
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual uint64 BytesRemaining() const OVERRIDE {
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return num_bytes_ - offset_;
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual bool IsInMemory() const OVERRIDE {
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual int Read(net::IOBuffer* buf,
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   int buf_length,
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   const net::CompletionCallback& callback) OVERRIDE {
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t bytes_read =
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        std::min(static_cast<uint32_t>(BytesRemaining()),
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 static_cast<uint32_t>(buf_length));
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (bytes_read > 0) {
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ReadDataRaw(pipe_.get(), buf->data(), &bytes_read,
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  MOJO_READ_DATA_FLAG_NONE);
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    offset_ += bytes_read;
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return bytes_read;
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private:
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedDataPipeConsumerHandle pipe_;
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t num_bytes_;
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t offset_;
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UploadDataPipeElementReader);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Keeps track of a pending two-phase write on a DataPipeProducerHandle.
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class URLLoaderImpl::PendingWriteToDataPipe :
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    public base::RefCountedThreadSafe<PendingWriteToDataPipe> {
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit PendingWriteToDataPipe(ScopedDataPipeProducerHandle handle)
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : handle_(handle.Pass()),
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        buffer_(NULL) {
11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MojoResult BeginWrite(uint32_t* num_bytes) {
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    MojoResult result = BeginWriteDataRaw(handle_.get(), &buffer_, num_bytes,
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                          MOJO_WRITE_DATA_FLAG_NONE);
12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (*num_bytes > kMaxReadSize)
12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      *num_bytes = kMaxReadSize;
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return result;
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScopedDataPipeProducerHandle Complete(uint32_t num_bytes) {
12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    EndWriteDataRaw(handle_.get(), num_bytes);
12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    buffer_ = NULL;
12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return handle_.Pass();
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  char* buffer() { return static_cast<char*>(buffer_); }
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  friend class base::RefCountedThreadSafe<PendingWriteToDataPipe>;
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ~PendingWriteToDataPipe() {
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (handle_.is_valid())
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      EndWriteDataRaw(handle_.get(), 0);
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScopedDataPipeProducerHandle handle_;
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void* buffer_;
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PendingWriteToDataPipe);
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Takes ownership of a pending two-phase write on a DataPipeProducerHandle,
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// and makes its buffer available as a net::IOBuffer.
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class URLLoaderImpl::DependentIOBuffer : public net::WrappedIOBuffer {
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DependentIOBuffer(PendingWriteToDataPipe* pending_write)
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : net::WrappedIOBuffer(pending_write->buffer()),
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        pending_write_(pending_write) {
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~DependentIOBuffer() {}
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<PendingWriteToDataPipe> pending_write_;
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLLoaderImpl::URLLoaderImpl(NetworkContext* context)
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : context_(context),
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      response_body_buffer_size_(0),
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      auto_follow_redirects_(true),
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      weak_ptr_factory_(this) {
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLLoaderImpl::~URLLoaderImpl() {
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::Start(URLRequestPtr request,
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          const Callback<void(URLResponsePtr)>& callback) {
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (url_request_) {
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SendError(net::ERR_UNEXPECTED, callback);
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!request) {
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SendError(net::ERR_INVALID_ARGUMENT, callback);
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  url_request_ = context_->url_request_context()->CreateRequest(
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      GURL(request->url),
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      net::DEFAULT_PRIORITY,
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      this,
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      NULL);
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  url_request_->set_method(request->method);
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (request->headers) {
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    net::HttpRequestHeaders headers;
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (size_t i = 0; i < request->headers.size(); ++i)
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      headers.AddHeaderFromString(request->headers[i].To<base::StringPiece>());
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    url_request_->SetExtraRequestHeaders(headers);
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (request->body) {
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ScopedVector<net::UploadElementReader> element_readers;
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (size_t i = 0; i < request->body.size(); ++i) {
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      element_readers.push_back(
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          new UploadDataPipeElementReader(request->body[i].Pass()));
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    url_request_->set_upload(make_scoped_ptr(
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new net::UploadDataStream(element_readers.Pass(), 0)));
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (request->bypass_cache)
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE);
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback_ = callback;
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response_body_buffer_size_ = request->response_body_buffer_size;
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  auto_follow_redirects_ = request->auto_follow_redirects;
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  url_request_->Start();
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::FollowRedirect(
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Callback<void(URLResponsePtr)>& callback) {
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!url_request_) {
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SendError(net::ERR_UNEXPECTED, callback);
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (auto_follow_redirects_) {
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DLOG(ERROR) << "Spurious call to FollowRedirect";
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SendError(net::ERR_UNEXPECTED, callback);
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(darin): Verify that it makes sense to call FollowDeferredRedirect.
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  url_request_->FollowDeferredRedirect();
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::QueryStatus(
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Callback<void(URLLoaderStatusPtr)>& callback) {
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  URLLoaderStatusPtr status(URLLoaderStatus::New());
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (url_request_) {
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status->is_loading = url_request_->is_pending();
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!url_request_->status().is_success())
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      status->error = MakeNetworkError(url_request_->status().error());
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    status->is_loading = false;
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(darin): Populate more status fields.
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback.Run(status.Pass());
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request,
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       const net::RedirectInfo& redirect_info,
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                       bool* defer_redirect) {
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(url_request == url_request_.get());
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(url_request->status().is_success());
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (auto_follow_redirects_)
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Send the redirect response to the client, allowing them to inspect it and
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // optionally follow the redirect.
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *defer_redirect = true;
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  URLResponsePtr response = MakeURLResponse(url_request);
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  response->redirect_method = redirect_info.new_method;
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  response->redirect_url = String::From(redirect_info.new_url);
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SendResponse(response.Pass());
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) {
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(url_request == url_request_.get());
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!url_request->status().is_success()) {
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SendError(url_request->status().error(), callback_);
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    callback_ = Callback<void(URLResponsePtr)>();
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(darin): Add support for optional MIME sniffing.
275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DataPipe data_pipe;
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(darin): Honor given buffer size.
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  URLResponsePtr response = MakeURLResponse(url_request);
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response->body = data_pipe.consumer_handle.Pass();
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response_body_stream_ = data_pipe.producer_handle.Pass();
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SendResponse(response.Pass());
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Start reading...
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ReadMore();
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::OnReadCompleted(net::URLRequest* url_request,
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                    int bytes_read) {
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(url_request == url_request_.get());
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (url_request->status().is_success()) {
29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DidRead(static_cast<uint32_t>(bytes_read), false);
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pending_write_ = NULL;  // This closes the data pipe.
29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::SendError(
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int error_code,
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Callback<void(URLResponsePtr)>& callback) {
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  URLResponsePtr response(URLResponse::New());
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (url_request_)
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    response->url = String::From(url_request_->url());
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  response->error = MakeNetworkError(error_code);
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback.Run(response.Pass());
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::SendResponse(URLResponsePtr response) {
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Callback<void(URLResponsePtr)> callback;
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::swap(callback_, callback);
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  callback.Run(response.Pass());
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) {
317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(darin): Handle a bad |result| value.
318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ReadMore();
319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid URLLoaderImpl::WaitToReadMore() {
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  handle_watcher_.Start(response_body_stream_.get(),
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        MOJO_HANDLE_SIGNAL_WRITABLE,
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        MOJO_DEADLINE_INDEFINITE,
325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        base::Bind(&URLLoaderImpl::OnResponseBodyStreamReady,
326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   weak_ptr_factory_.GetWeakPtr()));
32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::ReadMore() {
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!pending_write_.get());
33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pending_write_ = new PendingWriteToDataPipe(response_body_stream_.Pass());
33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  uint32_t num_bytes;
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  MojoResult result = pending_write_->BeginWrite(&num_bytes);
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (result == MOJO_RESULT_SHOULD_WAIT) {
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // The pipe is full. We need to wait for it to have more space.
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    response_body_stream_ = pending_write_->Complete(num_bytes);
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    pending_write_ = NULL;
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    WaitToReadMore();
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (result != MOJO_RESULT_OK) {
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // The response body stream is in a bad state. Bail.
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(darin): How should this be communicated to our client?
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::IOBuffer> buf =
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new DependentIOBuffer(pending_write_.get());
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int bytes_read;
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  url_request_->Read(buf.get(), static_cast<int>(num_bytes), &bytes_read);
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Drop our reference to the buffer.
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  buf = NULL;
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (url_request_->status().is_io_pending()) {
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Wait for OnReadCompleted.
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (url_request_->status().is_success() && bytes_read > 0) {
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DidRead(static_cast<uint32_t>(bytes_read), true);
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pending_write_->Complete(0);
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    pending_write_ = NULL;  // This closes the data pipe.
36646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) {
37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(url_request_->status().is_success());
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  response_body_stream_ = pending_write_->Complete(num_bytes);
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pending_write_ = NULL;
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (completed_synchronously) {
37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&URLLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr()));
37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ReadMore();
38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace mojo
385