// 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 "webkit/blob/local_file_stream_reader.h"

#include "base/file_util.h"
#include "base/file_util_proxy.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/platform_file.h"
#include "base/task_runner.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"

namespace webkit_blob {

namespace {

const int kOpenFlagsForRead = base::PLATFORM_FILE_OPEN |
                              base::PLATFORM_FILE_READ |
                              base::PLATFORM_FILE_ASYNC;

// Verify if the underlying file has not been modified.
bool VerifySnapshotTime(const base::Time& expected_modification_time,
                        const base::PlatformFileInfo& file_info) {
  return expected_modification_time.is_null() ||
         expected_modification_time.ToTimeT() ==
             file_info.last_modified.ToTimeT();
}

}  // namespace

LocalFileStreamReader::LocalFileStreamReader(
    base::TaskRunner* task_runner,
    const FilePath& file_path,
    int64 initial_offset,
    const base::Time& expected_modification_time)
    : task_runner_(task_runner),
      file_path_(file_path),
      initial_offset_(initial_offset),
      expected_modification_time_(expected_modification_time),
      has_pending_open_(false),
      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}

LocalFileStreamReader::~LocalFileStreamReader() {
}

int LocalFileStreamReader::Read(net::IOBuffer* buf, int buf_len,
                          const net::CompletionCallback& callback) {
  DCHECK(!has_pending_open_);
  if (stream_impl_.get())
    return stream_impl_->Read(buf, buf_len, callback);
  return Open(base::Bind(&LocalFileStreamReader::DidOpenForRead,
                         weak_factory_.GetWeakPtr(),
                         make_scoped_refptr(buf), buf_len, callback));
}

int LocalFileStreamReader::GetLength(
    const net::Int64CompletionCallback& callback) {
  const bool posted = base::FileUtilProxy::GetFileInfo(
      task_runner_, file_path_,
      base::Bind(&LocalFileStreamReader::DidGetFileInfoForGetLength,
                 weak_factory_.GetWeakPtr(), callback));
  DCHECK(posted);
  return net::ERR_IO_PENDING;
}

int LocalFileStreamReader::Open(const net::CompletionCallback& callback) {
  DCHECK(!has_pending_open_);
  DCHECK(!stream_impl_.get());
  has_pending_open_ = true;

  // Call GetLength first to make it perform last-modified-time verification,
  // and then call DidVerifyForOpen for do the rest.
  return GetLength(base::Bind(&LocalFileStreamReader::DidVerifyForOpen,
                              weak_factory_.GetWeakPtr(), callback));
}

void LocalFileStreamReader::DidVerifyForOpen(
    const net::CompletionCallback& callback,
    int64 get_length_result) {
  if (get_length_result < 0) {
    callback.Run(static_cast<int>(get_length_result));
    return;
  }

  stream_impl_.reset(new net::FileStream(NULL));
  const int result = stream_impl_->Open(
      file_path_, kOpenFlagsForRead,
      base::Bind(&LocalFileStreamReader::DidOpenFileStream,
                 weak_factory_.GetWeakPtr(),
                 callback));
  if (result != net::ERR_IO_PENDING)
    callback.Run(result);
}

void LocalFileStreamReader::DidOpenFileStream(
    const net::CompletionCallback& callback,
    int result) {
  if (result != net::OK) {
    callback.Run(result);
    return;
  }
  result = stream_impl_->Seek(
      net::FROM_BEGIN, initial_offset_,
      base::Bind(&LocalFileStreamReader::DidSeekFileStream,
                 weak_factory_.GetWeakPtr(),
                 callback));
  if (result != net::ERR_IO_PENDING) {
    callback.Run(result);
  }
}

void LocalFileStreamReader::DidSeekFileStream(
    const net::CompletionCallback& callback,
    int64 seek_result) {
  if (seek_result < 0) {
    callback.Run(static_cast<int>(seek_result));
    return;
  }
  if (seek_result != initial_offset_) {
    callback.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
    return;
  }
  callback.Run(net::OK);
}

void LocalFileStreamReader::DidOpenForRead(
    net::IOBuffer* buf,
    int buf_len,
    const net::CompletionCallback& callback,
    int open_result) {
  DCHECK(has_pending_open_);
  has_pending_open_ = false;
  if (open_result != net::OK) {
    stream_impl_.reset();
    callback.Run(open_result);
    return;
  }
  DCHECK(stream_impl_.get());
  const int read_result = stream_impl_->Read(buf, buf_len, callback);
  if (read_result != net::ERR_IO_PENDING)
    callback.Run(read_result);
}

void LocalFileStreamReader::DidGetFileInfoForGetLength(
    const net::Int64CompletionCallback& callback,
    base::PlatformFileError error,
    const base::PlatformFileInfo& file_info) {
  if (file_info.is_directory) {
    callback.Run(net::ERR_FILE_NOT_FOUND);
    return;
  }
  if (error != base::PLATFORM_FILE_OK) {
    callback.Run(net::PlatformFileErrorToNetError(error));
    return;
  }
  if (!VerifySnapshotTime(expected_modification_time_, file_info)) {
    callback.Run(net::ERR_UPLOAD_FILE_CHANGED);
    return;
  }
  callback.Run(file_info.size);
}

}  // namespace webkit_blob
