Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / webkit / browser / blob / local_file_stream_reader.cc
1 // Copyright (c) 2012 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 "webkit/browser/blob/local_file_stream_reader.h"
6
7 #include "base/file_util.h"
8 #include "base/files/file_util_proxy.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/task_runner.h"
12 #include "net/base/file_stream.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15
16 namespace webkit_blob {
17
18 namespace {
19
20 const int kOpenFlagsForRead = base::File::FLAG_OPEN |
21                               base::File::FLAG_READ |
22                               base::File::FLAG_ASYNC;
23
24 }  // namespace
25
26 FileStreamReader* FileStreamReader::CreateForLocalFile(
27     base::TaskRunner* task_runner,
28     const base::FilePath& file_path,
29     int64 initial_offset,
30     const base::Time& expected_modification_time) {
31   return new LocalFileStreamReader(task_runner, file_path, initial_offset,
32                                    expected_modification_time);
33 }
34
35 LocalFileStreamReader::~LocalFileStreamReader() {
36 }
37
38 int LocalFileStreamReader::Read(net::IOBuffer* buf, int buf_len,
39                           const net::CompletionCallback& callback) {
40   DCHECK(!has_pending_open_);
41   if (stream_impl_)
42     return stream_impl_->Read(buf, buf_len, callback);
43   return Open(base::Bind(&LocalFileStreamReader::DidOpenForRead,
44                          weak_factory_.GetWeakPtr(),
45                          make_scoped_refptr(buf), buf_len, callback));
46 }
47
48 int64 LocalFileStreamReader::GetLength(
49     const net::Int64CompletionCallback& callback) {
50   const bool posted = base::FileUtilProxy::GetFileInfo(
51       task_runner_.get(),
52       file_path_,
53       base::Bind(&LocalFileStreamReader::DidGetFileInfoForGetLength,
54                  weak_factory_.GetWeakPtr(),
55                  callback));
56   DCHECK(posted);
57   return net::ERR_IO_PENDING;
58 }
59
60 LocalFileStreamReader::LocalFileStreamReader(
61     base::TaskRunner* task_runner,
62     const base::FilePath& file_path,
63     int64 initial_offset,
64     const base::Time& expected_modification_time)
65     : task_runner_(task_runner),
66       file_path_(file_path),
67       initial_offset_(initial_offset),
68       expected_modification_time_(expected_modification_time),
69       has_pending_open_(false),
70       weak_factory_(this) {}
71
72 int LocalFileStreamReader::Open(const net::CompletionCallback& callback) {
73   DCHECK(!has_pending_open_);
74   DCHECK(!stream_impl_.get());
75   has_pending_open_ = true;
76
77   // Call GetLength first to make it perform last-modified-time verification,
78   // and then call DidVerifyForOpen for do the rest.
79   return GetLength(base::Bind(&LocalFileStreamReader::DidVerifyForOpen,
80                               weak_factory_.GetWeakPtr(), callback));
81 }
82
83 void LocalFileStreamReader::DidVerifyForOpen(
84     const net::CompletionCallback& callback,
85     int64 get_length_result) {
86   if (get_length_result < 0) {
87     callback.Run(static_cast<int>(get_length_result));
88     return;
89   }
90
91   stream_impl_.reset(new net::FileStream(task_runner_));
92   const int result = stream_impl_->Open(
93       file_path_, kOpenFlagsForRead,
94       base::Bind(&LocalFileStreamReader::DidOpenFileStream,
95                  weak_factory_.GetWeakPtr(),
96                  callback));
97   if (result != net::ERR_IO_PENDING)
98     callback.Run(result);
99 }
100
101 void LocalFileStreamReader::DidOpenFileStream(
102     const net::CompletionCallback& callback,
103     int result) {
104   if (result != net::OK) {
105     callback.Run(result);
106     return;
107   }
108   result = stream_impl_->Seek(
109       base::File::FROM_BEGIN, initial_offset_,
110       base::Bind(&LocalFileStreamReader::DidSeekFileStream,
111                  weak_factory_.GetWeakPtr(),
112                  callback));
113   if (result != net::ERR_IO_PENDING) {
114     callback.Run(result);
115   }
116 }
117
118 void LocalFileStreamReader::DidSeekFileStream(
119     const net::CompletionCallback& callback,
120     int64 seek_result) {
121   if (seek_result < 0) {
122     callback.Run(static_cast<int>(seek_result));
123     return;
124   }
125   if (seek_result != initial_offset_) {
126     callback.Run(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
127     return;
128   }
129   callback.Run(net::OK);
130 }
131
132 void LocalFileStreamReader::DidOpenForRead(
133     net::IOBuffer* buf,
134     int buf_len,
135     const net::CompletionCallback& callback,
136     int open_result) {
137   DCHECK(has_pending_open_);
138   has_pending_open_ = false;
139   if (open_result != net::OK) {
140     stream_impl_.reset();
141     callback.Run(open_result);
142     return;
143   }
144   DCHECK(stream_impl_.get());
145   const int read_result = stream_impl_->Read(buf, buf_len, callback);
146   if (read_result != net::ERR_IO_PENDING)
147     callback.Run(read_result);
148 }
149
150 void LocalFileStreamReader::DidGetFileInfoForGetLength(
151     const net::Int64CompletionCallback& callback,
152     base::File::Error error,
153     const base::File::Info& file_info) {
154   if (file_info.is_directory) {
155     callback.Run(net::ERR_FILE_NOT_FOUND);
156     return;
157   }
158   if (error != base::File::FILE_OK) {
159     callback.Run(net::FileErrorToNetError(error));
160     return;
161   }
162   if (!VerifySnapshotTime(expected_modification_time_, file_info)) {
163     callback.Run(net::ERR_UPLOAD_FILE_CHANGED);
164     return;
165   }
166   callback.Run(file_info.size);
167 }
168
169 }  // namespace webkit_blob