OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reade
r.h" | 5 #include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reade
r.h" |
6 | 6 |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/files/file.h" | 8 #include "base/files/file.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h" | 10 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 : public base::RefCountedThreadSafe<FileStreamReader::OperationRunner> { | 37 : public base::RefCountedThreadSafe<FileStreamReader::OperationRunner> { |
38 public: | 38 public: |
39 OperationRunner() : file_handle_(-1) {} | 39 OperationRunner() : file_handle_(-1) {} |
40 | 40 |
41 // Opens a file for reading and calls the completion callback. Must be called | 41 // Opens a file for reading and calls the completion callback. Must be called |
42 // on UI thread. | 42 // on UI thread. |
43 void OpenFileOnUIThread( | 43 void OpenFileOnUIThread( |
44 const storage::FileSystemURL& url, | 44 const storage::FileSystemURL& url, |
45 const storage::AsyncFileUtil::StatusCallback& callback) { | 45 const storage::AsyncFileUtil::StatusCallback& callback) { |
46 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 46 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 47 DCHECK(abort_callback_.is_null()); |
47 | 48 |
48 util::FileSystemURLParser parser(url); | 49 util::FileSystemURLParser parser(url); |
49 if (!parser.Parse()) { | 50 if (!parser.Parse()) { |
50 BrowserThread::PostTask( | 51 BrowserThread::PostTask( |
51 BrowserThread::IO, | 52 BrowserThread::IO, |
52 FROM_HERE, | 53 FROM_HERE, |
53 base::Bind(callback, base::File::FILE_ERROR_SECURITY)); | 54 base::Bind(callback, base::File::FILE_ERROR_SECURITY)); |
54 return; | 55 return; |
55 } | 56 } |
56 | 57 |
57 file_system_ = parser.file_system()->GetWeakPtr(); | 58 file_system_ = parser.file_system()->GetWeakPtr(); |
58 file_path_ = parser.file_path(); | 59 file_path_ = parser.file_path(); |
59 abort_callback_ = parser.file_system()->OpenFile( | 60 abort_callback_ = parser.file_system()->OpenFile( |
60 file_path_, | 61 file_path_, |
61 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, | 62 ProvidedFileSystemInterface::OPEN_FILE_MODE_READ, |
62 base::Bind( | 63 base::Bind( |
63 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback)); | 64 &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback)); |
64 } | 65 } |
65 | 66 |
66 // Closes a file. Ignores result, since it is called from a constructor. | 67 // Closes a file. Ignores result, since it is called from a constructor. |
67 // Must be called on UI thread. | 68 // Must be called on UI thread. |
68 void CloseFileOnUIThread() { | 69 void CloseFileOnUIThread() { |
69 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 70 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 71 DCHECK(abort_callback_.is_null()); |
| 72 |
70 if (file_system_.get() && file_handle_ != -1) { | 73 if (file_system_.get() && file_handle_ != -1) { |
71 // Closing a file must not be aborted, since we could end up on files | 74 // Closing a file must not be aborted, since we could end up on files |
72 // which are never closed. | 75 // which are never closed. |
73 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback)); | 76 file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback)); |
74 } | 77 } |
75 } | 78 } |
76 | 79 |
77 // Requests reading contents of a file. In case of either success or a failure | 80 // Requests reading contents of a file. In case of either success or a failure |
78 // |callback| is executed. It can be called many times, until |has_more| is | 81 // |callback| is executed. It can be called many times, until |has_more| is |
79 // set to false. This function guarantees that it will succeed only if the | 82 // set to false. This function guarantees that it will succeed only if the |
80 // file has not been changed while reading. Must be called on UI thread. | 83 // file has not been changed while reading. Must be called on UI thread. |
81 void ReadFileOnUIThread( | 84 void ReadFileOnUIThread( |
82 scoped_refptr<net::IOBuffer> buffer, | 85 scoped_refptr<net::IOBuffer> buffer, |
83 int64 offset, | 86 int64 offset, |
84 int length, | 87 int length, |
85 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) { | 88 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) { |
86 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 89 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 90 DCHECK(abort_callback_.is_null()); |
87 | 91 |
88 // If the file system got unmounted, then abort the reading operation. | 92 // If the file system got unmounted, then abort the reading operation. |
89 if (!file_system_.get()) { | 93 if (!file_system_.get()) { |
90 BrowserThread::PostTask( | 94 BrowserThread::PostTask( |
91 BrowserThread::IO, | 95 BrowserThread::IO, |
92 FROM_HERE, | 96 FROM_HERE, |
93 base::Bind( | 97 base::Bind( |
94 callback, 0, false /* has_more */, base::File::FILE_ERROR_ABORT)); | 98 callback, 0, false /* has_more */, base::File::FILE_ERROR_ABORT)); |
95 return; | 99 return; |
96 } | 100 } |
97 | 101 |
98 abort_callback_ = file_system_->ReadFile( | 102 abort_callback_ = file_system_->ReadFile( |
99 file_handle_, | 103 file_handle_, |
100 buffer.get(), | 104 buffer.get(), |
101 offset, | 105 offset, |
102 length, | 106 length, |
103 base::Bind( | 107 base::Bind( |
104 &OperationRunner::OnReadFileCompletedOnUIThread, this, callback)); | 108 &OperationRunner::OnReadFileCompletedOnUIThread, this, callback)); |
105 } | 109 } |
106 | 110 |
107 // Requests metadata of a file. In case of either succes or a failure, | 111 // Requests metadata of a file. In case of either succes or a failure, |
108 // |callback| is executed. Must be called on UI thread. | 112 // |callback| is executed. Must be called on UI thread. |
109 void GetMetadataOnUIThread( | 113 void GetMetadataOnUIThread( |
110 const ProvidedFileSystemInterface::GetMetadataCallback& callback) { | 114 const ProvidedFileSystemInterface::GetMetadataCallback& callback) { |
111 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 115 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 116 DCHECK(abort_callback_.is_null()); |
112 | 117 |
113 // If the file system got unmounted, then abort the get length operation. | 118 // If the file system got unmounted, then abort the get length operation. |
114 if (!file_system_.get()) { | 119 if (!file_system_.get()) { |
115 BrowserThread::PostTask( | 120 BrowserThread::PostTask( |
116 BrowserThread::IO, | 121 BrowserThread::IO, |
117 FROM_HERE, | 122 FROM_HERE, |
118 base::Bind(callback, | 123 base::Bind(callback, |
119 base::Passed(make_scoped_ptr<EntryMetadata>(NULL)), | 124 base::Passed(make_scoped_ptr<EntryMetadata>(NULL)), |
120 base::File::FILE_ERROR_ABORT)); | 125 base::File::FILE_ERROR_ABORT)); |
121 return; | 126 return; |
122 } | 127 } |
123 | 128 |
124 abort_callback_ = file_system_->GetMetadata( | 129 abort_callback_ = file_system_->GetMetadata( |
125 file_path_, | 130 file_path_, |
126 ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT, | 131 ProvidedFileSystemInterface::METADATA_FIELD_DEFAULT, |
127 base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread, | 132 base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread, |
128 this, | 133 this, |
129 callback)); | 134 callback)); |
130 } | 135 } |
131 | 136 |
132 // Aborts the most recent operation (if exists), and calls the callback. | 137 // Aborts the most recent operation (if exists), and calls the callback. |
133 void AbortOnUIThread(const storage::AsyncFileUtil::StatusCallback& callback) { | 138 void AbortOnUIThread() { |
134 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 139 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
135 | 140 if (abort_callback_.is_null()) |
136 if (abort_callback_.is_null()) { | |
137 // No operation to be cancelled. At most a callback call, which will be | |
138 // discarded. | |
139 BrowserThread::PostTask(BrowserThread::IO, | |
140 FROM_HERE, | |
141 base::Bind(callback, base::File::FILE_OK)); | |
142 return; | 141 return; |
143 } | |
144 | 142 |
145 const AbortCallback last_abort_callback = abort_callback_; | 143 const AbortCallback last_abort_callback = abort_callback_; |
146 abort_callback_ = AbortCallback(); | 144 abort_callback_ = AbortCallback(); |
147 last_abort_callback.Run(base::Bind( | 145 last_abort_callback.Run(); |
148 &OperationRunner::OnAbortCompletedOnUIThread, this, callback)); | |
149 } | 146 } |
150 | 147 |
151 private: | 148 private: |
152 friend class base::RefCountedThreadSafe<OperationRunner>; | 149 friend class base::RefCountedThreadSafe<OperationRunner>; |
153 | 150 |
154 virtual ~OperationRunner() {} | 151 virtual ~OperationRunner() {} |
155 | 152 |
156 // Remembers a file handle for further operations and forwards the result to | 153 // Remembers a file handle for further operations and forwards the result to |
157 // the IO thread. | 154 // the IO thread. |
158 void OnOpenFileCompletedOnUIThread( | 155 void OnOpenFileCompletedOnUIThread( |
159 const storage::AsyncFileUtil::StatusCallback& callback, | 156 const storage::AsyncFileUtil::StatusCallback& callback, |
160 int file_handle, | 157 int file_handle, |
161 base::File::Error result) { | 158 base::File::Error result) { |
162 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 159 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 160 abort_callback_ = AbortCallback(); |
163 | 161 |
164 if (result == base::File::FILE_OK) | 162 if (result == base::File::FILE_OK) |
165 file_handle_ = file_handle; | 163 file_handle_ = file_handle; |
166 | 164 |
167 BrowserThread::PostTask( | 165 BrowserThread::PostTask( |
168 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); | 166 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); |
169 } | 167 } |
170 | 168 |
171 // Forwards a metadata to the IO thread. | 169 // Forwards a metadata to the IO thread. |
172 void OnGetMetadataCompletedOnUIThread( | 170 void OnGetMetadataCompletedOnUIThread( |
173 const ProvidedFileSystemInterface::GetMetadataCallback& callback, | 171 const ProvidedFileSystemInterface::GetMetadataCallback& callback, |
174 scoped_ptr<EntryMetadata> metadata, | 172 scoped_ptr<EntryMetadata> metadata, |
175 base::File::Error result) { | 173 base::File::Error result) { |
176 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 174 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 175 abort_callback_ = AbortCallback(); |
| 176 |
177 BrowserThread::PostTask( | 177 BrowserThread::PostTask( |
178 BrowserThread::IO, | 178 BrowserThread::IO, |
179 FROM_HERE, | 179 FROM_HERE, |
180 base::Bind(callback, base::Passed(&metadata), result)); | 180 base::Bind(callback, base::Passed(&metadata), result)); |
181 } | 181 } |
182 | 182 |
183 // Forwards a response of reading from a file to the IO thread. | 183 // Forwards a response of reading from a file to the IO thread. |
184 void OnReadFileCompletedOnUIThread( | 184 void OnReadFileCompletedOnUIThread( |
185 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& | 185 const ProvidedFileSystemInterface::ReadChunkReceivedCallback& |
186 chunk_received_callback, | 186 chunk_received_callback, |
187 int chunk_length, | 187 int chunk_length, |
188 bool has_more, | 188 bool has_more, |
189 base::File::Error result) { | 189 base::File::Error result) { |
190 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 190 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 191 if (!has_more) |
| 192 abort_callback_ = AbortCallback(); |
| 193 |
191 BrowserThread::PostTask( | 194 BrowserThread::PostTask( |
192 BrowserThread::IO, | 195 BrowserThread::IO, |
193 FROM_HERE, | 196 FROM_HERE, |
194 base::Bind(chunk_received_callback, chunk_length, has_more, result)); | 197 base::Bind(chunk_received_callback, chunk_length, has_more, result)); |
195 } | 198 } |
196 | 199 |
197 // Forwards a response of aborting an operation to the IO thread. | |
198 void OnAbortCompletedOnUIThread( | |
199 const storage::AsyncFileUtil::StatusCallback& callback, | |
200 base::File::Error result) { | |
201 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
202 BrowserThread::PostTask( | |
203 BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); | |
204 } | |
205 | |
206 AbortCallback abort_callback_; | 200 AbortCallback abort_callback_; |
207 base::WeakPtr<ProvidedFileSystemInterface> file_system_; | 201 base::WeakPtr<ProvidedFileSystemInterface> file_system_; |
208 base::FilePath file_path_; | 202 base::FilePath file_path_; |
209 int file_handle_; | 203 int file_handle_; |
210 | 204 |
211 DISALLOW_COPY_AND_ASSIGN(OperationRunner); | 205 DISALLOW_COPY_AND_ASSIGN(OperationRunner); |
212 }; | 206 }; |
213 | 207 |
214 FileStreamReader::FileStreamReader(storage::FileSystemContext* context, | 208 FileStreamReader::FileStreamReader(storage::FileSystemContext* context, |
215 const storage::FileSystemURL& url, | 209 const storage::FileSystemURL& url, |
216 int64 initial_offset, | 210 int64 initial_offset, |
217 const base::Time& expected_modification_time) | 211 const base::Time& expected_modification_time) |
218 : url_(url), | 212 : url_(url), |
219 current_offset_(initial_offset), | 213 current_offset_(initial_offset), |
220 current_length_(0), | 214 current_length_(0), |
221 expected_modification_time_(expected_modification_time), | 215 expected_modification_time_(expected_modification_time), |
222 runner_(new OperationRunner), | 216 runner_(new OperationRunner), |
223 state_(NOT_INITIALIZED), | 217 state_(NOT_INITIALIZED), |
224 weak_ptr_factory_(this) { | 218 weak_ptr_factory_(this) { |
225 } | 219 } |
226 | 220 |
227 FileStreamReader::~FileStreamReader() { | 221 FileStreamReader::~FileStreamReader() { |
228 // FileStreamReader doesn't have a Cancel() method like in FileStreamWriter. | 222 // FileStreamReader doesn't have a Cancel() method like in FileStreamWriter. |
229 // Therefore, aborting is done from the destructor. | 223 // Therefore, aborting is done from the destructor. |
230 BrowserThread::PostTask(BrowserThread::UI, | 224 BrowserThread::PostTask( |
231 FROM_HERE, | 225 BrowserThread::UI, FROM_HERE, |
232 base::Bind(&OperationRunner::AbortOnUIThread, | 226 base::Bind(&OperationRunner::AbortOnUIThread, runner_)); |
233 runner_, | |
234 base::Bind(&EmptyStatusCallback))); | |
235 | 227 |
236 BrowserThread::PostTask( | 228 BrowserThread::PostTask( |
237 BrowserThread::UI, | 229 BrowserThread::UI, |
238 FROM_HERE, | 230 FROM_HERE, |
239 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_)); | 231 base::Bind(&OperationRunner::CloseFileOnUIThread, runner_)); |
240 } | 232 } |
241 | 233 |
242 void FileStreamReader::Initialize( | 234 void FileStreamReader::Initialize( |
243 const base::Closure& pending_closure, | 235 const base::Closure& pending_closure, |
244 const net::Int64CompletionCallback& error_callback) { | 236 const net::Int64CompletionCallback& error_callback) { |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 callback.Run(net::ERR_UPLOAD_FILE_CHANGED); | 481 callback.Run(net::ERR_UPLOAD_FILE_CHANGED); |
490 return; | 482 return; |
491 } | 483 } |
492 | 484 |
493 DCHECK_EQ(base::File::FILE_OK, result); | 485 DCHECK_EQ(base::File::FILE_OK, result); |
494 callback.Run(metadata->size); | 486 callback.Run(metadata->size); |
495 } | 487 } |
496 | 488 |
497 } // namespace file_system_provider | 489 } // namespace file_system_provider |
498 } // namespace chromeos | 490 } // namespace chromeos |
OLD | NEW |