| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "webkit/fileapi/isolated_context.h" | 5 #include "webkit/fileapi/isolated_context.h" |
| 6 | 6 |
| 7 #include "base/file_path.h" | 7 #include "base/file_path.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 break; | 32 break; |
| 33 } | 33 } |
| 34 name.append(1, path.value()[i]); | 34 name.append(1, path.value()[i]); |
| 35 } | 35 } |
| 36 return name; | 36 return name; |
| 37 #else | 37 #else |
| 38 return FILE_PATH_LITERAL("<root>"); | 38 return FILE_PATH_LITERAL("<root>"); |
| 39 #endif | 39 #endif |
| 40 } | 40 } |
| 41 | 41 |
| 42 bool IsSinglePathIsolatedFileSystem(FileSystemType type) { |
| 43 switch (type) { |
| 44 // As of writing dragged file system is the only filesystem |
| 45 // which could have multiple toplevel paths. |
| 46 case kFileSystemTypeDragged: |
| 47 return false; |
| 48 |
| 49 // Regular file systems. |
| 50 case kFileSystemTypeIsolated: |
| 51 case kFileSystemTypeNativeMedia: |
| 52 case kFileSystemTypeDeviceMedia: |
| 53 case kFileSystemTypeTemporary: |
| 54 case kFileSystemTypePersistent: |
| 55 case kFileSystemTypeExternal: |
| 56 case kFileSystemTypeTest: |
| 57 return true; |
| 58 |
| 59 case kFileSystemTypeUnknown: |
| 60 NOTREACHED(); |
| 61 return true; |
| 62 } |
| 63 NOTREACHED(); |
| 64 return true; |
| 65 } |
| 66 |
| 42 } | 67 } |
| 43 | 68 |
| 44 static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context = | 69 static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context = |
| 45 LAZY_INSTANCE_INITIALIZER; | 70 LAZY_INSTANCE_INITIALIZER; |
| 46 | 71 |
| 47 IsolatedContext::FileInfo::FileInfo() {} | 72 IsolatedContext::FileInfo::FileInfo() {} |
| 48 IsolatedContext::FileInfo::FileInfo( | 73 IsolatedContext::FileInfo::FileInfo( |
| 49 const std::string& name, const FilePath& path) | 74 const std::string& name, const FilePath& path) |
| 50 : name(name), path(path) {} | 75 : name(name), path(path) {} |
| 51 | 76 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 return false; | 109 return false; |
| 85 return fileset_.insert(FileInfo(name, path.NormalizePathSeparators())).second; | 110 return fileset_.insert(FileInfo(name, path.NormalizePathSeparators())).second; |
| 86 } | 111 } |
| 87 | 112 |
| 88 //-------------------------------------------------------------------------- | 113 //-------------------------------------------------------------------------- |
| 89 | 114 |
| 90 IsolatedContext::Instance::Instance(FileSystemType type, | 115 IsolatedContext::Instance::Instance(FileSystemType type, |
| 91 const FileInfo& file_info) | 116 const FileInfo& file_info) |
| 92 : type_(type), | 117 : type_(type), |
| 93 file_info_(file_info), | 118 file_info_(file_info), |
| 94 ref_counts_(0) {} | 119 ref_counts_(0) { |
| 120 DCHECK(IsSinglePathIsolatedFileSystem(type_)); |
| 121 } |
| 95 | 122 |
| 96 IsolatedContext::Instance::Instance(const std::set<FileInfo>& dragged_files) | 123 IsolatedContext::Instance::Instance(FileSystemType type, |
| 97 : type_(kFileSystemTypeDragged), | 124 const std::set<FileInfo>& files) |
| 98 dragged_files_(dragged_files), | 125 : type_(type), |
| 99 ref_counts_(0) {} | 126 files_(files), |
| 127 ref_counts_(0) { |
| 128 DCHECK(!IsSinglePathIsolatedFileSystem(type_)); |
| 129 } |
| 100 | 130 |
| 101 IsolatedContext::Instance::~Instance() {} | 131 IsolatedContext::Instance::~Instance() {} |
| 102 | 132 |
| 103 bool IsolatedContext::Instance::ResolvePathForName(const std::string& name, | 133 bool IsolatedContext::Instance::ResolvePathForName(const std::string& name, |
| 104 FilePath* path) { | 134 FilePath* path) const { |
| 105 if (type_ != kFileSystemTypeDragged) { | 135 if (IsSinglePathIsolatedFileSystem(type_)) { |
| 106 *path = file_info_.path; | 136 *path = file_info_.path; |
| 107 return file_info_.name == name; | 137 return file_info_.name == name; |
| 108 } | 138 } |
| 109 std::set<FileInfo>::const_iterator found = dragged_files_.find( | 139 std::set<FileInfo>::const_iterator found = files_.find( |
| 110 FileInfo(name, FilePath())); | 140 FileInfo(name, FilePath())); |
| 111 if (found == dragged_files_.end()) | 141 if (found == files_.end()) |
| 112 return false; | 142 return false; |
| 113 *path = found->path; | 143 *path = found->path; |
| 114 return true; | 144 return true; |
| 115 } | 145 } |
| 116 | 146 |
| 147 bool IsolatedContext::Instance::IsSinglePathInstance() const { |
| 148 return IsSinglePathIsolatedFileSystem(type_); |
| 149 } |
| 150 |
| 117 //-------------------------------------------------------------------------- | 151 //-------------------------------------------------------------------------- |
| 118 | 152 |
| 119 // static | 153 // static |
| 120 IsolatedContext* IsolatedContext::GetInstance() { | 154 IsolatedContext* IsolatedContext::GetInstance() { |
| 121 return g_isolated_context.Pointer(); | 155 return g_isolated_context.Pointer(); |
| 122 } | 156 } |
| 123 | 157 |
| 124 std::string IsolatedContext::RegisterDraggedFileSystem( | 158 std::string IsolatedContext::RegisterDraggedFileSystem( |
| 125 const FileInfoSet& files) { | 159 const FileInfoSet& files) { |
| 126 base::AutoLock locker(lock_); | 160 base::AutoLock locker(lock_); |
| 127 std::string filesystem_id = GetNewFileSystemId(); | 161 std::string filesystem_id = GetNewFileSystemId(); |
| 128 instance_map_[filesystem_id] = new Instance(files.fileset()); | 162 instance_map_[filesystem_id] = new Instance( |
| 163 kFileSystemTypeDragged, files.fileset()); |
| 129 return filesystem_id; | 164 return filesystem_id; |
| 130 } | 165 } |
| 131 | 166 |
| 132 std::string IsolatedContext::RegisterFileSystemForPath( | 167 std::string IsolatedContext::RegisterFileSystemForPath( |
| 133 FileSystemType type, | 168 FileSystemType type, |
| 134 const FilePath& path, | 169 const FilePath& path, |
| 135 std::string* register_name) { | 170 std::string* register_name) { |
| 136 DCHECK(!path.ReferencesParent() && path.IsAbsolute()); | 171 DCHECK(!path.ReferencesParent() && path.IsAbsolute()); |
| 137 std::string name; | 172 std::string name; |
| 138 if (register_name && !register_name->empty()) { | 173 if (register_name && !register_name->empty()) { |
| 139 name = *register_name; | 174 name = *register_name; |
| 140 } else { | 175 } else { |
| 141 name = FilePath(GetRegisterNameForPath(path)).AsUTF8Unsafe(); | 176 name = FilePath(GetRegisterNameForPath(path)).AsUTF8Unsafe(); |
| 142 if (register_name) | 177 if (register_name) |
| 143 register_name->assign(name); | 178 register_name->assign(name); |
| 144 } | 179 } |
| 145 | 180 |
| 146 base::AutoLock locker(lock_); | 181 base::AutoLock locker(lock_); |
| 147 std::string filesystem_id = GetNewFileSystemId(); | 182 std::string filesystem_id = GetNewFileSystemId(); |
| 148 instance_map_[filesystem_id] = new Instance(type, FileInfo(name, path)); | 183 instance_map_[filesystem_id] = new Instance(type, FileInfo(name, path)); |
| 184 path_to_id_map_[path].insert(filesystem_id); |
| 149 return filesystem_id; | 185 return filesystem_id; |
| 150 } | 186 } |
| 151 | 187 |
| 152 void IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) { | 188 void IsolatedContext::RevokeFileSystemByPath(const FilePath& path) { |
| 153 base::AutoLock locker(lock_); | 189 base::AutoLock locker(lock_); |
| 154 IDToInstance::iterator found = instance_map_.find(filesystem_id); | 190 PathToID::iterator ids_iter = path_to_id_map_.find(path); |
| 155 if (found == instance_map_.end()) | 191 if (ids_iter == path_to_id_map_.end()) |
| 156 return; | 192 return; |
| 157 delete found->second; | 193 std::set<std::string>& ids = ids_iter->second; |
| 158 instance_map_.erase(found); | 194 for (std::set<std::string>::iterator iter = ids.begin(); |
| 195 iter != ids.end(); ++iter) { |
| 196 IDToInstance::iterator found = instance_map_.find(*iter); |
| 197 if (found != instance_map_.end()) { |
| 198 delete found->second; |
| 199 instance_map_.erase(found); |
| 200 } |
| 201 } |
| 202 path_to_id_map_.erase(ids_iter); |
| 159 } | 203 } |
| 160 | 204 |
| 161 void IsolatedContext::AddReference(const std::string& filesystem_id) { | 205 void IsolatedContext::AddReference(const std::string& filesystem_id) { |
| 162 base::AutoLock locker(lock_); | 206 base::AutoLock locker(lock_); |
| 163 DCHECK(instance_map_.find(filesystem_id) != instance_map_.end()); | 207 DCHECK(instance_map_.find(filesystem_id) != instance_map_.end()); |
| 164 instance_map_[filesystem_id]->AddRef(); | 208 instance_map_[filesystem_id]->AddRef(); |
| 165 } | 209 } |
| 166 | 210 |
| 167 void IsolatedContext::RemoveReference(const std::string& filesystem_id) { | 211 void IsolatedContext::RemoveReference(const std::string& filesystem_id) { |
| 168 base::AutoLock locker(lock_); | 212 base::AutoLock locker(lock_); |
| 169 // This could get called for non-existent filesystem if it has been | 213 // This could get called for non-existent filesystem if it has been |
| 170 // already deleted by RevokeFileSystem. | 214 // already deleted by RevokeFileSystemByPath. |
| 171 IDToInstance::iterator found = instance_map_.find(filesystem_id); | 215 IDToInstance::iterator found = instance_map_.find(filesystem_id); |
| 172 if (found == instance_map_.end()) | 216 if (found == instance_map_.end()) |
| 173 return; | 217 return; |
| 174 DCHECK(found->second->ref_counts() > 0); | 218 Instance* instance = found->second; |
| 175 found->second->RemoveRef(); | 219 DCHECK(instance->ref_counts() > 0); |
| 176 if (found->second->ref_counts() == 0) { | 220 instance->RemoveRef(); |
| 177 delete found->second; | 221 if (instance->ref_counts() == 0) { |
| 222 if (instance->IsSinglePathInstance()) { |
| 223 PathToID::iterator ids_iter = path_to_id_map_.find( |
| 224 instance->file_info().path); |
| 225 DCHECK(ids_iter != path_to_id_map_.end()); |
| 226 ids_iter->second.erase(filesystem_id); |
| 227 if (ids_iter->second.empty()) |
| 228 path_to_id_map_.erase(ids_iter); |
| 229 } |
| 230 delete instance; |
| 178 instance_map_.erase(found); | 231 instance_map_.erase(found); |
| 179 } | 232 } |
| 180 } | 233 } |
| 181 | 234 |
| 182 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, | 235 bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path, |
| 183 std::string* filesystem_id, | 236 std::string* filesystem_id, |
| 184 FileSystemType* type, | 237 FileSystemType* type, |
| 185 FilePath* path) const { | 238 FilePath* path) const { |
| 186 DCHECK(filesystem_id); | 239 DCHECK(filesystem_id); |
| 187 DCHECK(path); | 240 DCHECK(path); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 } | 275 } |
| 223 | 276 |
| 224 bool IsolatedContext::GetDraggedFileInfo( | 277 bool IsolatedContext::GetDraggedFileInfo( |
| 225 const std::string& filesystem_id, std::vector<FileInfo>* files) const { | 278 const std::string& filesystem_id, std::vector<FileInfo>* files) const { |
| 226 DCHECK(files); | 279 DCHECK(files); |
| 227 base::AutoLock locker(lock_); | 280 base::AutoLock locker(lock_); |
| 228 IDToInstance::const_iterator found = instance_map_.find(filesystem_id); | 281 IDToInstance::const_iterator found = instance_map_.find(filesystem_id); |
| 229 if (found == instance_map_.end() || | 282 if (found == instance_map_.end() || |
| 230 found->second->type() != kFileSystemTypeDragged) | 283 found->second->type() != kFileSystemTypeDragged) |
| 231 return false; | 284 return false; |
| 232 files->assign(found->second->dragged_files().begin(), | 285 files->assign(found->second->files().begin(), |
| 233 found->second->dragged_files().end()); | 286 found->second->files().end()); |
| 234 return true; | 287 return true; |
| 235 } | 288 } |
| 236 | 289 |
| 237 bool IsolatedContext::GetRegisteredPath( | 290 bool IsolatedContext::GetRegisteredPath( |
| 238 const std::string& filesystem_id, FilePath* path) const { | 291 const std::string& filesystem_id, FilePath* path) const { |
| 239 DCHECK(path); | 292 DCHECK(path); |
| 240 base::AutoLock locker(lock_); | 293 base::AutoLock locker(lock_); |
| 241 IDToInstance::const_iterator found = instance_map_.find(filesystem_id); | 294 IDToInstance::const_iterator found = instance_map_.find(filesystem_id); |
| 242 if (found == instance_map_.end() || | 295 if (found == instance_map_.end() || !found->second->IsSinglePathInstance()) |
| 243 found->second->type() == kFileSystemTypeDragged) | |
| 244 return false; | 296 return false; |
| 245 *path = found->second->file_info().path; | 297 *path = found->second->file_info().path; |
| 246 return true; | 298 return true; |
| 247 } | 299 } |
| 248 | 300 |
| 249 FilePath IsolatedContext::CreateVirtualRootPath( | 301 FilePath IsolatedContext::CreateVirtualRootPath( |
| 250 const std::string& filesystem_id) const { | 302 const std::string& filesystem_id) const { |
| 251 return FilePath().AppendASCII(filesystem_id); | 303 return FilePath().AppendASCII(filesystem_id); |
| 252 } | 304 } |
| 253 | 305 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 264 uint32 random_data[4]; | 316 uint32 random_data[4]; |
| 265 std::string id; | 317 std::string id; |
| 266 do { | 318 do { |
| 267 base::RandBytes(random_data, sizeof(random_data)); | 319 base::RandBytes(random_data, sizeof(random_data)); |
| 268 id = base::HexEncode(random_data, sizeof(random_data)); | 320 id = base::HexEncode(random_data, sizeof(random_data)); |
| 269 } while (instance_map_.find(id) != instance_map_.end()); | 321 } while (instance_map_.find(id) != instance_map_.end()); |
| 270 return id; | 322 return id; |
| 271 } | 323 } |
| 272 | 324 |
| 273 } // namespace fileapi | 325 } // namespace fileapi |
| OLD | NEW |