| 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 |