// Copyright (c) 2012 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/appcache/appcache_response.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "content/browser/appcache/appcache_storage.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"

namespace content {

namespace {

// Disk cache entry data indices.
enum {
  kResponseInfoIndex,
  kResponseContentIndex
};

// An IOBuffer that wraps a pickle's data. Ownership of the
// pickle is transfered to the WrappedPickleIOBuffer object.
class WrappedPickleIOBuffer : public net::WrappedIOBuffer {
 public:
  explicit WrappedPickleIOBuffer(const Pickle* pickle) :
      net::WrappedIOBuffer(reinterpret_cast<const char*>(pickle->data())),
      pickle_(pickle) {
    DCHECK(pickle->data());
  }

 private:
  virtual ~WrappedPickleIOBuffer() {}

  scoped_ptr<const Pickle> pickle_;
};

}  // anon namespace


// AppCacheResponseInfo ----------------------------------------------

AppCacheResponseInfo::AppCacheResponseInfo(
    AppCacheStorage* storage, const GURL& manifest_url,
    int64 response_id,  net::HttpResponseInfo* http_info,
    int64 response_data_size)
    : manifest_url_(manifest_url), response_id_(response_id),
      http_response_info_(http_info), response_data_size_(response_data_size),
      storage_(storage) {
  DCHECK(http_info);
  DCHECK(response_id != kAppCacheNoResponseId);
  storage_->working_set()->AddResponseInfo(this);
}

AppCacheResponseInfo::~AppCacheResponseInfo() {
  storage_->working_set()->RemoveResponseInfo(this);
}

// HttpResponseInfoIOBuffer ------------------------------------------

HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer()
    : response_data_size(kUnkownResponseDataSize) {}

HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(net::HttpResponseInfo* info)
    : http_info(info), response_data_size(kUnkownResponseDataSize) {}

HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() {}

// AppCacheResponseIO ----------------------------------------------

AppCacheResponseIO::AppCacheResponseIO(
    int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
    : response_id_(response_id),
      group_id_(group_id),
      disk_cache_(disk_cache),
      entry_(NULL),
      buffer_len_(0),
      weak_factory_(this) {
}

AppCacheResponseIO::~AppCacheResponseIO() {
  if (entry_)
    entry_->Close();
}

void AppCacheResponseIO::ScheduleIOCompletionCallback(int result) {
  base::MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&AppCacheResponseIO::OnIOComplete,
                            weak_factory_.GetWeakPtr(), result));
}

void AppCacheResponseIO::InvokeUserCompletionCallback(int result) {
  // Clear the user callback and buffers prior to invoking the callback
  // so the caller can schedule additional operations in the callback.
  buffer_ = NULL;
  info_buffer_ = NULL;
  net::CompletionCallback cb = callback_;
  callback_.Reset();
  cb.Run(result);
}

void AppCacheResponseIO::ReadRaw(int index, int offset,
                                 net::IOBuffer* buf, int buf_len) {
  DCHECK(entry_);
  int rv = entry_->Read(
      index, offset, buf, buf_len,
      base::Bind(&AppCacheResponseIO::OnRawIOComplete,
                 weak_factory_.GetWeakPtr()));
  if (rv != net::ERR_IO_PENDING)
    ScheduleIOCompletionCallback(rv);
}

void AppCacheResponseIO::WriteRaw(int index, int offset,
                                 net::IOBuffer* buf, int buf_len) {
  DCHECK(entry_);
  int rv = entry_->Write(
      index, offset, buf, buf_len,
      base::Bind(&AppCacheResponseIO::OnRawIOComplete,
                 weak_factory_.GetWeakPtr()));
  if (rv != net::ERR_IO_PENDING)
    ScheduleIOCompletionCallback(rv);
}

void AppCacheResponseIO::OnRawIOComplete(int result) {
  DCHECK_NE(net::ERR_IO_PENDING, result);
  OnIOComplete(result);
}


// AppCacheResponseReader ----------------------------------------------

AppCacheResponseReader::AppCacheResponseReader(
    int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
    : AppCacheResponseIO(response_id, group_id, disk_cache),
      range_offset_(0),
      range_length_(kint32max),
      read_position_(0),
      weak_factory_(this) {
}

AppCacheResponseReader::~AppCacheResponseReader() {
}

void AppCacheResponseReader::ReadInfo(HttpResponseInfoIOBuffer* info_buf,
                                      const net::CompletionCallback& callback) {
  DCHECK(!callback.is_null());
  DCHECK(!IsReadPending());
  DCHECK(info_buf);
  DCHECK(!info_buf->http_info.get());
  DCHECK(!buffer_.get());
  DCHECK(!info_buffer_.get());

  info_buffer_ = info_buf;
  callback_ = callback;  // cleared on completion
  OpenEntryIfNeededAndContinue();
}

void AppCacheResponseReader::ContinueReadInfo() {
  if (!entry_)  {
    ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
    return;
  }

  int size = entry_->GetSize(kResponseInfoIndex);
  if (size <= 0) {
    ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
    return;
  }

  buffer_ = new net::IOBuffer(size);
  ReadRaw(kResponseInfoIndex, 0, buffer_.get(), size);
}

void AppCacheResponseReader::ReadData(net::IOBuffer* buf, int buf_len,
                                      const net::CompletionCallback& callback) {
  DCHECK(!callback.is_null());
  DCHECK(!IsReadPending());
  DCHECK(buf);
  DCHECK(buf_len >= 0);
  DCHECK(!buffer_.get());
  DCHECK(!info_buffer_.get());

  buffer_ = buf;
  buffer_len_ = buf_len;
  callback_ = callback;  // cleared on completion
  OpenEntryIfNeededAndContinue();
}

void AppCacheResponseReader::ContinueReadData() {
  if (!entry_)  {
    ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
    return;
  }

  if (read_position_ + buffer_len_ > range_length_) {
    // TODO(michaeln): What about integer overflows?
    DCHECK(range_length_ >= read_position_);
    buffer_len_ = range_length_ - read_position_;
  }
  ReadRaw(kResponseContentIndex,
          range_offset_ + read_position_,
          buffer_.get(),
          buffer_len_);
}

void AppCacheResponseReader::SetReadRange(int offset, int length) {
  DCHECK(!IsReadPending() && !read_position_);
  range_offset_ = offset;
  range_length_ = length;
}

void AppCacheResponseReader::OnIOComplete(int result) {
  if (result >= 0) {
    if (info_buffer_.get()) {
      // Deserialize the http info structure, ensuring we got headers.
      Pickle pickle(buffer_->data(), result);
      scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
      bool response_truncated = false;
      if (!info->InitFromPickle(pickle, &response_truncated) ||
          !info->headers.get()) {
        InvokeUserCompletionCallback(net::ERR_FAILED);
        return;
      }
      DCHECK(!response_truncated);
      info_buffer_->http_info.reset(info.release());

      // Also return the size of the response body
      DCHECK(entry_);
      info_buffer_->response_data_size =
          entry_->GetSize(kResponseContentIndex);
    } else {
      read_position_ += result;
    }
  }
  InvokeUserCompletionCallback(result);
}

void AppCacheResponseReader::OpenEntryIfNeededAndContinue() {
  int rv;
  AppCacheDiskCacheInterface::Entry** entry_ptr = NULL;
  if (entry_) {
    rv = net::OK;
  } else if (!disk_cache_) {
    rv = net::ERR_FAILED;
  } else {
    entry_ptr = new AppCacheDiskCacheInterface::Entry*;
    open_callback_ =
        base::Bind(&AppCacheResponseReader::OnOpenEntryComplete,
                   weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
    rv = disk_cache_->OpenEntry(response_id_, entry_ptr, open_callback_);
  }

  if (rv != net::ERR_IO_PENDING)
    OnOpenEntryComplete(entry_ptr, rv);
}

void AppCacheResponseReader::OnOpenEntryComplete(
    AppCacheDiskCacheInterface::Entry** entry, int rv) {
  DCHECK(info_buffer_.get() || buffer_.get());

  if (!open_callback_.is_null()) {
    if (rv == net::OK) {
      DCHECK(entry);
      entry_ = *entry;
    }
    open_callback_.Reset();
  }

  if (info_buffer_.get())
    ContinueReadInfo();
  else
    ContinueReadData();
}

// AppCacheResponseWriter ----------------------------------------------

AppCacheResponseWriter::AppCacheResponseWriter(
    int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
    : AppCacheResponseIO(response_id, group_id, disk_cache),
      info_size_(0),
      write_position_(0),
      write_amount_(0),
      creation_phase_(INITIAL_ATTEMPT),
      weak_factory_(this) {
}

AppCacheResponseWriter::~AppCacheResponseWriter() {
}

void AppCacheResponseWriter::WriteInfo(
    HttpResponseInfoIOBuffer* info_buf,
    const net::CompletionCallback& callback) {
  DCHECK(!callback.is_null());
  DCHECK(!IsWritePending());
  DCHECK(info_buf);
  DCHECK(info_buf->http_info.get());
  DCHECK(!buffer_.get());
  DCHECK(!info_buffer_.get());
  DCHECK(info_buf->http_info->headers.get());

  info_buffer_ = info_buf;
  callback_ = callback;  // cleared on completion
  CreateEntryIfNeededAndContinue();
}

void AppCacheResponseWriter::ContinueWriteInfo() {
  if (!entry_) {
    ScheduleIOCompletionCallback(net::ERR_FAILED);
    return;
  }

  const bool kSkipTransientHeaders = true;
  const bool kTruncated = false;
  Pickle* pickle = new Pickle;
  info_buffer_->http_info->Persist(pickle, kSkipTransientHeaders, kTruncated);
  write_amount_ = static_cast<int>(pickle->size());
  buffer_ = new WrappedPickleIOBuffer(pickle);  // takes ownership of pickle
  WriteRaw(kResponseInfoIndex, 0, buffer_.get(), write_amount_);
}

void AppCacheResponseWriter::WriteData(
    net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) {
  DCHECK(!callback.is_null());
  DCHECK(!IsWritePending());
  DCHECK(buf);
  DCHECK(buf_len >= 0);
  DCHECK(!buffer_.get());
  DCHECK(!info_buffer_.get());

  buffer_ = buf;
  write_amount_ = buf_len;
  callback_ = callback;  // cleared on completion
  CreateEntryIfNeededAndContinue();
}

void AppCacheResponseWriter::ContinueWriteData() {
  if (!entry_) {
    ScheduleIOCompletionCallback(net::ERR_FAILED);
    return;
  }
  WriteRaw(
      kResponseContentIndex, write_position_, buffer_.get(), write_amount_);
}

void AppCacheResponseWriter::OnIOComplete(int result) {
  if (result >= 0) {
    DCHECK(write_amount_ == result);
    if (!info_buffer_.get())
      write_position_ += result;
    else
      info_size_ = result;
  }
  InvokeUserCompletionCallback(result);
}

void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
  int rv;
  AppCacheDiskCacheInterface::Entry** entry_ptr = NULL;
  if (entry_) {
    creation_phase_ = NO_ATTEMPT;
    rv = net::OK;
  } else if (!disk_cache_) {
    creation_phase_ = NO_ATTEMPT;
    rv = net::ERR_FAILED;
  } else {
    creation_phase_ = INITIAL_ATTEMPT;
    entry_ptr = new AppCacheDiskCacheInterface::Entry*;
    create_callback_ =
        base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
                   weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
    rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
  }
  if (rv != net::ERR_IO_PENDING)
    OnCreateEntryComplete(entry_ptr, rv);
}

void AppCacheResponseWriter::OnCreateEntryComplete(
    AppCacheDiskCacheInterface::Entry** entry, int rv) {
  DCHECK(info_buffer_.get() || buffer_.get());

  if (creation_phase_ == INITIAL_ATTEMPT) {
    if (rv != net::OK) {
      // We may try to overwrite existing entries.
      creation_phase_ = DOOM_EXISTING;
      rv = disk_cache_->DoomEntry(response_id_, create_callback_);
      if (rv != net::ERR_IO_PENDING)
        OnCreateEntryComplete(NULL, rv);
      return;
    }
  } else if (creation_phase_ == DOOM_EXISTING) {
    creation_phase_ = SECOND_ATTEMPT;
    AppCacheDiskCacheInterface::Entry** entry_ptr =
        new AppCacheDiskCacheInterface::Entry*;
    create_callback_ =
        base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
                   weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
    rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
    if (rv != net::ERR_IO_PENDING)
      OnCreateEntryComplete(entry_ptr, rv);
    return;
  }

  if (!create_callback_.is_null()) {
    if (rv == net::OK)
      entry_ = *entry;

    create_callback_.Reset();
  }

  if (info_buffer_.get())
    ContinueWriteInfo();
  else
    ContinueWriteData();
}

}  // namespace content
