OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/filesystem/directory_impl.h" | 5 #include "components/filesystem/directory_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
12 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
15 #include "components/filesystem/file_impl.h" | 15 #include "components/filesystem/file_impl.h" |
16 #include "components/filesystem/lock_table.h" | 16 #include "components/filesystem/lock_table.h" |
17 #include "components/filesystem/util.h" | 17 #include "components/filesystem/util.h" |
18 #include "mojo/common/common_type_converters.h" | 18 #include "mojo/common/common_type_converters.h" |
| 19 #include "mojo/public/cpp/bindings/strong_binding.h" |
19 #include "mojo/public/cpp/system/platform_handle.h" | 20 #include "mojo/public/cpp/system/platform_handle.h" |
20 | 21 |
21 namespace filesystem { | 22 namespace filesystem { |
22 | 23 |
23 DirectoryImpl::DirectoryImpl(mojo::InterfaceRequest<mojom::Directory> request, | 24 DirectoryImpl::DirectoryImpl(base::FilePath directory_path, |
24 base::FilePath directory_path, | |
25 scoped_refptr<SharedTempDir> temp_dir, | 25 scoped_refptr<SharedTempDir> temp_dir, |
26 scoped_refptr<LockTable> lock_table) | 26 scoped_refptr<LockTable> lock_table) |
27 : binding_(this, std::move(request)), | 27 : directory_path_(directory_path), |
28 directory_path_(directory_path), | |
29 temp_dir_(std::move(temp_dir)), | 28 temp_dir_(std::move(temp_dir)), |
30 lock_table_(std::move(lock_table)) {} | 29 lock_table_(std::move(lock_table)) {} |
31 | 30 |
32 DirectoryImpl::~DirectoryImpl() {} | 31 DirectoryImpl::~DirectoryImpl() {} |
33 | 32 |
34 void DirectoryImpl::Read(const ReadCallback& callback) { | 33 void DirectoryImpl::Read(const ReadCallback& callback) { |
35 mojo::Array<mojom::DirectoryEntryPtr> entries; | 34 mojo::Array<mojom::DirectoryEntryPtr> entries; |
36 base::FileEnumerator directory_enumerator( | 35 base::FileEnumerator directory_enumerator( |
37 directory_path_, false, | 36 directory_path_, false, |
38 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES); | 37 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES); |
39 for (base::FilePath name = directory_enumerator.Next(); !name.empty(); | 38 for (base::FilePath name = directory_enumerator.Next(); !name.empty(); |
40 name = directory_enumerator.Next()) { | 39 name = directory_enumerator.Next()) { |
41 base::FileEnumerator::FileInfo info = directory_enumerator.GetInfo(); | 40 base::FileEnumerator::FileInfo info = directory_enumerator.GetInfo(); |
42 mojom::DirectoryEntryPtr entry = mojom::DirectoryEntry::New(); | 41 mojom::DirectoryEntryPtr entry = mojom::DirectoryEntry::New(); |
43 entry->type = info.IsDirectory() ? mojom::FsFileType::DIRECTORY | 42 entry->type = info.IsDirectory() ? mojom::FsFileType::DIRECTORY |
44 : mojom::FsFileType::REGULAR_FILE; | 43 : mojom::FsFileType::REGULAR_FILE; |
45 entry->name = info.GetName().AsUTF8Unsafe(); | 44 entry->name = info.GetName().AsUTF8Unsafe(); |
46 entries.push_back(std::move(entry)); | 45 entries.push_back(std::move(entry)); |
47 } | 46 } |
48 | 47 |
49 callback.Run(mojom::FileError::OK, std::move(entries)); | 48 callback.Run(mojom::FileError::OK, std::move(entries)); |
50 } | 49 } |
51 | 50 |
52 // TODO(erg): Consider adding an implementation of Stat()/Touch() to the | 51 // TODO(erg): Consider adding an implementation of Stat()/Touch() to the |
53 // directory, too. Right now, the base::File abstractions do not really deal | 52 // directory, too. Right now, the base::File abstractions do not really deal |
54 // with directories properly, so these are broken for now. | 53 // with directories properly, so these are broken for now. |
55 | 54 |
56 // TODO(vtl): Move the implementation to a thread pool. | 55 // TODO(vtl): Move the implementation to a thread pool. |
57 void DirectoryImpl::OpenFile(const mojo::String& raw_path, | 56 void DirectoryImpl::OpenFile(const mojo::String& raw_path, |
58 mojo::InterfaceRequest<mojom::File> file, | 57 mojom::FileRequest file, |
59 uint32_t open_flags, | 58 uint32_t open_flags, |
60 const OpenFileCallback& callback) { | 59 const OpenFileCallback& callback) { |
61 base::FilePath path; | 60 base::FilePath path; |
62 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); | 61 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); |
63 if (error != mojom::FileError::OK) { | 62 if (error != mojom::FileError::OK) { |
64 callback.Run(error); | 63 callback.Run(error); |
65 return; | 64 return; |
66 } | 65 } |
67 | 66 |
68 if (base::DirectoryExists(path)) { | 67 if (base::DirectoryExists(path)) { |
69 // We must not return directories as files. In the file abstraction, we can | 68 // We must not return directories as files. In the file abstraction, we can |
70 // fetch raw file descriptors over mojo pipes, and passing a file | 69 // fetch raw file descriptors over mojo pipes, and passing a file |
71 // descriptor to a directory is a sandbox escape on Windows. | 70 // descriptor to a directory is a sandbox escape on Windows. |
72 callback.Run(mojom::FileError::NOT_A_FILE); | 71 callback.Run(mojom::FileError::NOT_A_FILE); |
73 return; | 72 return; |
74 } | 73 } |
75 | 74 |
76 base::File base_file(path, open_flags); | 75 base::File base_file(path, open_flags); |
77 if (!base_file.IsValid()) { | 76 if (!base_file.IsValid()) { |
78 callback.Run(GetError(base_file)); | 77 callback.Run(GetError(base_file)); |
79 return; | 78 return; |
80 } | 79 } |
81 | 80 |
82 if (file.is_pending()) { | 81 if (file.is_pending()) { |
83 new FileImpl(std::move(file), path, std::move(base_file), temp_dir_, | 82 mojo::MakeStrongBinding( |
84 lock_table_); | 83 base::MakeUnique<FileImpl>(path, std::move(base_file), temp_dir_, |
| 84 lock_table_), |
| 85 std::move(file)); |
85 } | 86 } |
86 callback.Run(mojom::FileError::OK); | 87 callback.Run(mojom::FileError::OK); |
87 } | 88 } |
88 | 89 |
89 void DirectoryImpl::OpenFileHandle(const mojo::String& raw_path, | 90 void DirectoryImpl::OpenFileHandle(const mojo::String& raw_path, |
90 uint32_t open_flags, | 91 uint32_t open_flags, |
91 const OpenFileHandleCallback& callback) { | 92 const OpenFileHandleCallback& callback) { |
92 mojom::FileError error = mojom::FileError::OK; | 93 mojom::FileError error = mojom::FileError::OK; |
93 mojo::ScopedHandle handle = OpenFileHandleImpl(raw_path, open_flags, &error); | 94 mojo::ScopedHandle handle = OpenFileHandleImpl(raw_path, open_flags, &error); |
94 callback.Run(error, std::move(handle)); | 95 callback.Run(error, std::move(handle)); |
95 } | 96 } |
96 | 97 |
97 void DirectoryImpl::OpenFileHandles( | 98 void DirectoryImpl::OpenFileHandles( |
98 mojo::Array<mojom::FileOpenDetailsPtr> details, | 99 mojo::Array<mojom::FileOpenDetailsPtr> details, |
99 const OpenFileHandlesCallback& callback) { | 100 const OpenFileHandlesCallback& callback) { |
100 mojo::Array<mojom::FileOpenResultPtr> results( | 101 mojo::Array<mojom::FileOpenResultPtr> results( |
101 mojo::Array<mojom::FileOpenResultPtr>::New(details.size())); | 102 mojo::Array<mojom::FileOpenResultPtr>::New(details.size())); |
102 size_t i = 0; | 103 size_t i = 0; |
103 for (const auto& detail : details) { | 104 for (const auto& detail : details) { |
104 mojom::FileOpenResultPtr result(mojom::FileOpenResult::New()); | 105 mojom::FileOpenResultPtr result(mojom::FileOpenResult::New()); |
105 result->path = detail->path; | 106 result->path = detail->path; |
106 result->file_handle = | 107 result->file_handle = |
107 OpenFileHandleImpl(detail->path, detail->open_flags, &result->error); | 108 OpenFileHandleImpl(detail->path, detail->open_flags, &result->error); |
108 results[i++] = std::move(result); | 109 results[i++] = std::move(result); |
109 } | 110 } |
110 callback.Run(std::move(results)); | 111 callback.Run(std::move(results)); |
111 } | 112 } |
112 | 113 |
113 void DirectoryImpl::OpenDirectory( | 114 void DirectoryImpl::OpenDirectory(const mojo::String& raw_path, |
114 const mojo::String& raw_path, | 115 mojom::DirectoryRequest directory, |
115 mojo::InterfaceRequest<mojom::Directory> directory, | 116 uint32_t open_flags, |
116 uint32_t open_flags, | 117 const OpenDirectoryCallback& callback) { |
117 const OpenDirectoryCallback& callback) { | |
118 base::FilePath path; | 118 base::FilePath path; |
119 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); | 119 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); |
120 if (error != mojom::FileError::OK) { | 120 if (error != mojom::FileError::OK) { |
121 callback.Run(error); | 121 callback.Run(error); |
122 return; | 122 return; |
123 } | 123 } |
124 | 124 |
125 if (!base::DirectoryExists(path)) { | 125 if (!base::DirectoryExists(path)) { |
126 if (base::PathExists(path)) { | 126 if (base::PathExists(path)) { |
127 callback.Run(mojom::FileError::NOT_A_DIRECTORY); | 127 callback.Run(mojom::FileError::NOT_A_DIRECTORY); |
128 return; | 128 return; |
129 } | 129 } |
130 | 130 |
131 if (!(open_flags & mojom::kFlagOpenAlways || | 131 if (!(open_flags & mojom::kFlagOpenAlways || |
132 open_flags & mojom::kFlagCreate)) { | 132 open_flags & mojom::kFlagCreate)) { |
133 // The directory doesn't exist, and we weren't passed parameters to | 133 // The directory doesn't exist, and we weren't passed parameters to |
134 // create it. | 134 // create it. |
135 callback.Run(mojom::FileError::NOT_FOUND); | 135 callback.Run(mojom::FileError::NOT_FOUND); |
136 return; | 136 return; |
137 } | 137 } |
138 | 138 |
139 base::File::Error error; | 139 base::File::Error error; |
140 if (!base::CreateDirectoryAndGetError(path, &error)) { | 140 if (!base::CreateDirectoryAndGetError(path, &error)) { |
141 callback.Run(static_cast<filesystem::mojom::FileError>(error)); | 141 callback.Run(static_cast<filesystem::mojom::FileError>(error)); |
142 return; | 142 return; |
143 } | 143 } |
144 } | 144 } |
145 | 145 |
146 if (directory.is_pending()) | 146 if (directory.is_pending()) { |
147 new DirectoryImpl(std::move(directory), path, temp_dir_, lock_table_); | 147 mojo::MakeStrongBinding( |
| 148 base::MakeUnique<DirectoryImpl>(path, temp_dir_, lock_table_), |
| 149 std::move(directory)); |
| 150 } |
| 151 |
148 callback.Run(mojom::FileError::OK); | 152 callback.Run(mojom::FileError::OK); |
149 } | 153 } |
150 | 154 |
151 void DirectoryImpl::Rename(const mojo::String& raw_old_path, | 155 void DirectoryImpl::Rename(const mojo::String& raw_old_path, |
152 const mojo::String& raw_new_path, | 156 const mojo::String& raw_new_path, |
153 const RenameCallback& callback) { | 157 const RenameCallback& callback) { |
154 base::FilePath old_path; | 158 base::FilePath old_path; |
155 mojom::FileError error = | 159 mojom::FileError error = |
156 ValidatePath(raw_old_path, directory_path_, &old_path); | 160 ValidatePath(raw_old_path, directory_path_, &old_path); |
157 if (error != mojom::FileError::OK) { | 161 if (error != mojom::FileError::OK) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 | 254 |
251 base::File::Info info; | 255 base::File::Info info; |
252 if (!base_file.GetInfo(&info)) { | 256 if (!base_file.GetInfo(&info)) { |
253 callback.Run(mojom::FileError::FAILED, nullptr); | 257 callback.Run(mojom::FileError::FAILED, nullptr); |
254 return; | 258 return; |
255 } | 259 } |
256 | 260 |
257 callback.Run(mojom::FileError::OK, MakeFileInformation(info)); | 261 callback.Run(mojom::FileError::OK, MakeFileInformation(info)); |
258 } | 262 } |
259 | 263 |
260 void DirectoryImpl::Clone(mojo::InterfaceRequest<mojom::Directory> directory) { | 264 void DirectoryImpl::Clone(mojom::DirectoryRequest directory) { |
261 if (directory.is_pending()) { | 265 if (directory.is_pending()) { |
262 new DirectoryImpl(std::move(directory), directory_path_, | 266 mojo::MakeStrongBinding(base::MakeUnique<DirectoryImpl>( |
263 temp_dir_, lock_table_); | 267 directory_path_, temp_dir_, lock_table_), |
| 268 std::move(directory)); |
264 } | 269 } |
265 } | 270 } |
266 | 271 |
267 void DirectoryImpl::ReadEntireFile(const mojo::String& raw_path, | 272 void DirectoryImpl::ReadEntireFile(const mojo::String& raw_path, |
268 const ReadEntireFileCallback& callback) { | 273 const ReadEntireFileCallback& callback) { |
269 base::FilePath path; | 274 base::FilePath path; |
270 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); | 275 mojom::FileError error = ValidatePath(raw_path, directory_path_, &path); |
271 if (error != mojom::FileError::OK) { | 276 if (error != mojom::FileError::OK) { |
272 callback.Run(error, mojo::Array<uint8_t>()); | 277 callback.Run(error, mojo::Array<uint8_t>()); |
273 return; | 278 return; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 if (!base_file.IsValid()) { | 355 if (!base_file.IsValid()) { |
351 *error = GetError(base_file); | 356 *error = GetError(base_file); |
352 return mojo::ScopedHandle(); | 357 return mojo::ScopedHandle(); |
353 } | 358 } |
354 | 359 |
355 *error = mojom::FileError::OK; | 360 *error = mojom::FileError::OK; |
356 return mojo::WrapPlatformFile(base_file.TakePlatformFile()); | 361 return mojo::WrapPlatformFile(base_file.TakePlatformFile()); |
357 } | 362 } |
358 | 363 |
359 } // namespace filesystem | 364 } // namespace filesystem |
OLD | NEW |