Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / local_file_reader.cc
blob5b9b016301ece7f591bc52f367194fbf1e8ba4b9
1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/drive/local_file_reader.h"
7 #include <errno.h>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h"
12 #include "base/location.h"
13 #include "base/platform_file.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/task_runner_util.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
20 namespace drive {
21 namespace util {
23 namespace {
25 // Opens the file at |file_path| and seeks to the |offset| from begin.
26 // Returns the net::Error code. If succeeded, |platform_file| is set to point
27 // the opened file.
28 // This function should run on the blocking pool.
29 int OpenAndSeekOnBlockingPool(const base::FilePath& file_path,
30 int64 offset,
31 base::PlatformFile* platform_file) {
32 DCHECK(platform_file);
33 DCHECK_EQ(base::kInvalidPlatformFileValue, *platform_file);
35 // First of all, open the file.
36 const int open_flags = base::PLATFORM_FILE_OPEN |
37 base::PLATFORM_FILE_READ |
38 base::PLATFORM_FILE_ASYNC;
39 base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
40 base::PlatformFile file =
41 base::CreatePlatformFile(file_path, open_flags, NULL, &error);
42 if (file == base::kInvalidPlatformFileValue) {
43 DCHECK_NE(base::PLATFORM_FILE_OK, error);
44 return net::PlatformFileErrorToNetError(error);
47 // If succeeded, seek to the |offset| from begin.
48 int64 position = base::SeekPlatformFile(
49 file, base::PLATFORM_FILE_FROM_BEGIN, offset);
50 if (position < 0) {
51 // If failed, close the file and return an error.
52 base::ClosePlatformFile(file);
53 return net::ERR_FAILED;
56 *platform_file = file;
57 return net::OK;
60 // Reads the data from the |platform_file| and copies it to the |buffer| at
61 // most |buffer_length| size. Returns the number of copied bytes if succeeded,
62 // or the net::Error code.
63 // This function should run on the blocking pool.
64 int ReadOnBlockingPool(base::PlatformFile platform_file,
65 scoped_refptr<net::IOBuffer> buffer,
66 int buffer_length) {
67 DCHECK_NE(base::kInvalidPlatformFileValue, platform_file);
68 int result = base::ReadPlatformFileCurPosNoBestEffort(
69 platform_file, buffer->data(), buffer_length);
70 return result < 0 ? net::MapSystemError(errno) : result;
73 // Posts a task to close the |platform_file| into |task_runner|.
74 // Or, if |platform_file| is kInvalidPlatformFileValue, does nothing.
75 void PostCloseIfNeeded(base::TaskRunner* task_runner,
76 base::PlatformFile platform_file) {
77 DCHECK(task_runner);
78 if (platform_file != base::kInvalidPlatformFileValue) {
79 task_runner->PostTask(
80 FROM_HERE,
81 base::Bind(
82 base::IgnoreResult(&base::ClosePlatformFile), platform_file));
86 } // namespace
88 class LocalFileReader::ScopedPlatformFile {
89 public:
90 explicit ScopedPlatformFile(base::TaskRunner* task_runner)
91 : task_runner_(task_runner),
92 platform_file_(base::kInvalidPlatformFileValue) {
93 DCHECK(task_runner);
96 ~ScopedPlatformFile() {
97 PostCloseIfNeeded(task_runner_.get(), platform_file_);
100 base::PlatformFile* ptr() { return &platform_file_; }
102 base::PlatformFile release() {
103 base::PlatformFile result = platform_file_;
104 platform_file_ = base::kInvalidPlatformFileValue;
105 return result;
108 private:
109 scoped_refptr<base::TaskRunner> task_runner_;
110 base::PlatformFile platform_file_;
112 DISALLOW_COPY_AND_ASSIGN(ScopedPlatformFile);
115 LocalFileReader::LocalFileReader(
116 base::SequencedTaskRunner* sequenced_task_runner)
117 : sequenced_task_runner_(sequenced_task_runner),
118 platform_file_(base::kInvalidPlatformFileValue),
119 weak_ptr_factory_(this) {
120 DCHECK(sequenced_task_runner_.get());
123 LocalFileReader::~LocalFileReader() {
124 PostCloseIfNeeded(sequenced_task_runner_.get(), platform_file_);
127 void LocalFileReader::Open(const base::FilePath& file_path,
128 int64 offset,
129 const net::CompletionCallback& callback) {
130 DCHECK(!callback.is_null());
131 DCHECK_EQ(base::kInvalidPlatformFileValue, platform_file_);
133 ScopedPlatformFile* platform_file =
134 new ScopedPlatformFile(sequenced_task_runner_.get());
135 base::PostTaskAndReplyWithResult(
136 sequenced_task_runner_.get(),
137 FROM_HERE,
138 base::Bind(
139 &OpenAndSeekOnBlockingPool, file_path, offset, platform_file->ptr()),
140 base::Bind(&LocalFileReader::OpenAfterBlockingPoolTask,
141 weak_ptr_factory_.GetWeakPtr(),
142 callback,
143 base::Owned(platform_file)));
146 void LocalFileReader::Read(net::IOBuffer* in_buffer,
147 int buffer_length,
148 const net::CompletionCallback& callback) {
149 DCHECK(!callback.is_null());
150 DCHECK_NE(base::kInvalidPlatformFileValue, platform_file_);
152 scoped_refptr<net::IOBuffer> buffer(in_buffer);
153 base::PostTaskAndReplyWithResult(
154 sequenced_task_runner_.get(),
155 FROM_HERE,
156 base::Bind(&ReadOnBlockingPool, platform_file_, buffer, buffer_length),
157 callback);
160 void LocalFileReader::OpenAfterBlockingPoolTask(
161 const net::CompletionCallback& callback,
162 ScopedPlatformFile* platform_file,
163 int open_result) {
164 DCHECK(!callback.is_null());
165 DCHECK(platform_file);
166 DCHECK_EQ(base::kInvalidPlatformFileValue, platform_file_);
168 if (open_result == net::OK) {
169 DCHECK_NE(base::kInvalidPlatformFileValue, *platform_file->ptr());
170 platform_file_ = platform_file->release();
173 callback.Run(open_result);
176 } // namespace util
177 } // namespace drive