15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/ref_counted.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/io_buffer.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/net_errors.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using content::BrowserThread; 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace chromeos { 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace file_system_provider { 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Dicards the callback from CloseFile(). 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EmptyStatusCallback(base::File::Error /* result */) { 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class FileStreamWriter::OperationRunner 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : public base::RefCountedThreadSafe<FileStreamWriter::OperationRunner> { 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public: 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) OperationRunner() : file_handle_(-1) {} 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Opens a file for writing and calls the completion callback. Must be called 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // on UI thread. 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void OpenFileOnUIThread( 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::FileSystemURL& url, 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::AsyncFileUtil::StatusCallback& callback) { 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) util::FileSystemURLParser parser(url); 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!parser.Parse()) { 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::IO, 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(callback, base::File::FILE_ERROR_SECURITY)); 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) file_system_ = parser.file_system()->GetWeakPtr(); 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) abort_callback_ = parser.file_system()->OpenFile( 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) parser.file_path(), 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ProvidedFileSystemInterface::OPEN_FILE_MODE_WRITE, 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind( 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &OperationRunner::OnOpenFileCompletedOnUIThread, this, callback)); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Closes a file. Ignores result, since outlives the caller. Must be called on 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // UI thread. 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void CloseFileOnUIThread() { 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (file_system_.get() && file_handle_ != -1) { 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Closing a file must not be aborted, since we could end up on files 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // which are never closed. 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) file_system_->CloseFile(file_handle_, base::Bind(&EmptyStatusCallback)); 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Requests writing bytes to the file. In case of either success or a failure 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // |callback| is executed. Must be called on UI thread. 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void WriteFileOnUIThread( 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<net::IOBuffer> buffer, 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int64 offset, 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int length, 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::AsyncFileUtil::StatusCallback& callback) { 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // If the file system got unmounted, then abort the writing operation. 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!file_system_.get()) { 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::IO, 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(callback, base::File::FILE_ERROR_ABORT)); 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) abort_callback_ = file_system_->WriteFile( 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) file_handle_, 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer.get(), 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) offset, 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) length, 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind( 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback)); 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Aborts the most recent operation (if exists), and calls the callback. 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void AbortOnUIThread(const storage::AsyncFileUtil::StatusCallback& callback) { 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (abort_callback_.is_null()) { 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // No operation to be cancelled. At most a callback call, which will be 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // discarded. 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::IO, 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(callback, base::File::FILE_OK)); 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const ProvidedFileSystemInterface::AbortCallback abort_callback = 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) abort_callback_; 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) abort_callback_ = ProvidedFileSystemInterface::AbortCallback(); 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) abort_callback.Run(base::Bind( 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &OperationRunner::OnAbortCompletedOnUIThread, this, callback)); 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private: 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) friend class base::RefCountedThreadSafe<OperationRunner>; 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual ~OperationRunner() {} 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Remembers a file handle for further operations and forwards the result to 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the IO thread. 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void OnOpenFileCompletedOnUIThread( 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::AsyncFileUtil::StatusCallback& callback, 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int file_handle, 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::File::Error result) { 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) file_handle_ = file_handle; 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Forwards a response of writing to a file to the IO thread. 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void OnWriteFileCompletedOnUIThread( 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::AsyncFileUtil::StatusCallback& callback, 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::File::Error result) { 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Forwards a response of aborting an operation to the IO thread. 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void OnAbortCompletedOnUIThread( 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const storage::AsyncFileUtil::StatusCallback& callback, 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::File::Error result) { 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::UI); 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::IO, FROM_HERE, base::Bind(callback, result)); 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ProvidedFileSystemInterface::AbortCallback abort_callback_; 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::WeakPtr<ProvidedFileSystemInterface> file_system_; 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int file_handle_; 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(OperationRunner); 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}; 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)FileStreamWriter::FileStreamWriter(const storage::FileSystemURL& url, 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 initial_offset) 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : url_(url), 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) current_offset_(initial_offset), 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_(new OperationRunner), 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_(NOT_INITIALIZED), 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_(this) { 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileStreamWriter::~FileStreamWriter() { 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::PostTask( 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::UI, 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&OperationRunner::CloseFileOnUIThread, runner_)); 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FileStreamWriter::Initialize( 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Closure& pending_closure, 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& error_callback) { 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(NOT_INITIALIZED, state_); 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_ = INITIALIZING; 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::PostTask( 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::UI, 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&OperationRunner::OpenFileOnUIThread, 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_, 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url_, 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&FileStreamWriter::OnOpenFileCompleted, 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pending_closure, 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) error_callback))); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FileStreamWriter::OnOpenFileCompleted( 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::Closure& pending_closure, 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& error_callback, 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::File::Error result) { 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(INITIALIZING, state_); 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // In case of an error, return immediately using the |error_callback| of the 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Write() pending request. 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result != base::File::FILE_OK) { 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_ = FAILED; 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_callback.Run(net::FileErrorToNetError(result)); 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(base::File::FILE_OK, result); 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_ = INITIALIZED; 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Run the task waiting for the initialization to be completed. 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_closure.Run(); 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int FileStreamWriter::Write(net::IOBuffer* buffer, 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buffer_length, 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback) { 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TRACE_EVENT_ASYNC_BEGIN1("file_system_provider", 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "FileStreamWriter::Write", 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this, 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "buffer_length", 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_length); 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switch (state_) { 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case NOT_INITIALIZED: 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Lazily initialize with the first call to Write(). 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Initialize(base::Bind(&FileStreamWriter::WriteAfterInitialized, 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) make_scoped_refptr(buffer), 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_length, 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&FileStreamWriter::OnWriteCompleted, 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback)), 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&FileStreamWriter::OnWriteCompleted, 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback)); 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case INITIALIZING: 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case INITIALIZED: 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WriteAfterInitialized(buffer, 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_length, 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&FileStreamWriter::OnWriteCompleted, 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback)); 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case FAILED: 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED(); 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return net::ERR_IO_PENDING; 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int FileStreamWriter::Cancel(const net::CompletionCallback& callback) { 26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::PostTask( 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserThread::UI, 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FROM_HERE, 26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&OperationRunner::AbortOnUIThread, 26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_, 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&FileStreamWriter::OnAbortCompleted, 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) callback))); 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return net::ERR_IO_PENDING; 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int FileStreamWriter::Flush(const net::CompletionCallback& callback) { 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (state_ != INITIALIZED) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return net::ERR_FAILED; 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return net::OK; 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FileStreamWriter::OnWriteFileCompleted( 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buffer_length, 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback, 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::File::Error result) { 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(INITIALIZED, state_); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (result != base::File::FILE_OK) { 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) state_ = FAILED; 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(net::FileErrorToNetError(result)); 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) current_offset_ += buffer_length; 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(buffer_length); 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FileStreamWriter::OnWriteCompleted(net::CompletionCallback callback, 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int result) { 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(result); 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TRACE_EVENT_ASYNC_END0( 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "file_system_provider", "FileStreamWriter::Write", this); 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void FileStreamWriter::OnAbortCompleted(const net::CompletionCallback& callback, 30703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::File::Error result) { 30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (result != base::File::FILE_OK) 31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) state_ = FAILED; 31203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 31303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) callback.Run(net::FileErrorToNetError(result)); 31403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 31503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void FileStreamWriter::WriteAfterInitialized( 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBuffer> buffer, 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buffer_length, 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback) { 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_CURRENTLY_ON(BrowserThread::IO); 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(INITIALIZED, state_); 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::PostTask( 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserThread::UI, 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 32603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&OperationRunner::WriteFileOnUIThread, 32703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_, 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer, 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) current_offset_, 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buffer_length, 33103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::Bind(&FileStreamWriter::OnWriteFileCompleted, 33203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) buffer_length, 33403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) callback))); 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace file_system_provider 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace chromeos 339