OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/chromeos/drive/webkit_file_stream_writer_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback_helpers.h" | |
9 #include "chrome/browser/chromeos/drive/file_system_util.h" | |
10 #include "chrome/browser/chromeos/drive/fileapi_worker.h" | |
11 #include "content/public/browser/browser_thread.h" | |
12 #include "google_apis/drive/task_util.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "webkit/browser/fileapi/file_stream_writer.h" | |
16 | |
17 using content::BrowserThread; | |
18 | |
19 namespace drive { | |
20 namespace internal { | |
21 namespace { | |
22 | |
23 // Creates a writable snapshot file of the |drive_path|. | |
24 void CreateWritableSnapshotFile( | |
25 const WebkitFileStreamWriterImpl::FileSystemGetter& file_system_getter, | |
26 const base::FilePath& drive_path, | |
27 const fileapi_internal::CreateWritableSnapshotFileCallback& callback) { | |
28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
29 | |
30 BrowserThread::PostTask( | |
31 BrowserThread::UI, | |
32 FROM_HERE, | |
33 base::Bind( | |
34 &fileapi_internal::RunFileSystemCallback, | |
35 file_system_getter, | |
36 base::Bind(&fileapi_internal::CreateWritableSnapshotFile, | |
37 drive_path, google_apis::CreateRelayCallback(callback)), | |
38 google_apis::CreateRelayCallback(base::Bind( | |
39 callback, base::File::FILE_ERROR_FAILED, base::FilePath(), | |
40 base::Closure())))); | |
41 } | |
42 | |
43 } // namespace | |
44 | |
45 WebkitFileStreamWriterImpl::WebkitFileStreamWriterImpl( | |
46 const FileSystemGetter& file_system_getter, | |
47 base::TaskRunner* file_task_runner, | |
48 const base::FilePath& file_path, | |
49 int64 offset) | |
50 : file_system_getter_(file_system_getter), | |
51 file_task_runner_(file_task_runner), | |
52 file_path_(file_path), | |
53 offset_(offset), | |
54 weak_ptr_factory_(this) { | |
55 } | |
56 | |
57 WebkitFileStreamWriterImpl::~WebkitFileStreamWriterImpl() { | |
58 if (local_file_writer_) { | |
59 // If the file is opened, close it at destructor. | |
60 // It is necessary to close the local file in advance. | |
61 local_file_writer_.reset(); | |
62 DCHECK(!close_callback_on_ui_thread_.is_null()); | |
63 BrowserThread::PostTask(BrowserThread::UI, | |
64 FROM_HERE, | |
65 close_callback_on_ui_thread_); | |
66 } | |
67 } | |
68 | |
69 int WebkitFileStreamWriterImpl::Write(net::IOBuffer* buf, | |
70 int buf_len, | |
71 const net::CompletionCallback& callback) { | |
72 DCHECK(pending_write_callback_.is_null()); | |
73 DCHECK(pending_cancel_callback_.is_null()); | |
74 DCHECK(!callback.is_null()); | |
75 | |
76 // If the local file is already available, just delegate to it. | |
77 if (local_file_writer_) | |
78 return local_file_writer_->Write(buf, buf_len, callback); | |
79 | |
80 // The local file is not yet ready. Create the writable snapshot. | |
81 if (file_path_.empty()) | |
82 return net::ERR_FILE_NOT_FOUND; | |
83 | |
84 pending_write_callback_ = callback; | |
85 CreateWritableSnapshotFile( | |
86 file_system_getter_, file_path_, | |
87 base::Bind( | |
88 &WebkitFileStreamWriterImpl::WriteAfterCreateWritableSnapshotFile, | |
89 weak_ptr_factory_.GetWeakPtr(), make_scoped_refptr(buf), buf_len)); | |
90 return net::ERR_IO_PENDING; | |
91 } | |
92 | |
93 int WebkitFileStreamWriterImpl::Cancel( | |
94 const net::CompletionCallback& callback) { | |
95 DCHECK(pending_cancel_callback_.is_null()); | |
96 DCHECK(!callback.is_null()); | |
97 | |
98 // If LocalFileWriter is already created, just delegate the cancel to it. | |
99 if (local_file_writer_) | |
100 return local_file_writer_->Cancel(callback); | |
101 | |
102 // If file open operation is in-flight, wait for its completion and cancel | |
103 // further write operation in WriteAfterCreateWritableSnapshotFile. | |
104 if (!pending_write_callback_.is_null()) { | |
105 // Dismiss pending write callback immediately. | |
106 pending_write_callback_.Reset(); | |
107 pending_cancel_callback_ = callback; | |
108 return net::ERR_IO_PENDING; | |
109 } | |
110 | |
111 // Write() is not called yet. | |
112 return net::ERR_UNEXPECTED; | |
113 } | |
114 | |
115 int WebkitFileStreamWriterImpl::Flush(const net::CompletionCallback& callback) { | |
116 DCHECK(pending_cancel_callback_.is_null()); | |
117 DCHECK(!callback.is_null()); | |
118 | |
119 // If LocalFileWriter is already created, just delegate to it. | |
120 if (local_file_writer_) | |
121 return local_file_writer_->Flush(callback); | |
122 | |
123 // There shouldn't be in-flight Write operation. | |
124 DCHECK(pending_write_callback_.is_null()); | |
125 | |
126 // Here is the case Flush() is called before any Write() invocation. | |
127 // Do nothing. | |
128 // Synchronization to the remote server is not done until the file is closed. | |
129 return net::OK; | |
130 } | |
131 | |
132 void WebkitFileStreamWriterImpl::WriteAfterCreateWritableSnapshotFile( | |
133 net::IOBuffer* buf, | |
134 int buf_len, | |
135 base::File::Error open_result, | |
136 const base::FilePath& local_path, | |
137 const base::Closure& close_callback_on_ui_thread) { | |
138 DCHECK(!local_file_writer_); | |
139 | |
140 if (!pending_cancel_callback_.is_null()) { | |
141 DCHECK(pending_write_callback_.is_null()); | |
142 // Cancel() is called during the creation of the snapshot file. | |
143 // Don't write to the file. | |
144 if (open_result == base::File::FILE_OK) { | |
145 // Here the file is internally created. To revert the operation, close | |
146 // the file. | |
147 DCHECK(!close_callback_on_ui_thread.is_null()); | |
148 BrowserThread::PostTask(BrowserThread::UI, | |
149 FROM_HERE, | |
150 close_callback_on_ui_thread); | |
151 } | |
152 | |
153 base::ResetAndReturn(&pending_cancel_callback_).Run(net::OK); | |
154 return; | |
155 } | |
156 | |
157 DCHECK(!pending_write_callback_.is_null()); | |
158 | |
159 const net::CompletionCallback callback = | |
160 base::ResetAndReturn(&pending_write_callback_); | |
161 if (open_result != base::File::FILE_OK) { | |
162 DCHECK(close_callback_on_ui_thread.is_null()); | |
163 callback.Run( | |
164 net::FileErrorToNetError(open_result)); | |
165 return; | |
166 } | |
167 | |
168 // Keep |close_callback| to close the file when the stream is destructed. | |
169 DCHECK(!close_callback_on_ui_thread.is_null()); | |
170 close_callback_on_ui_thread_ = close_callback_on_ui_thread; | |
171 local_file_writer_.reset(fileapi::FileStreamWriter::CreateForLocalFile( | |
172 file_task_runner_.get(), local_path, offset_)); | |
173 int result = local_file_writer_->Write(buf, buf_len, callback); | |
174 if (result != net::ERR_IO_PENDING) | |
175 callback.Run(result); | |
176 } | |
177 | |
178 } // namespace internal | |
179 } // namespace drive | |
OLD | NEW |