OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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 "webkit/fileapi/external_mount_points.h" | |
6 | |
7 #include "base/file_path.h" | |
8 #include "base/lazy_instance.h" | |
9 #include "base/path_service.h" | |
10 #include "base/stl_util.h" | |
11 #include "webkit/fileapi/remote_file_system_proxy.h" | |
12 | |
13 namespace { | |
14 | |
15 // Wrapper around ref-counted ExternalMountPoints that will be used to lazily | |
16 // create and initialize LazyInstance system ExternalMountPoints. | |
17 class SystemMountPointsLazyWrapper { | |
18 public: | |
19 SystemMountPointsLazyWrapper() | |
20 : system_mount_points_(fileapi::ExternalMountPoints::CreateRefCounted()) { | |
21 RegisterDefaultMountPoints(); | |
22 } | |
23 | |
24 ~SystemMountPointsLazyWrapper() {} | |
25 | |
26 fileapi::ExternalMountPoints* get() { | |
27 return system_mount_points_.get(); | |
28 } | |
29 | |
30 private: | |
31 void RegisterDefaultMountPoints() { | |
32 #if defined(OS_CHROMEOS) | |
33 // Add default system mount points. | |
34 system_mount_points_->RegisterFileSystem( | |
35 "archive", | |
36 fileapi::kFileSystemTypeNativeLocal, | |
37 FilePath(FILE_PATH_LITERAL("/media/archive"))); | |
38 system_mount_points_->RegisterFileSystem( | |
39 "removable", | |
40 fileapi::kFileSystemTypeNativeLocal, | |
41 FilePath(FILE_PATH_LITERAL("/media/removable"))); | |
42 system_mount_points_->RegisterFileSystem( | |
43 "oem", | |
44 fileapi::kFileSystemTypeRestrictedNativeLocal, | |
45 FilePath(FILE_PATH_LITERAL("/usr/share/oem"))); | |
46 | |
47 // TODO(tbarzic): Move this out of here. | |
48 FilePath home_path; | |
49 if (PathService::Get(base::DIR_HOME, &home_path)) { | |
50 system_mount_points_->RegisterFileSystem( | |
51 "Downloads", | |
52 fileapi::kFileSystemTypeNativeLocal, | |
53 home_path.AppendASCII("Downloads")); | |
54 } | |
55 #endif // defined(OS_CHROMEOS) | |
56 } | |
57 | |
58 scoped_refptr<fileapi::ExternalMountPoints> system_mount_points_; | |
59 }; | |
60 | |
61 base::LazyInstance<SystemMountPointsLazyWrapper>::Leaky | |
62 g_external_mount_points = LAZY_INSTANCE_INITIALIZER; | |
63 | |
64 } // namespace | |
65 | |
66 namespace fileapi { | |
67 | |
68 class ExternalMountPoints::Instance { | |
69 public: | |
70 Instance(FileSystemType type, | |
71 const FilePath& path, | |
72 RemoteFileSystemProxyInterface* remote_proxy); | |
73 | |
74 ~Instance(); | |
75 | |
76 FileSystemType type() const { return type_; } | |
77 const FilePath& path() const { return path_; } | |
78 RemoteFileSystemProxyInterface* remote_proxy() const { | |
79 return remote_proxy_.get(); | |
80 } | |
81 | |
82 private: | |
83 const FileSystemType type_; | |
84 const FilePath path_; | |
85 | |
86 // For file systems that have a remote file system proxy. | |
87 scoped_refptr<RemoteFileSystemProxyInterface> remote_proxy_; | |
88 | |
89 DISALLOW_COPY_AND_ASSIGN(Instance); | |
90 }; | |
91 | |
92 ExternalMountPoints::Instance::Instance(FileSystemType type, | |
93 const FilePath& path, | |
94 RemoteFileSystemProxyInterface* proxy) | |
95 : type_(type), | |
96 path_(path), | |
97 remote_proxy_(proxy) { | |
98 DCHECK(!proxy || (kFileSystemTypeDrive == type_)); | |
99 } | |
100 | |
101 ExternalMountPoints::Instance::~Instance() {} | |
102 | |
103 //-------------------------------------------------------------------------- | |
104 | |
105 // static | |
106 ExternalMountPoints* ExternalMountPoints::GetSystemInstance() { | |
107 return g_external_mount_points.Pointer()->get(); | |
108 } | |
109 | |
110 // static | |
111 scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() { | |
112 return new ExternalMountPoints(); | |
113 } | |
114 | |
115 bool ExternalMountPoints::RegisterFileSystem( | |
116 const std::string& mount_name, | |
117 FileSystemType type, | |
118 const FilePath& path) { | |
119 return RegisterRemoteFileSystem(mount_name, type, NULL, path); | |
120 } | |
121 | |
122 bool ExternalMountPoints::RegisterRemoteFileSystem( | |
123 const std::string& mount_name, | |
124 FileSystemType type, | |
125 RemoteFileSystemProxyInterface* remote_proxy, | |
126 const FilePath& path) { | |
127 base::AutoLock locker(lock_); | |
128 | |
129 if (!ValidateNewMountPoint(mount_name, path)) | |
130 return false; | |
131 | |
132 instance_map_[mount_name] = new Instance(type, path, remote_proxy); | |
133 if (!path.empty()) | |
134 path_to_name_map_.insert(std::make_pair(path, mount_name)); | |
135 return true; | |
136 } | |
137 | |
138 bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) { | |
139 base::AutoLock locker(lock_); | |
140 NameToInstance::iterator found = instance_map_.find(mount_name); | |
141 if (found == instance_map_.end()) | |
142 return false; | |
143 Instance* instance = found->second; | |
144 path_to_name_map_.erase(instance->path()); | |
145 delete found->second; | |
146 instance_map_.erase(found); | |
147 return true; | |
148 } | |
149 | |
150 bool ExternalMountPoints::GetRegisteredPath( | |
151 const std::string& filesystem_id, FilePath* path) const { | |
152 DCHECK(path); | |
153 base::AutoLock locker(lock_); | |
154 NameToInstance::const_iterator found = instance_map_.find(filesystem_id); | |
155 if (found == instance_map_.end()) | |
156 return false; | |
157 *path = found->second->path(); | |
158 return true; | |
159 } | |
160 | |
161 bool ExternalMountPoints::CrackVirtualPath(const FilePath& virtual_path, | |
162 std::string* mount_name, | |
163 FileSystemType* type, | |
164 FilePath* path) const { | |
165 DCHECK(mount_name); | |
166 DCHECK(path); | |
167 | |
168 // The path should not contain any '..' references. | |
169 if (virtual_path.ReferencesParent()) | |
170 return false; | |
171 | |
172 // The virtual_path should comprise of <mount_name> and <relative_path> parts. | |
173 std::vector<FilePath::StringType> components; | |
174 virtual_path.GetComponents(&components); | |
175 if (components.size() < 1) | |
176 return false; | |
177 | |
178 std::vector<FilePath::StringType>::iterator component_iter = | |
179 components.begin(); | |
180 std::string maybe_mount_name = FilePath(*component_iter++).MaybeAsASCII(); | |
181 if (maybe_mount_name.empty()) | |
182 return false; | |
183 | |
184 FilePath cracked_path; | |
185 { | |
186 base::AutoLock locker(lock_); | |
187 NameToInstance::const_iterator found_instance = | |
188 instance_map_.find(maybe_mount_name); | |
189 if (found_instance == instance_map_.end()) | |
190 return false; | |
191 | |
192 *mount_name = maybe_mount_name; | |
193 const Instance* instance = found_instance->second; | |
194 if (type) | |
195 *type = instance->type(); | |
196 cracked_path = instance->path(); | |
197 } | |
198 | |
199 for (; component_iter != components.end(); ++component_iter) | |
200 cracked_path = cracked_path.Append(*component_iter); | |
201 *path = cracked_path; | |
202 return true; | |
203 } | |
204 | |
205 RemoteFileSystemProxyInterface* ExternalMountPoints::GetRemoteFileSystemProxy( | |
206 const std::string& mount_name) const { | |
207 base::AutoLock locker(lock_); | |
208 NameToInstance::const_iterator found = instance_map_.find(mount_name); | |
209 if (found == instance_map_.end()) | |
210 return NULL; | |
211 return found->second->remote_proxy(); | |
212 } | |
213 | |
214 void ExternalMountPoints::AddMountPointInfosTo( | |
215 std::vector<MountPointInfo>* mount_points) const { | |
216 base::AutoLock locker(lock_); | |
217 DCHECK(mount_points); | |
218 for (NameToInstance::const_iterator iter = instance_map_.begin(); | |
219 iter != instance_map_.end(); ++iter) { | |
220 mount_points->push_back(MountPointInfo(iter->first, iter->second->path())); | |
221 } | |
222 } | |
223 | |
224 bool ExternalMountPoints::GetVirtualPath(const FilePath& absolute_path, | |
225 FilePath* virtual_path) { | |
226 DCHECK(virtual_path); | |
227 base::AutoLock locker(lock_); | |
228 std::map<FilePath, std::string>::reverse_iterator iter( | |
229 path_to_name_map_.upper_bound(absolute_path)); | |
230 if (iter == path_to_name_map_.rend()) | |
231 return false; | |
232 | |
233 *virtual_path = CreateVirtualRootPath(iter->second); | |
234 if (iter->first == absolute_path) | |
235 return true; | |
236 return iter->first.AppendRelativePath(absolute_path, virtual_path); | |
237 } | |
238 | |
239 FilePath ExternalMountPoints::CreateVirtualRootPath( | |
240 const std::string& mount_name) const { | |
241 return FilePath().AppendASCII(mount_name); | |
242 } | |
243 | |
244 ExternalMountPoints::ExternalMountPoints() { } | |
kinuko
2013/01/11 08:20:52
nit: no space necessary in empty {}
tbarzic
2013/01/11 09:13:16
Done.
| |
245 | |
246 ExternalMountPoints::~ExternalMountPoints() { | |
247 STLDeleteContainerPairSecondPointers(instance_map_.begin(), | |
248 instance_map_.end()); | |
249 } | |
250 | |
251 bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name, | |
252 const FilePath& path) { | |
kinuko
2013/01/11 08:20:52
Can you call lock_.AssertAcquired() here to make s
tbarzic
2013/01/11 09:13:16
Done.
| |
253 // Mount name must not be empty. | |
254 if (mount_name.empty()) | |
255 return false; | |
256 | |
257 // Verify there is no registered mount point with the same name. | |
258 NameToInstance::iterator found = instance_map_.find(mount_name); | |
259 if (found != instance_map_.end()) | |
260 return false; | |
261 | |
262 // Allow empty paths. | |
263 if (path.empty()) | |
264 return true; | |
265 | |
266 // Verify path is legal. | |
267 if (path.ReferencesParent() || !path.IsAbsolute()) | |
268 return false; | |
269 | |
270 // Check there the new path does not overlap with one of the existing ones. | |
271 std::map<FilePath, std::string>::reverse_iterator potential_parent( | |
272 path_to_name_map_.upper_bound(path)); | |
273 if (potential_parent != path_to_name_map_.rend()) { | |
274 if (potential_parent->first == path || | |
275 potential_parent->first.IsParent(path)) { | |
276 return false; | |
277 } | |
278 } | |
279 | |
280 std::map<FilePath, std::string>::iterator potential_child = | |
281 path_to_name_map_.upper_bound(path); | |
282 if (potential_child == path_to_name_map_.end()) | |
283 return true; | |
284 return !(potential_child->first == path) && | |
285 !path.IsParent(potential_child->first); | |
286 } | |
287 | |
288 ScopedExternalFileSystem::ScopedExternalFileSystem( | |
289 const std::string& mount_name, | |
290 FileSystemType type, | |
291 const FilePath& path) | |
292 : mount_name_(mount_name) { | |
293 ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( | |
294 mount_name, type, path); | |
295 } | |
296 | |
297 FilePath ScopedExternalFileSystem::GetVirtualRootPath() const { | |
298 return ExternalMountPoints::GetSystemInstance()-> | |
299 CreateVirtualRootPath(mount_name_); | |
300 } | |
301 | |
302 ScopedExternalFileSystem::~ScopedExternalFileSystem() { | |
303 ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(mount_name_); | |
304 } | |
305 | |
306 } // namespace fileapi | |
307 | |
OLD | NEW |