1 // Copyright 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/browser/fileapi/plugin_private_file_system_backend.h" 6 7 #include <map> 8 9 #include "base/stl_util.h" 10 #include "base/synchronization/lock.h" 11 #include "base/task_runner_util.h" 12 #include "net/base/net_util.h" 13 #include "webkit/browser/blob/file_stream_reader.h" 14 #include "webkit/browser/fileapi/async_file_util_adapter.h" 15 #include "webkit/browser/fileapi/file_stream_writer.h" 16 #include "webkit/browser/fileapi/file_system_context.h" 17 #include "webkit/browser/fileapi/file_system_operation.h" 18 #include "webkit/browser/fileapi/file_system_operation_context.h" 19 #include "webkit/browser/fileapi/file_system_options.h" 20 #include "webkit/browser/fileapi/isolated_context.h" 21 #include "webkit/browser/fileapi/obfuscated_file_util.h" 22 #include "webkit/browser/fileapi/quota/quota_reservation.h" 23 #include "webkit/common/fileapi/file_system_util.h" 24 25 namespace fileapi { 26 27 class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap { 28 public: 29 explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner) 30 : task_runner_(task_runner) {} 31 ~FileSystemIDToPluginMap() {} 32 33 std::string GetPluginIDForURL(const FileSystemURL& url) { 34 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 35 Map::iterator found = map_.find(url.filesystem_id()); 36 if (url.type() != kFileSystemTypePluginPrivate || found == map_.end()) { 37 NOTREACHED() << "Unsupported url is given: " << url.DebugString(); 38 return std::string(); 39 } 40 return found->second; 41 } 42 43 void RegisterFileSystem(const std::string& filesystem_id, 44 const std::string& plugin_id) { 45 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 46 DCHECK(!filesystem_id.empty()); 47 DCHECK(!ContainsKey(map_, filesystem_id)) << filesystem_id; 48 map_[filesystem_id] = plugin_id; 49 } 50 51 void RemoveFileSystem(const std::string& filesystem_id) { 52 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 53 map_.erase(filesystem_id); 54 } 55 56 private: 57 typedef std::map<std::string, std::string> Map; 58 scoped_refptr<base::SequencedTaskRunner> task_runner_; 59 Map map_; 60 }; 61 62 namespace { 63 64 const base::FilePath::CharType* kFileSystemDirectory = 65 SandboxFileSystemBackendDelegate::kFileSystemDirectory; 66 const base::FilePath::CharType* kPluginPrivateDirectory = 67 FILE_PATH_LITERAL("Plugins"); 68 69 base::File::Error OpenFileSystemOnFileTaskRunner( 70 ObfuscatedFileUtil* file_util, 71 PluginPrivateFileSystemBackend::FileSystemIDToPluginMap* plugin_map, 72 const GURL& origin_url, 73 const std::string& filesystem_id, 74 const std::string& plugin_id, 75 OpenFileSystemMode mode) { 76 base::File::Error error = base::File::FILE_ERROR_FAILED; 77 const bool create = (mode == OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT); 78 file_util->GetDirectoryForOriginAndType( 79 origin_url, plugin_id, create, &error); 80 if (error == base::File::FILE_OK) 81 plugin_map->RegisterFileSystem(filesystem_id, plugin_id); 82 return error; 83 } 84 85 } // namespace 86 87 PluginPrivateFileSystemBackend::PluginPrivateFileSystemBackend( 88 base::SequencedTaskRunner* file_task_runner, 89 const base::FilePath& profile_path, 90 quota::SpecialStoragePolicy* special_storage_policy, 91 const FileSystemOptions& file_system_options) 92 : file_task_runner_(file_task_runner), 93 file_system_options_(file_system_options), 94 base_path_(profile_path.Append( 95 kFileSystemDirectory).Append(kPluginPrivateDirectory)), 96 plugin_map_(new FileSystemIDToPluginMap(file_task_runner)), 97 weak_factory_(this) { 98 file_util_.reset( 99 new AsyncFileUtilAdapter(new ObfuscatedFileUtil( 100 special_storage_policy, 101 base_path_, file_system_options.env_override(), 102 file_task_runner, 103 base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL, 104 base::Owned(plugin_map_)), 105 std::set<std::string>(), 106 NULL))); 107 } 108 109 PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() { 110 if (!file_task_runner_->RunsTasksOnCurrentThread()) { 111 AsyncFileUtil* file_util = file_util_.release(); 112 if (!file_task_runner_->DeleteSoon(FROM_HERE, file_util)) 113 delete file_util; 114 } 115 } 116 117 void PluginPrivateFileSystemBackend::OpenPrivateFileSystem( 118 const GURL& origin_url, 119 FileSystemType type, 120 const std::string& filesystem_id, 121 const std::string& plugin_id, 122 OpenFileSystemMode mode, 123 const StatusCallback& callback) { 124 if (!CanHandleType(type) || file_system_options_.is_incognito()) { 125 base::MessageLoopProxy::current()->PostTask( 126 FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_SECURITY)); 127 return; 128 } 129 130 PostTaskAndReplyWithResult( 131 file_task_runner_.get(), 132 FROM_HERE, 133 base::Bind(&OpenFileSystemOnFileTaskRunner, 134 obfuscated_file_util(), plugin_map_, 135 origin_url, filesystem_id, plugin_id, mode), 136 callback); 137 } 138 139 bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const { 140 return type == kFileSystemTypePluginPrivate; 141 } 142 143 void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) { 144 } 145 146 void PluginPrivateFileSystemBackend::ResolveURL( 147 const FileSystemURL& url, 148 OpenFileSystemMode mode, 149 const OpenFileSystemCallback& callback) { 150 // We never allow opening a new plugin-private filesystem via usual 151 // ResolveURL. 152 base::MessageLoopProxy::current()->PostTask( 153 FROM_HERE, 154 base::Bind(callback, GURL(), std::string(), 155 base::File::FILE_ERROR_SECURITY)); 156 } 157 158 AsyncFileUtil* 159 PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) { 160 return file_util_.get(); 161 } 162 163 CopyOrMoveFileValidatorFactory* 164 PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory( 165 FileSystemType type, 166 base::File::Error* error_code) { 167 DCHECK(error_code); 168 *error_code = base::File::FILE_OK; 169 return NULL; 170 } 171 172 FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation( 173 const FileSystemURL& url, 174 FileSystemContext* context, 175 base::File::Error* error_code) const { 176 scoped_ptr<FileSystemOperationContext> operation_context( 177 new FileSystemOperationContext(context)); 178 return FileSystemOperation::Create(url, context, operation_context.Pass()); 179 } 180 181 bool PluginPrivateFileSystemBackend::SupportsStreaming( 182 const fileapi::FileSystemURL& url) const { 183 return false; 184 } 185 186 scoped_ptr<webkit_blob::FileStreamReader> 187 PluginPrivateFileSystemBackend::CreateFileStreamReader( 188 const FileSystemURL& url, 189 int64 offset, 190 const base::Time& expected_modification_time, 191 FileSystemContext* context) const { 192 return scoped_ptr<webkit_blob::FileStreamReader>(); 193 } 194 195 scoped_ptr<FileStreamWriter> 196 PluginPrivateFileSystemBackend::CreateFileStreamWriter( 197 const FileSystemURL& url, 198 int64 offset, 199 FileSystemContext* context) const { 200 return scoped_ptr<FileStreamWriter>(); 201 } 202 203 FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() { 204 return this; 205 } 206 207 base::File::Error 208 PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner( 209 FileSystemContext* context, 210 quota::QuotaManagerProxy* proxy, 211 const GURL& origin_url, 212 FileSystemType type) { 213 if (!CanHandleType(type)) 214 return base::File::FILE_ERROR_SECURITY; 215 bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType( 216 origin_url, std::string()); 217 if (result) 218 return base::File::FILE_OK; 219 return base::File::FILE_ERROR_FAILED; 220 } 221 222 void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner( 223 FileSystemType type, 224 std::set<GURL>* origins) { 225 if (!CanHandleType(type)) 226 return; 227 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( 228 obfuscated_file_util()->CreateOriginEnumerator()); 229 GURL origin; 230 while (!(origin = enumerator->Next()).is_empty()) 231 origins->insert(origin); 232 } 233 234 void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner( 235 FileSystemType type, 236 const std::string& host, 237 std::set<GURL>* origins) { 238 if (!CanHandleType(type)) 239 return; 240 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( 241 obfuscated_file_util()->CreateOriginEnumerator()); 242 GURL origin; 243 while (!(origin = enumerator->Next()).is_empty()) { 244 if (host == net::GetHostOrSpecFromURL(origin)) 245 origins->insert(origin); 246 } 247 } 248 249 int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner( 250 FileSystemContext* context, 251 const GURL& origin_url, 252 FileSystemType type) { 253 // We don't track usage on this filesystem. 254 return 0; 255 } 256 257 scoped_refptr<QuotaReservation> 258 PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner( 259 const GURL& origin_url, 260 FileSystemType type) { 261 // We don't track usage on this filesystem. 262 NOTREACHED(); 263 return scoped_refptr<QuotaReservation>(); 264 } 265 266 void PluginPrivateFileSystemBackend::AddFileUpdateObserver( 267 FileSystemType type, 268 FileUpdateObserver* observer, 269 base::SequencedTaskRunner* task_runner) {} 270 271 void PluginPrivateFileSystemBackend::AddFileChangeObserver( 272 FileSystemType type, 273 FileChangeObserver* observer, 274 base::SequencedTaskRunner* task_runner) {} 275 276 void PluginPrivateFileSystemBackend::AddFileAccessObserver( 277 FileSystemType type, 278 FileAccessObserver* observer, 279 base::SequencedTaskRunner* task_runner) {} 280 281 const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers( 282 FileSystemType type) const { 283 return NULL; 284 } 285 286 const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers( 287 FileSystemType type) const { 288 return NULL; 289 } 290 291 const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers( 292 FileSystemType type) const { 293 return NULL; 294 } 295 296 ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() { 297 return static_cast<ObfuscatedFileUtil*>( 298 static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util()); 299 } 300 301 } // namespace fileapi 302