blob: 0190e1e7b30746bc0d5fdf06374babbc8d8085f6 [file] [log] [blame]
// Copyright 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 "chrome/browser/chromeos/drive/webkit_file_stream_reader_impl.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/drive/drive.pb.h"
#include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_byte_range.h"
using content::BrowserThread;
namespace drive {
namespace internal {
WebkitFileStreamReaderImpl::WebkitFileStreamReaderImpl(
const DriveFileStreamReader::FileSystemGetter& file_system_getter,
base::SequencedTaskRunner* file_task_runner,
const base::FilePath& drive_file_path,
int64 offset,
const base::Time& expected_modification_time)
: stream_reader_(
new DriveFileStreamReader(file_system_getter, file_task_runner)),
drive_file_path_(drive_file_path),
offset_(offset),
expected_modification_time_(expected_modification_time),
file_size_(-1),
weak_ptr_factory_(this) {
DCHECK_GE(offset, 0);
}
WebkitFileStreamReaderImpl::~WebkitFileStreamReaderImpl() {
}
int WebkitFileStreamReaderImpl::Read(net::IOBuffer* buffer,
int buffer_length,
const net::CompletionCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(stream_reader_);
DCHECK(buffer);
DCHECK(!callback.is_null());
if (stream_reader_->IsInitialized())
return stream_reader_->Read(buffer, buffer_length, callback);
net::HttpByteRange byte_range;
byte_range.set_first_byte_position(offset_);
stream_reader_->Initialize(
drive_file_path_,
byte_range,
base::Bind(&WebkitFileStreamReaderImpl::OnStreamReaderInitialized,
weak_ptr_factory_.GetWeakPtr(),
base::Bind(&WebkitFileStreamReaderImpl
::ReadAfterStreamReaderInitialized,
weak_ptr_factory_.GetWeakPtr(),
make_scoped_refptr(buffer),
buffer_length, callback)));
return net::ERR_IO_PENDING;
}
int64 WebkitFileStreamReaderImpl::GetLength(
const net::Int64CompletionCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(stream_reader_);
DCHECK(!callback.is_null());
if (stream_reader_->IsInitialized()) {
// Returns file_size regardless of |offset_|.
return file_size_;
}
net::HttpByteRange byte_range;
byte_range.set_first_byte_position(offset_);
stream_reader_->Initialize(
drive_file_path_,
byte_range,
base::Bind(&WebkitFileStreamReaderImpl::OnStreamReaderInitialized,
weak_ptr_factory_.GetWeakPtr(),
base::Bind(&WebkitFileStreamReaderImpl
::GetLengthAfterStreamReaderInitialized,
weak_ptr_factory_.GetWeakPtr(),
callback)));
return net::ERR_IO_PENDING;
}
void WebkitFileStreamReaderImpl::OnStreamReaderInitialized(
const net::CompletionCallback& callback,
int error,
scoped_ptr<ResourceEntry> entry) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(stream_reader_);
DCHECK(!callback.is_null());
if (error == net::OK) {
DCHECK(entry);
// Check last modification time.
if (!expected_modification_time_.is_null() &&
expected_modification_time_.ToInternalValue() !=
entry->file_info().last_modified()) {
error = net::ERR_UPLOAD_FILE_CHANGED;
}
}
if (error != net::OK) {
// Found an error. Close the |stream_reader_| and notify it to the caller.
stream_reader_.reset();
callback.Run(error);
return;
}
// Remember the size of the file.
file_size_ = entry->file_info().size();
callback.Run(net::OK);
}
void WebkitFileStreamReaderImpl::ReadAfterStreamReaderInitialized(
scoped_refptr<net::IOBuffer> buffer,
int buffer_length,
const net::CompletionCallback& callback,
int initialization_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!callback.is_null());
if (initialization_result != net::OK) {
callback.Run(initialization_result);
return;
}
DCHECK(stream_reader_);
int result = stream_reader_->Read(buffer.get(), buffer_length, callback);
if (result != net::ERR_IO_PENDING)
callback.Run(result);
}
void WebkitFileStreamReaderImpl::GetLengthAfterStreamReaderInitialized(
const net::Int64CompletionCallback& callback,
int initialization_result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!callback.is_null());
if (initialization_result != net::OK) {
callback.Run(initialization_result);
return;
}
DCHECK_GE(file_size_, 0);
callback.Run(file_size_);
}
} // namespace internal
} // namespace drive