blob: 2a609b0dcb22703656422af50cacf0b97086e42c [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"
ergb3d5935f2016-03-29 20:09:3413
14namespace leveldb {
15
16struct LevelDBMojoProxy::OpaqueLock {
leon.han99744852016-05-10 03:48:1317 filesystem::mojom::FilePtr lock_file;
ergb3d5935f2016-03-29 20:09:3418};
19
20struct LevelDBMojoProxy::OpaqueDir {
21 explicit OpaqueDir(
leon.han99744852016-05-10 03:48:1322 mojo::InterfacePtrInfo<filesystem::mojom::Directory> directory_info) {
ergb3d5935f2016-03-29 20:09:3423 directory.Bind(std::move(directory_info));
24 }
25
leon.han99744852016-05-10 03:48:1326 filesystem::mojom::DirectoryPtr directory;
ergb3d5935f2016-03-29 20:09:3427};
28
29LevelDBMojoProxy::LevelDBMojoProxy(
30 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
31 : task_runner_(std::move(task_runner)), outstanding_opaque_dirs_(0) {}
32
33LevelDBMojoProxy::OpaqueDir* LevelDBMojoProxy::RegisterDirectory(
leon.han99744852016-05-10 03:48:1334 filesystem::mojom::DirectoryPtr directory) {
ergb3d5935f2016-03-29 20:09:3435 OpaqueDir* out_dir = nullptr;
36 RunInternal(base::Bind(&LevelDBMojoProxy::RegisterDirectoryImpl, this,
37 base::Passed(directory.PassInterface()),
38 &out_dir));
39
40 return out_dir;
41}
42
43void LevelDBMojoProxy::UnregisterDirectory(OpaqueDir* dir) {
44 RunInternal(base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl,
45 this, dir));
46}
47
48base::File LevelDBMojoProxy::OpenFileHandle(OpaqueDir* dir,
49 const std::string& name,
50 uint32_t open_flags) {
51 base::File file;
52 RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir,
53 name, open_flags, &file));
54 return file;
55}
56
leon.han99744852016-05-10 03:48:1357filesystem::mojom::FileError LevelDBMojoProxy::SyncDirectory(
58 OpaqueDir* dir,
59 const std::string& name) {
60 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3461 RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir,
62 name, &error));
63 return error;
64}
65
66bool LevelDBMojoProxy::FileExists(OpaqueDir* dir, const std::string& name) {
67 bool exists = false;
68 RunInternal(base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir,
69 name, &exists));
70 return exists;
71}
72
leon.han99744852016-05-10 03:48:1373filesystem::mojom::FileError LevelDBMojoProxy::GetChildren(
ergb3d5935f2016-03-29 20:09:3474 OpaqueDir* dir,
75 const std::string& path,
76 std::vector<std::string>* result) {
leon.han99744852016-05-10 03:48:1377 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3478 RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir,
79 path, result, &error));
80 return error;
81}
82
leon.han99744852016-05-10 03:48:1383filesystem::mojom::FileError LevelDBMojoProxy::Delete(OpaqueDir* dir,
84 const std::string& path,
85 uint32_t delete_flags) {
86 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3487 RunInternal(base::Bind(&LevelDBMojoProxy::DeleteImpl, this, dir, path,
88 delete_flags, &error));
89 return error;
90}
91
leon.han99744852016-05-10 03:48:1392filesystem::mojom::FileError LevelDBMojoProxy::CreateDir(
93 OpaqueDir* dir,
94 const std::string& path) {
95 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:3496 RunInternal(base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path,
97 &error));
98 return error;
99}
100
leon.han99744852016-05-10 03:48:13101filesystem::mojom::FileError LevelDBMojoProxy::GetFileSize(
102 OpaqueDir* dir,
103 const std::string& path,
104 uint64_t* file_size) {
105 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34106 RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir,
107 path, file_size, &error));
108 return error;
109}
110
leon.han99744852016-05-10 03:48:13111filesystem::mojom::FileError LevelDBMojoProxy::RenameFile(
ergb3d5935f2016-03-29 20:09:34112 OpaqueDir* dir,
113 const std::string& old_path,
114 const std::string& new_path) {
leon.han99744852016-05-10 03:48:13115 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34116 RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir,
117 old_path, new_path, &error));
118 return error;
119}
120
leon.han99744852016-05-10 03:48:13121std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*>
ergb3d5935f2016-03-29 20:09:34122LevelDBMojoProxy::LockFile(OpaqueDir* dir, const std::string& path) {
leon.han99744852016-05-10 03:48:13123 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34124 OpaqueLock* out_lock = nullptr;
125 RunInternal(base::Bind(&LevelDBMojoProxy::LockFileImpl, this, dir, path,
126 &error, &out_lock));
127 return std::make_pair(error, out_lock);
128}
129
leon.han99744852016-05-10 03:48:13130filesystem::mojom::FileError LevelDBMojoProxy::UnlockFile(OpaqueLock* lock) {
ergb3d5935f2016-03-29 20:09:34131 // Take ownership of the incoming lock so it gets destroyed whatever happens.
dcheng84c358e2016-04-26 07:05:53132 std::unique_ptr<OpaqueLock> scoped_lock(lock);
leon.han99744852016-05-10 03:48:13133 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
ergb3d5935f2016-03-29 20:09:34134 RunInternal(base::Bind(&LevelDBMojoProxy::UnlockFileImpl, this,
135 base::Passed(&scoped_lock), &error));
136 return error;
137}
138
139LevelDBMojoProxy::~LevelDBMojoProxy() {
140 DCHECK_EQ(0, outstanding_opaque_dirs_);
141}
142
143void LevelDBMojoProxy::RunInternal(const base::Closure& task) {
144 if (task_runner_->BelongsToCurrentThread()) {
145 task.Run();
146 } else {
gab77f88322016-06-02 13:47:03147 base::WaitableEvent done_event(
148 base::WaitableEvent::ResetPolicy::AUTOMATIC,
149 base::WaitableEvent::InitialState::NOT_SIGNALED);
ergb3d5935f2016-03-29 20:09:34150 task_runner_->PostTask(
151 FROM_HERE,
152 base::Bind(&LevelDBMojoProxy::DoOnOtherThread,
153 this,
154 task,
155 base::Unretained(&done_event)));
156 done_event.Wait();
157 }
158}
159
160void LevelDBMojoProxy::DoOnOtherThread(const base::Closure& c,
161 base::WaitableEvent* event) {
162 c.Run();
163 event->Signal();
164}
165
166void LevelDBMojoProxy::RegisterDirectoryImpl(
leon.han99744852016-05-10 03:48:13167 mojo::InterfacePtrInfo<filesystem::mojom::Directory> directory_info,
ergb3d5935f2016-03-29 20:09:34168 OpaqueDir** out_dir) {
169 // Take the Directory pipe and bind it on this thread.
170 *out_dir = new OpaqueDir(std::move(directory_info));
171 outstanding_opaque_dirs_++;
172}
173
174void LevelDBMojoProxy::UnregisterDirectoryImpl(
175 OpaqueDir* dir) {
176 // Only delete the directories on the thread that owns them.
177 delete dir;
178 outstanding_opaque_dirs_--;
179}
180
181void LevelDBMojoProxy::OpenFileHandleImpl(OpaqueDir* dir,
182 std::string name,
183 uint32_t open_flags,
184 base::File* output_file) {
sammcc2148972016-12-07 01:14:06185 base::File file;
leon.han99744852016-05-10 03:48:13186 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
yzshencd0e2062016-11-14 23:19:40187 bool completed =
sammcc2148972016-12-07 01:14:06188 dir->directory->OpenFileHandle(name, open_flags, &error, &file);
ergb3d5935f2016-03-29 20:09:34189 DCHECK(completed);
190
leon.han99744852016-05-10 03:48:13191 if (error != filesystem::mojom::FileError::OK) {
ergb3d5935f2016-03-29 20:09:34192 *output_file = base::File(static_cast<base::File::Error>(error));
193 } else {
sammcc2148972016-12-07 01:14:06194 *output_file = std::move(file);
ergb3d5935f2016-03-29 20:09:34195 }
196}
197
leon.han99744852016-05-10 03:48:13198void LevelDBMojoProxy::SyncDirectoryImpl(
199 OpaqueDir* dir,
200 std::string name,
201 filesystem::mojom::FileError* out_error) {
202 filesystem::mojom::DirectoryPtr target;
ergb3d5935f2016-03-29 20:09:34203 bool completed = dir->directory->OpenDirectory(
leon.han99744852016-05-10 03:48:13204 name, GetProxy(&target),
205 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite, out_error);
ergb3d5935f2016-03-29 20:09:34206 DCHECK(completed);
207
leon.han99744852016-05-10 03:48:13208 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34209 return;
210
211 completed = target->Flush(out_error);
212 DCHECK(completed);
213}
214
215void LevelDBMojoProxy::FileExistsImpl(OpaqueDir* dir,
216 std::string name,
217 bool* exists) {
leon.han99744852016-05-10 03:48:13218 filesystem::mojom::FileError error = filesystem::mojom::FileError::FAILED;
yzshencd0e2062016-11-14 23:19:40219 bool completed = dir->directory->Exists(name, &error, exists);
ergb3d5935f2016-03-29 20:09:34220 DCHECK(completed);
221}
222
leon.han99744852016-05-10 03:48:13223void LevelDBMojoProxy::GetChildrenImpl(
224 OpaqueDir* dir,
225 std::string name,
226 std::vector<std::string>* out_contents,
227 filesystem::mojom::FileError* out_error) {
228 filesystem::mojom::DirectoryPtr target;
229 filesystem::mojom::DirectoryRequest proxy = GetProxy(&target);
ergb3d5935f2016-03-29 20:09:34230 bool completed = dir->directory->OpenDirectory(
leon.han99744852016-05-10 03:48:13231 name, std::move(proxy),
232 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite, out_error);
ergb3d5935f2016-03-29 20:09:34233 DCHECK(completed);
234
leon.han99744852016-05-10 03:48:13235 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34236 return;
237
yzshencd0e2062016-11-14 23:19:40238 base::Optional<std::vector<filesystem::mojom::DirectoryEntryPtr>>
239 directory_contents;
ergb3d5935f2016-03-29 20:09:34240 completed = target->Read(out_error, &directory_contents);
241 DCHECK(completed);
242
yzshencd0e2062016-11-14 23:19:40243 if (directory_contents.has_value()) {
244 for (size_t i = 0; i < directory_contents->size(); ++i)
245 out_contents->push_back(directory_contents.value()[i]->name);
ergb3d5935f2016-03-29 20:09:34246 }
247}
248
249void LevelDBMojoProxy::DeleteImpl(OpaqueDir* dir,
250 std::string name,
251 uint32_t delete_flags,
leon.han99744852016-05-10 03:48:13252 filesystem::mojom::FileError* out_error) {
yzshencd0e2062016-11-14 23:19:40253 bool completed = dir->directory->Delete(name, delete_flags, out_error);
ergb3d5935f2016-03-29 20:09:34254 DCHECK(completed);
255}
256
257void LevelDBMojoProxy::CreateDirImpl(OpaqueDir* dir,
258 std::string name,
leon.han99744852016-05-10 03:48:13259 filesystem::mojom::FileError* out_error) {
ergb3d5935f2016-03-29 20:09:34260 bool completed = dir->directory->OpenDirectory(
261 name, nullptr,
leon.han99744852016-05-10 03:48:13262 filesystem::mojom::kFlagRead | filesystem::mojom::kFlagWrite |
263 filesystem::mojom::kFlagCreate,
ergb3d5935f2016-03-29 20:09:34264 out_error);
265 DCHECK(completed);
266}
267
leon.han99744852016-05-10 03:48:13268void LevelDBMojoProxy::GetFileSizeImpl(
269 OpaqueDir* dir,
270 const std::string& path,
271 uint64_t* file_size,
272 filesystem::mojom::FileError* out_error) {
273 filesystem::mojom::FileInformationPtr info;
ergb3d5935f2016-03-29 20:09:34274 bool completed = dir->directory->StatFile(path, out_error, &info);
275 DCHECK(completed);
276 if (info)
277 *file_size = info->size;
278}
279
280void LevelDBMojoProxy::RenameFileImpl(OpaqueDir* dir,
281 const std::string& old_path,
282 const std::string& new_path,
leon.han99744852016-05-10 03:48:13283 filesystem::mojom::FileError* out_error) {
yzshencd0e2062016-11-14 23:19:40284 bool completed = dir->directory->Rename(old_path, new_path, out_error);
ergb3d5935f2016-03-29 20:09:34285 DCHECK(completed);
286}
287
288void LevelDBMojoProxy::LockFileImpl(OpaqueDir* dir,
289 const std::string& path,
leon.han99744852016-05-10 03:48:13290 filesystem::mojom::FileError* out_error,
ergb3d5935f2016-03-29 20:09:34291 OpaqueLock** out_lock) {
292 // Since a lock is associated with a file descriptor, we need to open and
293 // have a persistent file on the other side of the connection.
leon.han99744852016-05-10 03:48:13294 filesystem::mojom::FilePtr target;
295 filesystem::mojom::FileRequest proxy = GetProxy(&target);
yzshencd0e2062016-11-14 23:19:40296 bool completed = dir->directory->OpenFile(path, std::move(proxy),
297 filesystem::mojom::kFlagOpenAlways |
298 filesystem::mojom::kFlagRead |
299 filesystem::mojom::kFlagWrite,
300 out_error);
ergb3d5935f2016-03-29 20:09:34301 DCHECK(completed);
302
leon.han99744852016-05-10 03:48:13303 if (*out_error != filesystem::mojom::FileError::OK)
ergb3d5935f2016-03-29 20:09:34304 return;
305
306 completed = target->Lock(out_error);
307 DCHECK(completed);
308
leon.han99744852016-05-10 03:48:13309 if (*out_error == filesystem::mojom::FileError::OK) {
ergb3d5935f2016-03-29 20:09:34310 OpaqueLock* l = new OpaqueLock;
311 l->lock_file = std::move(target);
312 *out_lock = l;
313 }
314}
315
dcheng84c358e2016-04-26 07:05:53316void LevelDBMojoProxy::UnlockFileImpl(std::unique_ptr<OpaqueLock> lock,
leon.han99744852016-05-10 03:48:13317 filesystem::mojom::FileError* out_error) {
ergb3d5935f2016-03-29 20:09:34318 lock->lock_file->Unlock(out_error);
319}
320
321} // namespace leveldb