blob: 67c0521d65279a7da085b8e679414758a5063031 [file] [log] [blame]
ergb3d5935f2016-03-29 20:09:341// Copyright 2016 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 "components/leveldb/leveldb_mojo_proxy.h"
6
7#include <set>
8
9#include "base/bind.h"
10#include "base/callback.h"
gab4d92485f2016-09-26 21:00:4511#include "base/single_thread_task_runner.h"
ergb3d5935f2016-03-29 20:09:3412#include "mojo/public/cpp/bindings/interface_request.h"
rockot28a287e2016-05-24 02:51:3713#include "mojo/public/cpp/system/platform_handle.h"
ergb3d5935f2016-03-29 20:09:3414
15namespace leveldb {
16
17struct LevelDBMojoProxy::OpaqueLock {
leon.han99744852016-05-10 03:48:1318 filesystem::mojom::FilePtr lock_file;
ergb3d5935f2016-03-29 20:09:3419};
20
21struct LevelDBMojoProxy::OpaqueDir {
22 explicit OpaqueDir(
leon.han99744852016-05-10 03:48:1323 mojo::InterfacePtrInfo<filesystem::mojom::Directory> directory_info) {
ergb3d5935f2016-03-29 20:09:3424 directory.Bind(std::move(directory_info));
25 }
26
leon.han99744852016-05-10 03:48:1327 filesystem::mojom::DirectoryPtr directory;
ergb3d5935f2016-03-29 20:09:3428};
29
30LevelDBMojoProxy::LevelDBMojoProxy(
31 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
32 : task_runner_(std::move(task_runner)), outstanding_opaque_dirs_(0) {}
33
34LevelDBMojoProxy::OpaqueDir* LevelDBMojoProxy::RegisterDirectory(
leon.han99744852016-05-10 03:48:1335 filesystem::mojom::DirectoryPtr directory) {
ergb3d5935f2016-03-29 20:09:3436 OpaqueDir* out_dir = nullptr;
37 RunInternal(base::Bind(&LevelDBMojoProxy::RegisterDirectoryImpl, this,
38 base::Passed(directory.PassInterface()),
39 &out_dir));
40
41 return out_dir;
42}
43
44void LevelDBMojoProxy::UnregisterDirectory(OpaqueDir* dir) {
45 RunInternal(base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl,
46 this, dir));
47}
48
49base::File LevelDBMojoProxy::OpenFileHandle(OpaqueDir* dir,
50 const std::string& name,
51 uint32_t open_flags) {
52 base::File file;
53 RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir,
54 name, open_flags, &file));
55 return file;
56}
57
leon.han99744852016-05-10 03:48:1358filesystem::mojom::FileError LevelDBMojoProxy::SyncDirectory(
59 OpaqueDir* dir,
60 const std::string& name) {
61 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3462 RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir,
63 name, &error));
64 return error;
65}
66
67bool LevelDBMojoProxy::FileExists(OpaqueDir* dir, const std::string& name) {
68 bool exists = false;
69 RunInternal(base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir,
70 name, &exists));
71 return exists;
72}
73
leon.han99744852016-05-10 03:48:1374filesystem::mojom::FileError LevelDBMojoProxy::GetChildren(
ergb3d5935f2016-03-29 20:09:3475 OpaqueDir* dir,
76 const std::string& path,
77 std::vector<std::string>* result) {
leon.han99744852016-05-10 03:48:1378 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3479 RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir,
80 path, result, &error));
81 return error;
82}
83
leon.han99744852016-05-10 03:48:1384filesystem::mojom::FileError LevelDBMojoProxy::Delete(OpaqueDir* dir,
85 const std::string& path,
86 uint32_t delete_flags) {
87 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3488 RunInternal(base::Bind(&LevelDBMojoProxy::DeleteImpl, this, dir, path,
89 delete_flags, &error));
90 return error;
91}
92
leon.han99744852016-05-10 03:48:1393filesystem::mojom::FileError LevelDBMojoProxy::CreateDir(
94 OpaqueDir* dir,
95 const std::string& path) {
96 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3497 RunInternal(base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path,
98 &error));
99 return error;
100}
101
leon.han99744852016-05-10 03:48:13102filesystem::mojom::FileError LevelDBMojoProxy::GetFileSize(
103 OpaqueDir* dir,
104 const std::string& path,
105 uint64_t* file_size) {
106 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34107 RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir,
108 path, file_size, &error));
109 return error;
110}
111
leon.han99744852016-05-10 03:48:13112filesystem::mojom::FileError LevelDBMojoProxy::RenameFile(
ergb3d5935f2016-03-29 20:09:34113 OpaqueDir* dir,
114 const std::string& old_path,
115 const std::string& new_path) {
leon.han99744852016-05-10 03:48:13116 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34117 RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir,
118 old_path, new_path, &error));
119 return error;
120}
121
leon.han99744852016-05-10 03:48:13122std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*>
ergb3d5935f2016-03-29 20:09:34123LevelDBMojoProxy::LockFile(OpaqueDir* dir, const std::string& path) {
leon.han99744852016-05-10 03:48:13124 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34125 OpaqueLock* out_lock = nullptr;
126 RunInternal(base::Bind(&LevelDBMojoProxy::LockFileImpl, this, dir, path,
127 &error, &out_lock));
128 return std::make_pair(error, out_lock);
129}
130
leon.han99744852016-05-10 03:48:13131filesystem::mojom::FileError LevelDBMojoProxy::UnlockFile(OpaqueLock* lock) {
ergb3d5935f2016-03-29 20:09:34132 // Take ownership of the incoming lock so it gets destroyed whatever happens.
dcheng84c358e2016-04-26 07:05:53133 std::unique_ptr<OpaqueLock> scoped_lock(lock);
leon.han99744852016-05-10 03:48:13134 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34135 RunInternal(base::Bind(&LevelDBMojoProxy::UnlockFileImpl, this,
136 base::Passed(&scoped_lock), &error));
137 return error;
138}
139
140LevelDBMojoProxy::~LevelDBMojoProxy() {
141 DCHECK_EQ(0, outstanding_opaque_dirs_);
142}
143
144void LevelDBMojoProxy::RunInternal(const base::Closure& task) {
145 if (task_runner_->BelongsToCurrentThread()) {
146 task.Run();
147 } else {
gab77f88322016-06-02 13:47:03148 base::WaitableEvent done_event(
149 base::WaitableEvent::ResetPolicy::AUTOMATIC,
150 base::WaitableEvent::InitialState::NOT_SIGNALED);
ergb3d5935f2016-03-29 20:09:34151 task_runner_->PostTask(
152 FROM_HERE,
153 base::Bind(&LevelDBMojoProxy::DoOnOtherThread,
154 this,
155 task,
156 base::Unretained(&done_event)));
157 done_event.Wait();
158 }
159}
160
161void LevelDBMojoProxy::DoOnOtherThread(const base::Closure& c,
162 base::WaitableEvent* event) {
163 c.Run();
164 event->Signal();
165}
166
167void LevelDBMojoProxy::RegisterDirectoryImpl(
leon.han99744852016-05-10 03:48:13168 mojo::InterfacePtrInfo<filesystem::mojom::Directory> directory_info,
ergb3d5935f2016-03-29 20:09:34169 OpaqueDir** out_dir) {
170 // Take the Directory pipe and bind it on this thread.
171 *out_dir = new OpaqueDir(std::move(directory_info));
172 outstanding_opaque_dirs_++;
173}
174
175void LevelDBMojoProxy::UnregisterDirectoryImpl(
176 OpaqueDir* dir) {
177 // Only delete the directories on the thread that owns them.
178 delete dir;
179 outstanding_opaque_dirs_--;
180}
181
182void LevelDBMojoProxy::OpenFileHandleImpl(OpaqueDir* dir,
183 std::string name,
184 uint32_t open_flags,
185 base::File* output_file) {
186 mojo::ScopedHandle handle;
leon.han99744852016-05-10 03:48:13187 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
yzshencd0e2062016-11-14 23:19:40188 bool completed =
189 dir->directory->OpenFileHandle(name, open_flags, &error, &handle);
ergb3d5935f2016-03-29 20:09:34190 DCHECK(completed);
191
leon.han99744852016-05-10 03:48:13192 if (error != filesystem::mojom::FileError::OK) {
ergb3d5935f2016-03-29 20:09:34193 *output_file = base::File(static_cast<base::File::Error>(error));
194 } else {
rockot28a287e2016-05-24 02:51:37195 base::PlatformFile platform_file;
196 MojoResult unwrap_result = mojo::UnwrapPlatformFile(std::move(handle),
197 &platform_file);
198 if (unwrap_result == MOJO_RESULT_OK) {
199 *output_file = base::File(platform_file);
ergb3d5935f2016-03-29 20:09:34200 } else {
201 NOTREACHED();
202 *output_file = base::File(base::File::Error::FILE_ERROR_FAILED);
203 }
204 }
205}
206
leon.han99744852016-05-10 03:48:13207void LevelDBMojoProxy::SyncDirectoryImpl(
208 OpaqueDir* dir,
209 std::string name,
210 filesystem::mojom::FileError* out_error) {
211 filesystem::mojom::DirectoryPtr target;
ergb3d5935f2016-03-29 20:09:34212 bool completed = dir->directory->OpenDirectory(
leon.han99744852016-05-10 03:48:13213 name, GetProxy(&target),
214 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite, out_error);
ergb3d5935f2016-03-29 20:09:34215 DCHECK(completed);
216
leon.han99744852016-05-10 03:48:13217 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34218 return;
219
220 completed = target->Flush(out_error);
221 DCHECK(completed);
222}
223
224void LevelDBMojoProxy::FileExistsImpl(OpaqueDir* dir,
225 std::string name,
226 bool* exists) {
leon.han99744852016-05-10 03:48:13227 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
yzshencd0e2062016-11-14 23:19:40228 bool completed = dir->directory->Exists(name, &error, exists);
ergb3d5935f2016-03-29 20:09:34229 DCHECK(completed);
230}
231
leon.han99744852016-05-10 03:48:13232void LevelDBMojoProxy::GetChildrenImpl(
233 OpaqueDir* dir,
234 std::string name,
235 std::vector<std::string>* out_contents,
236 filesystem::mojom::FileError* out_error) {
237 filesystem::mojom::DirectoryPtr target;
238 filesystem::mojom::DirectoryRequest proxy = GetProxy(&target);
ergb3d5935f2016-03-29 20:09:34239 bool completed = dir->directory->OpenDirectory(
leon.han99744852016-05-10 03:48:13240 name, std::move(proxy),
241 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite, out_error);
ergb3d5935f2016-03-29 20:09:34242 DCHECK(completed);
243
leon.han99744852016-05-10 03:48:13244 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34245 return;
246
yzshencd0e2062016-11-14 23:19:40247 base::Optional<std::vector<filesystem::mojom::DirectoryEntryPtr>>
248 directory_contents;
ergb3d5935f2016-03-29 20:09:34249 completed = target->Read(out_error, &directory_contents);
250 DCHECK(completed);
251
yzshencd0e2062016-11-14 23:19:40252 if (directory_contents.has_value()) {
253 for (size_t i = 0; i < directory_contents->size(); ++i)
254 out_contents->push_back(directory_contents.value()[i]->name);
ergb3d5935f2016-03-29 20:09:34255 }
256}
257
258void LevelDBMojoProxy::DeleteImpl(OpaqueDir* dir,
259 std::string name,
260 uint32_t delete_flags,
leon.han99744852016-05-10 03:48:13261 filesystem::mojom::FileError* out_error) {
yzshencd0e2062016-11-14 23:19:40262 bool completed = dir->directory->Delete(name, delete_flags, out_error);
ergb3d5935f2016-03-29 20:09:34263 DCHECK(completed);
264}
265
266void LevelDBMojoProxy::CreateDirImpl(OpaqueDir* dir,
267 std::string name,
leon.han99744852016-05-10 03:48:13268 filesystem::mojom::FileError* out_error) {
ergb3d5935f2016-03-29 20:09:34269 bool completed = dir->directory->OpenDirectory(
270 name, nullptr,
leon.han99744852016-05-10 03:48:13271 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite |
272 filesystem::mojom::kFlagCreate,
ergb3d5935f2016-03-29 20:09:34273 out_error);
274 DCHECK(completed);
275}
276
leon.han99744852016-05-10 03:48:13277void LevelDBMojoProxy::GetFileSizeImpl(
278 OpaqueDir* dir,
279 const std::string& path,
280 uint64_t* file_size,
281 filesystem::mojom::FileError* out_error) {
282 filesystem::mojom::FileInformationPtr info;
ergb3d5935f2016-03-29 20:09:34283 bool completed = dir->directory->StatFile(path, out_error, &info);
284 DCHECK(completed);
285 if (info)
286 *file_size = info->size;
287}
288
289void LevelDBMojoProxy::RenameFileImpl(OpaqueDir* dir,
290 const std::string& old_path,
291 const std::string& new_path,
leon.han99744852016-05-10 03:48:13292 filesystem::mojom::FileError* out_error) {
yzshencd0e2062016-11-14 23:19:40293 bool completed = dir->directory->Rename(old_path, new_path, out_error);
ergb3d5935f2016-03-29 20:09:34294 DCHECK(completed);
295}
296
297void LevelDBMojoProxy::LockFileImpl(OpaqueDir* dir,
298 const std::string& path,
leon.han99744852016-05-10 03:48:13299 filesystem::mojom::FileError* out_error,
ergb3d5935f2016-03-29 20:09:34300 OpaqueLock** out_lock) {
301 // Since a lock is associated with a file descriptor, we need to open and
302 // have a persistent file on the other side of the connection.
leon.han99744852016-05-10 03:48:13303 filesystem::mojom::FilePtr target;
304 filesystem::mojom::FileRequest proxy = GetProxy(&target);
yzshencd0e2062016-11-14 23:19:40305 bool completed = dir->directory->OpenFile(path, std::move(proxy),
306 filesystem::mojom::kFlagOpenAlways |
307 filesystem::mojom::kFlagRead |
308 filesystem::mojom::kFlagWrite,
309 out_error);
ergb3d5935f2016-03-29 20:09:34310 DCHECK(completed);
311
leon.han99744852016-05-10 03:48:13312 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34313 return;
314
315 completed = target->Lock(out_error);
316 DCHECK(completed);
317
leon.han99744852016-05-10 03:48:13318 if (*out_error == filesystem::mojom::FileError::OK) {
ergb3d5935f2016-03-29 20:09:34319 OpaqueLock* l = new OpaqueLock;
320 l->lock_file = std::move(target);
321 *out_lock = l;
322 }
323}
324
dcheng84c358e2016-04-26 07:05:53325void LevelDBMojoProxy::UnlockFileImpl(std::unique_ptr<OpaqueLock> lock,
leon.han99744852016-05-10 03:48:13326 filesystem::mojom::FileError* out_error) {
ergb3d5935f2016-03-29 20:09:34327 lock->lock_file->Unlock(out_error);
328}
329
330} // namespace leveldb