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.
5 #include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
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"
27 class PluginPrivateFileSystemBackend::FileSystemIDToPluginMap {
29 explicit FileSystemIDToPluginMap(base::SequencedTaskRunner* task_runner)
30 : task_runner_(task_runner) {}
31 ~FileSystemIDToPluginMap() {}
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();
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;
51 void RemoveFileSystem(const std::string& filesystem_id) {
52 DCHECK(task_runner_->RunsTasksOnCurrentThread());
53 map_.erase(filesystem_id);
57 typedef std::map<std::string, std::string> Map;
58 scoped_refptr<base::SequencedTaskRunner> task_runner_;
64 const base::FilePath::CharType* kFileSystemDirectory =
65 SandboxFileSystemBackendDelegate::kFileSystemDirectory;
66 const base::FilePath::CharType* kPluginPrivateDirectory =
67 FILE_PATH_LITERAL("Plugins");
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);
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)),
99 new AsyncFileUtilAdapter(new ObfuscatedFileUtil(
100 special_storage_policy,
101 base_path_, file_system_options.env_override(),
103 base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL,
104 base::Owned(plugin_map_)),
105 std::set<std::string>(),
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))
117 void PluginPrivateFileSystemBackend::OpenPrivateFileSystem(
118 const GURL& origin_url,
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));
130 PostTaskAndReplyWithResult(
131 file_task_runner_.get(),
133 base::Bind(&OpenFileSystemOnFileTaskRunner,
134 obfuscated_file_util(), plugin_map_,
135 origin_url, filesystem_id, plugin_id, mode),
139 bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const {
140 return type == kFileSystemTypePluginPrivate;
143 void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) {
146 void PluginPrivateFileSystemBackend::OpenFileSystem(
147 const GURL& origin_url,
149 OpenFileSystemMode mode,
150 const OpenFileSystemCallback& callback) {
151 // We never allow opening a new plugin-private filesystem via usual
153 base::MessageLoopProxy::current()->PostTask(
155 base::Bind(callback, GURL(), std::string(),
156 base::File::FILE_ERROR_SECURITY));
160 PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type) {
161 return file_util_.get();
164 CopyOrMoveFileValidatorFactory*
165 PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
167 base::File::Error* error_code) {
169 *error_code = base::File::FILE_OK;
173 FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
174 const FileSystemURL& url,
175 FileSystemContext* context,
176 base::File::Error* error_code) const {
177 scoped_ptr<FileSystemOperationContext> operation_context(
178 new FileSystemOperationContext(context));
179 return FileSystemOperation::Create(url, context, operation_context.Pass());
182 scoped_ptr<webkit_blob::FileStreamReader>
183 PluginPrivateFileSystemBackend::CreateFileStreamReader(
184 const FileSystemURL& url,
186 const base::Time& expected_modification_time,
187 FileSystemContext* context) const {
188 return scoped_ptr<webkit_blob::FileStreamReader>();
191 scoped_ptr<FileStreamWriter>
192 PluginPrivateFileSystemBackend::CreateFileStreamWriter(
193 const FileSystemURL& url,
195 FileSystemContext* context) const {
196 return scoped_ptr<FileStreamWriter>();
199 FileSystemQuotaUtil* PluginPrivateFileSystemBackend::GetQuotaUtil() {
204 PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner(
205 FileSystemContext* context,
206 quota::QuotaManagerProxy* proxy,
207 const GURL& origin_url,
208 FileSystemType type) {
209 if (!CanHandleType(type))
210 return base::File::FILE_ERROR_SECURITY;
211 bool result = obfuscated_file_util()->DeleteDirectoryForOriginAndType(
212 origin_url, std::string());
214 return base::File::FILE_OK;
215 return base::File::FILE_ERROR_FAILED;
218 void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner(
220 std::set<GURL>* origins) {
221 if (!CanHandleType(type))
223 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
224 obfuscated_file_util()->CreateOriginEnumerator());
226 while (!(origin = enumerator->Next()).is_empty())
227 origins->insert(origin);
230 void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner(
232 const std::string& host,
233 std::set<GURL>* origins) {
234 if (!CanHandleType(type))
236 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator(
237 obfuscated_file_util()->CreateOriginEnumerator());
239 while (!(origin = enumerator->Next()).is_empty()) {
240 if (host == net::GetHostOrSpecFromURL(origin))
241 origins->insert(origin);
245 int64 PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner(
246 FileSystemContext* context,
247 const GURL& origin_url,
248 FileSystemType type) {
249 // We don't track usage on this filesystem.
253 scoped_refptr<QuotaReservation>
254 PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner(
255 const GURL& origin_url,
256 FileSystemType type) {
257 // We don't track usage on this filesystem.
259 return scoped_refptr<QuotaReservation>();
262 void PluginPrivateFileSystemBackend::AddFileUpdateObserver(
264 FileUpdateObserver* observer,
265 base::SequencedTaskRunner* task_runner) {}
267 void PluginPrivateFileSystemBackend::AddFileChangeObserver(
269 FileChangeObserver* observer,
270 base::SequencedTaskRunner* task_runner) {}
272 void PluginPrivateFileSystemBackend::AddFileAccessObserver(
274 FileAccessObserver* observer,
275 base::SequencedTaskRunner* task_runner) {}
277 const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers(
278 FileSystemType type) const {
282 const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers(
283 FileSystemType type) const {
287 const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers(
288 FileSystemType type) const {
292 ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() {
293 return static_cast<ObfuscatedFileUtil*>(
294 static_cast<AsyncFileUtilAdapter*>(file_util_.get())->sync_file_util());
297 } // namespace fileapi