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