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 "storage/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 "storage/browser/fileapi/async_file_util_adapter.h"
14 #include "storage/browser/fileapi/file_stream_reader.h"
15 #include "storage/browser/fileapi/file_stream_writer.h"
16 #include "storage/browser/fileapi/file_system_context.h"
17 #include "storage/browser/fileapi/file_system_operation.h"
18 #include "storage/browser/fileapi/file_system_operation_context.h"
19 #include "storage/browser/fileapi/file_system_options.h"
20 #include "storage/browser/fileapi/isolated_context.h"
21 #include "storage/browser/fileapi/obfuscated_file_util.h"
22 #include "storage/browser/fileapi/quota/quota_reservation.h"
23 #include "storage/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 storage::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(kFileSystemDirectory
)
95 .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::ResolveURL(
147 const FileSystemURL
& url
,
148 OpenFileSystemMode mode
,
149 const OpenFileSystemCallback
& callback
) {
150 // We never allow opening a new plugin-private filesystem via usual
152 base::MessageLoopProxy::current()->PostTask(
154 base::Bind(callback
, GURL(), std::string(),
155 base::File::FILE_ERROR_SECURITY
));
159 PluginPrivateFileSystemBackend::GetAsyncFileUtil(FileSystemType type
) {
160 return file_util_
.get();
163 WatcherManager
* PluginPrivateFileSystemBackend::GetWatcherManager(
164 FileSystemType type
) {
168 CopyOrMoveFileValidatorFactory
*
169 PluginPrivateFileSystemBackend::GetCopyOrMoveFileValidatorFactory(
171 base::File::Error
* error_code
) {
173 *error_code
= base::File::FILE_OK
;
177 FileSystemOperation
* PluginPrivateFileSystemBackend::CreateFileSystemOperation(
178 const FileSystemURL
& url
,
179 FileSystemContext
* context
,
180 base::File::Error
* error_code
) const {
181 scoped_ptr
<FileSystemOperationContext
> operation_context(
182 new FileSystemOperationContext(context
));
183 return FileSystemOperation::Create(url
, context
, operation_context
.Pass());
186 bool PluginPrivateFileSystemBackend::SupportsStreaming(
187 const storage::FileSystemURL
& url
) const {
191 bool PluginPrivateFileSystemBackend::HasInplaceCopyImplementation(
192 storage::FileSystemType type
) const {
196 scoped_ptr
<storage::FileStreamReader
>
197 PluginPrivateFileSystemBackend::CreateFileStreamReader(
198 const FileSystemURL
& url
,
200 int64 max_bytes_to_read
,
201 const base::Time
& expected_modification_time
,
202 FileSystemContext
* context
) const {
203 return scoped_ptr
<storage::FileStreamReader
>();
206 scoped_ptr
<FileStreamWriter
>
207 PluginPrivateFileSystemBackend::CreateFileStreamWriter(
208 const FileSystemURL
& url
,
210 FileSystemContext
* context
) const {
211 return scoped_ptr
<FileStreamWriter
>();
214 FileSystemQuotaUtil
* PluginPrivateFileSystemBackend::GetQuotaUtil() {
219 PluginPrivateFileSystemBackend::DeleteOriginDataOnFileTaskRunner(
220 FileSystemContext
* context
,
221 storage::QuotaManagerProxy
* proxy
,
222 const GURL
& origin_url
,
223 FileSystemType type
) {
224 if (!CanHandleType(type
))
225 return base::File::FILE_ERROR_SECURITY
;
226 bool result
= obfuscated_file_util()->DeleteDirectoryForOriginAndType(
227 origin_url
, std::string());
229 return base::File::FILE_OK
;
230 return base::File::FILE_ERROR_FAILED
;
233 void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner(
235 std::set
<GURL
>* origins
) {
236 if (!CanHandleType(type
))
238 scoped_ptr
<ObfuscatedFileUtil::AbstractOriginEnumerator
> enumerator(
239 obfuscated_file_util()->CreateOriginEnumerator());
241 while (!(origin
= enumerator
->Next()).is_empty())
242 origins
->insert(origin
);
245 void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner(
247 const std::string
& host
,
248 std::set
<GURL
>* origins
) {
249 if (!CanHandleType(type
))
251 scoped_ptr
<ObfuscatedFileUtil::AbstractOriginEnumerator
> enumerator(
252 obfuscated_file_util()->CreateOriginEnumerator());
254 while (!(origin
= enumerator
->Next()).is_empty()) {
255 if (host
== net::GetHostOrSpecFromURL(origin
))
256 origins
->insert(origin
);
260 int64
PluginPrivateFileSystemBackend::GetOriginUsageOnFileTaskRunner(
261 FileSystemContext
* context
,
262 const GURL
& origin_url
,
263 FileSystemType type
) {
264 // We don't track usage on this filesystem.
268 scoped_refptr
<QuotaReservation
>
269 PluginPrivateFileSystemBackend::CreateQuotaReservationOnFileTaskRunner(
270 const GURL
& origin_url
,
271 FileSystemType type
) {
272 // We don't track usage on this filesystem.
274 return scoped_refptr
<QuotaReservation
>();
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 storage