webkit_file_stream_reader_impl.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/drive/fileapi/webkit_file_stream_reader_impl.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/logging.h"
11#include "chrome/browser/chromeos/drive/drive.pb.h"
12#include "chrome/browser/chromeos/drive/drive_file_stream_reader.h"
13#include "content/public/browser/browser_thread.h"
14#include "net/base/io_buffer.h"
15#include "net/base/net_errors.h"
16#include "net/http/http_byte_range.h"
17
18using content::BrowserThread;
19
20namespace drive {
21namespace internal {
22
23WebkitFileStreamReaderImpl::WebkitFileStreamReaderImpl(
24    const DriveFileStreamReader::FileSystemGetter& file_system_getter,
25    base::SequencedTaskRunner* file_task_runner,
26    const base::FilePath& drive_file_path,
27    int64 offset,
28    const base::Time& expected_modification_time)
29    : stream_reader_(
30          new DriveFileStreamReader(file_system_getter, file_task_runner)),
31      drive_file_path_(drive_file_path),
32      offset_(offset),
33      expected_modification_time_(expected_modification_time),
34      file_size_(-1),
35      weak_ptr_factory_(this) {
36  DCHECK_GE(offset, 0);
37}
38
39WebkitFileStreamReaderImpl::~WebkitFileStreamReaderImpl() {
40}
41
42int WebkitFileStreamReaderImpl::Read(net::IOBuffer* buffer,
43                                     int buffer_length,
44                                     const net::CompletionCallback& callback) {
45  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
46  DCHECK(stream_reader_);
47  DCHECK(buffer);
48  DCHECK(!callback.is_null());
49
50  if (stream_reader_->IsInitialized())
51    return stream_reader_->Read(buffer, buffer_length, callback);
52
53  net::HttpByteRange byte_range;
54  byte_range.set_first_byte_position(offset_);
55  stream_reader_->Initialize(
56      drive_file_path_,
57      byte_range,
58      base::Bind(&WebkitFileStreamReaderImpl::OnStreamReaderInitialized,
59                 weak_ptr_factory_.GetWeakPtr(),
60                 base::Bind(&WebkitFileStreamReaderImpl
61                                ::ReadAfterStreamReaderInitialized,
62                            weak_ptr_factory_.GetWeakPtr(),
63                            make_scoped_refptr(buffer),
64                            buffer_length, callback)));
65  return net::ERR_IO_PENDING;
66}
67
68int64 WebkitFileStreamReaderImpl::GetLength(
69    const net::Int64CompletionCallback& callback) {
70  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
71  DCHECK(stream_reader_);
72  DCHECK(!callback.is_null());
73
74  if (stream_reader_->IsInitialized()) {
75    // Returns file_size regardless of |offset_|.
76    return file_size_;
77  }
78
79  net::HttpByteRange byte_range;
80  byte_range.set_first_byte_position(offset_);
81  stream_reader_->Initialize(
82      drive_file_path_,
83      byte_range,
84      base::Bind(&WebkitFileStreamReaderImpl::OnStreamReaderInitialized,
85                 weak_ptr_factory_.GetWeakPtr(),
86                 base::Bind(&WebkitFileStreamReaderImpl
87                                ::GetLengthAfterStreamReaderInitialized,
88                            weak_ptr_factory_.GetWeakPtr(),
89                            callback)));
90  return net::ERR_IO_PENDING;
91}
92
93void WebkitFileStreamReaderImpl::OnStreamReaderInitialized(
94    const net::CompletionCallback& callback,
95    int error,
96    scoped_ptr<ResourceEntry> entry) {
97  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
98  DCHECK(stream_reader_);
99  DCHECK(!callback.is_null());
100
101  // TODO(hashimoto): Report ERR_UPLOAD_FILE_CHANGED when modification time
102  // doesn't match. crbug.com/346625
103  if (error != net::OK) {
104    // Found an error. Close the |stream_reader_| and notify it to the caller.
105    stream_reader_.reset();
106    callback.Run(error);
107    return;
108  }
109
110  // Remember the size of the file.
111  file_size_ = entry->file_info().size();
112  callback.Run(net::OK);
113}
114
115void WebkitFileStreamReaderImpl::ReadAfterStreamReaderInitialized(
116    scoped_refptr<net::IOBuffer> buffer,
117    int buffer_length,
118    const net::CompletionCallback& callback,
119    int initialization_result) {
120  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
121  DCHECK(!callback.is_null());
122
123  if (initialization_result != net::OK) {
124    callback.Run(initialization_result);
125    return;
126  }
127
128  DCHECK(stream_reader_);
129  int result = stream_reader_->Read(buffer.get(), buffer_length, callback);
130  if (result != net::ERR_IO_PENDING)
131    callback.Run(result);
132}
133
134void WebkitFileStreamReaderImpl::GetLengthAfterStreamReaderInitialized(
135    const net::Int64CompletionCallback& callback,
136    int initialization_result) {
137  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
138  DCHECK(!callback.is_null());
139
140  if (initialization_result != net::OK) {
141    callback.Run(initialization_result);
142    return;
143  }
144
145  DCHECK_GE(file_size_, 0);
146  callback.Run(file_size_);
147}
148
149}  // namespace internal
150}  // namespace drive
151