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.
5 #include "webkit/fileapi/file_system_context.h"
8 #include "base/stl_util.h"
9 #include "base/single_thread_task_runner.h"
10 #include "googleurl/src/gurl.h"
11 #include "webkit/blob/file_stream_reader.h"
12 #include "webkit/fileapi/copy_or_move_file_validator.h"
13 #include "webkit/fileapi/external_mount_points.h"
14 #include "webkit/fileapi/file_stream_writer.h"
15 #include "webkit/fileapi/file_system_file_util.h"
16 #include "webkit/fileapi/file_system_operation.h"
17 #include "webkit/fileapi/file_system_options.h"
18 #include "webkit/fileapi/file_system_quota_client.h"
19 #include "webkit/fileapi/file_system_task_runners.h"
20 #include "webkit/fileapi/file_system_url.h"
21 #include "webkit/fileapi/file_system_util.h"
22 #include "webkit/fileapi/isolated_context.h"
23 #include "webkit/fileapi/isolated_mount_point_provider.h"
24 #include "webkit/fileapi/mount_points.h"
25 #include "webkit/fileapi/sandbox_mount_point_provider.h"
26 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
27 #include "webkit/fileapi/syncable/local_file_sync_context.h"
28 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
29 #include "webkit/fileapi/test_mount_point_provider.h"
30 #include "webkit/quota/quota_manager.h"
31 #include "webkit/quota/special_storage_policy.h"
33 #if defined(OS_CHROMEOS)
34 #include "webkit/chromeos/fileapi/cros_mount_point_provider.h"
37 using quota::QuotaClient
;
43 QuotaClient
* CreateQuotaClient(
44 FileSystemContext
* context
,
46 return new FileSystemQuotaClient(context
, is_incognito
);
49 void DidOpenFileSystem(
50 const FileSystemContext::OpenFileSystemCallback
& callback
,
51 const GURL
& filesystem_root
,
52 const std::string
& filesystem_name
,
53 base::PlatformFileError error
) {
54 callback
.Run(error
, filesystem_name
, filesystem_root
);
59 FileSystemContext::FileSystemContext(
60 scoped_ptr
<FileSystemTaskRunners
> task_runners
,
61 ExternalMountPoints
* external_mount_points
,
62 quota::SpecialStoragePolicy
* special_storage_policy
,
63 quota::QuotaManagerProxy
* quota_manager_proxy
,
64 const base::FilePath
& partition_path
,
65 const FileSystemOptions
& options
)
66 : task_runners_(task_runners
.Pass()),
67 quota_manager_proxy_(quota_manager_proxy
),
69 new SandboxMountPointProvider(
71 task_runners_
->file_task_runner(),
74 isolated_provider_(new IsolatedMountPointProvider(partition_path
)),
75 external_mount_points_(external_mount_points
),
76 partition_path_(partition_path
) {
77 DCHECK(task_runners_
.get());
79 if (quota_manager_proxy
) {
80 quota_manager_proxy
->RegisterClient(CreateQuotaClient(
81 this, options
.is_incognito()));
84 #if defined(OS_CHROMEOS)
85 DCHECK(external_mount_points
);
86 external_provider_
.reset(
87 new chromeos::CrosMountPointProvider(
88 special_storage_policy
,
89 external_mount_points
,
90 ExternalMountPoints::GetSystemInstance()));
93 if (external_mount_points
)
94 url_crackers_
.push_back(external_mount_points
);
95 url_crackers_
.push_back(ExternalMountPoints::GetSystemInstance());
96 url_crackers_
.push_back(IsolatedContext::GetInstance());
99 bool FileSystemContext::DeleteDataForOriginOnFileThread(
100 const GURL
& origin_url
) {
101 DCHECK(task_runners_
->file_task_runner()->RunsTasksOnCurrentThread());
102 DCHECK(sandbox_provider());
103 DCHECK(origin_url
== origin_url
.GetOrigin());
105 // Delete temporary and persistent data.
107 (sandbox_provider()->DeleteOriginDataOnFileThread(
108 this, quota_manager_proxy(), origin_url
,
109 kFileSystemTypeTemporary
) ==
110 base::PLATFORM_FILE_OK
) &&
111 (sandbox_provider()->DeleteOriginDataOnFileThread(
112 this, quota_manager_proxy(), origin_url
,
113 kFileSystemTypePersistent
) ==
114 base::PLATFORM_FILE_OK
) &&
115 (sandbox_provider()->DeleteOriginDataOnFileThread(
116 this, quota_manager_proxy(), origin_url
,
117 kFileSystemTypeSyncable
) ==
118 base::PLATFORM_FILE_OK
);
122 FileSystemContext::GetQuotaUtil(FileSystemType type
) const {
123 FileSystemMountPointProvider
* mount_point_provider
=
124 GetMountPointProvider(type
);
125 if (!mount_point_provider
)
127 return mount_point_provider
->GetQuotaUtil();
130 AsyncFileUtil
* FileSystemContext::GetAsyncFileUtil(
131 FileSystemType type
) const {
132 FileSystemMountPointProvider
* mount_point_provider
=
133 GetMountPointProvider(type
);
134 if (!mount_point_provider
)
136 return mount_point_provider
->GetAsyncFileUtil(type
);
139 CopyOrMoveFileValidatorFactory
*
140 FileSystemContext::GetCopyOrMoveFileValidatorFactory(
141 FileSystemType type
, base::PlatformFileError
* error_code
) const {
143 *error_code
= base::PLATFORM_FILE_OK
;
144 FileSystemMountPointProvider
* mount_point_provider
=
145 GetMountPointProvider(type
);
146 if (!mount_point_provider
)
148 return mount_point_provider
->GetCopyOrMoveFileValidatorFactory(
152 FileSystemMountPointProvider
* FileSystemContext::GetMountPointProvider(
153 FileSystemType type
) const {
155 case kFileSystemTypeTemporary
:
156 case kFileSystemTypePersistent
:
157 case kFileSystemTypeSyncable
:
158 return sandbox_provider_
.get();
159 case kFileSystemTypeExternal
:
160 case kFileSystemTypeDrive
:
161 case kFileSystemTypeRestrictedNativeLocal
:
162 return external_provider_
.get();
163 case kFileSystemTypeIsolated
:
164 case kFileSystemTypeDragged
:
165 case kFileSystemTypeNativeMedia
:
166 case kFileSystemTypeDeviceMedia
:
167 return isolated_provider_
.get();
168 case kFileSystemTypeNativeLocal
:
169 case kFileSystemTypeNativeForPlatformApp
:
170 #if defined(OS_CHROMEOS)
171 return external_provider_
.get();
173 return isolated_provider_
.get();
176 if (provider_map_
.find(type
) != provider_map_
.end())
177 return provider_map_
.find(type
)->second
;
179 case kFileSystemTypeUnknown
:
185 const UpdateObserverList
* FileSystemContext::GetUpdateObservers(
186 FileSystemType type
) const {
187 // Currently update observer is only available in SandboxMountPointProvider
188 // and TestMountPointProvider.
189 // TODO(kinuko): Probably GetUpdateObservers() virtual method should be
190 // added to FileSystemMountPointProvider interface and be called like
191 // other GetFoo() methods do.
192 if (SandboxMountPointProvider::CanHandleType(type
))
193 return sandbox_provider()->GetUpdateObservers(type
);
194 if (type
!= kFileSystemTypeTest
)
196 FileSystemMountPointProvider
* mount_point_provider
=
197 GetMountPointProvider(type
);
198 return static_cast<TestMountPointProvider
*>(
199 mount_point_provider
)->GetUpdateObservers(type
);
202 SandboxMountPointProvider
*
203 FileSystemContext::sandbox_provider() const {
204 return sandbox_provider_
.get();
207 ExternalFileSystemMountPointProvider
*
208 FileSystemContext::external_provider() const {
209 return external_provider_
.get();
212 void FileSystemContext::OpenFileSystem(
213 const GURL
& origin_url
,
216 const OpenFileSystemCallback
& callback
) {
217 DCHECK(!callback
.is_null());
219 FileSystemMountPointProvider
* mount_point_provider
=
220 GetMountPointProvider(type
);
221 if (!mount_point_provider
) {
222 callback
.Run(base::PLATFORM_FILE_ERROR_SECURITY
, std::string(), GURL());
226 GURL root_url
= GetFileSystemRootURI(origin_url
, type
);
227 std::string name
= GetFileSystemName(origin_url
, type
);
229 mount_point_provider
->ValidateFileSystemRoot(
230 origin_url
, type
, create
,
231 base::Bind(&DidOpenFileSystem
, callback
, root_url
, name
));
234 void FileSystemContext::OpenSyncableFileSystem(
235 const std::string
& mount_name
,
236 const GURL
& origin_url
,
239 const OpenFileSystemCallback
& callback
) {
240 DCHECK(!callback
.is_null());
242 DCHECK(type
== kFileSystemTypeSyncable
);
244 GURL root_url
= sync_file_system::GetSyncableFileSystemRootURI(
245 origin_url
, mount_name
);
246 std::string name
= GetFileSystemName(origin_url
, kFileSystemTypeSyncable
);
248 FileSystemMountPointProvider
* mount_point_provider
=
249 GetMountPointProvider(type
);
250 DCHECK(mount_point_provider
);
251 mount_point_provider
->ValidateFileSystemRoot(
252 origin_url
, type
, create
,
253 base::Bind(&DidOpenFileSystem
, callback
, root_url
, name
));
256 void FileSystemContext::DeleteFileSystem(
257 const GURL
& origin_url
,
259 const DeleteFileSystemCallback
& callback
) {
260 DCHECK(origin_url
== origin_url
.GetOrigin());
261 FileSystemMountPointProvider
* mount_point_provider
=
262 GetMountPointProvider(type
);
263 if (!mount_point_provider
) {
264 callback
.Run(base::PLATFORM_FILE_ERROR_SECURITY
);
268 mount_point_provider
->DeleteFileSystem(origin_url
, type
, this, callback
);
271 FileSystemOperation
* FileSystemContext::CreateFileSystemOperation(
272 const FileSystemURL
& url
, base::PlatformFileError
* error_code
) {
273 if (!url
.is_valid()) {
275 *error_code
= base::PLATFORM_FILE_ERROR_INVALID_URL
;
279 FileSystemMountPointProvider
* mount_point_provider
=
280 GetMountPointProvider(url
.type());
281 if (!mount_point_provider
) {
283 *error_code
= base::PLATFORM_FILE_ERROR_FAILED
;
287 base::PlatformFileError fs_error
= base::PLATFORM_FILE_OK
;
288 FileSystemOperation
* operation
=
289 mount_point_provider
->CreateFileSystemOperation(url
, this, &fs_error
);
292 *error_code
= fs_error
;
296 scoped_ptr
<webkit_blob::FileStreamReader
>
297 FileSystemContext::CreateFileStreamReader(
298 const FileSystemURL
& url
,
300 const base::Time
& expected_modification_time
) {
302 return scoped_ptr
<webkit_blob::FileStreamReader
>();
303 FileSystemMountPointProvider
* mount_point_provider
=
304 GetMountPointProvider(url
.type());
305 if (!mount_point_provider
)
306 return scoped_ptr
<webkit_blob::FileStreamReader
>();
307 return mount_point_provider
->CreateFileStreamReader(
308 url
, offset
, expected_modification_time
, this);
311 scoped_ptr
<FileStreamWriter
> FileSystemContext::CreateFileStreamWriter(
312 const FileSystemURL
& url
,
315 return scoped_ptr
<FileStreamWriter
>();
316 FileSystemMountPointProvider
* mount_point_provider
=
317 GetMountPointProvider(url
.type());
318 if (!mount_point_provider
)
319 return scoped_ptr
<FileStreamWriter
>();
320 return mount_point_provider
->CreateFileStreamWriter(url
, offset
, this);
323 void FileSystemContext::RegisterMountPointProvider(
325 FileSystemMountPointProvider
* provider
) {
327 DCHECK(provider_map_
.find(type
) == provider_map_
.end());
328 provider_map_
[type
] = provider
;
331 void FileSystemContext::SetLocalFileChangeTracker(
332 scoped_ptr
<sync_file_system::LocalFileChangeTracker
> tracker
) {
333 DCHECK(!change_tracker_
.get());
334 DCHECK(tracker
.get());
335 change_tracker_
= tracker
.Pass();
336 sandbox_provider_
->AddSyncableFileUpdateObserver(
337 change_tracker_
.get(),
338 task_runners_
->file_task_runner());
339 sandbox_provider_
->AddSyncableFileChangeObserver(
340 change_tracker_
.get(),
341 task_runners_
->file_task_runner());
344 void FileSystemContext::set_sync_context(
345 sync_file_system::LocalFileSyncContext
* sync_context
) {
346 sync_context_
= sync_context
;
349 FileSystemURL
FileSystemContext::CrackURL(const GURL
& url
) const {
350 return CrackFileSystemURL(FileSystemURL(url
));
353 FileSystemURL
FileSystemContext::CreateCrackedFileSystemURL(
356 const base::FilePath
& path
) const {
357 return CrackFileSystemURL(FileSystemURL(origin
, type
, path
));
360 FileSystemContext::~FileSystemContext() {
361 task_runners_
->file_task_runner()->DeleteSoon(
362 FROM_HERE
, change_tracker_
.release());
365 void FileSystemContext::DeleteOnCorrectThread() const {
366 if (!task_runners_
->io_task_runner()->RunsTasksOnCurrentThread() &&
367 task_runners_
->io_task_runner()->DeleteSoon(FROM_HERE
, this)) {
370 STLDeleteContainerPairSecondPointers(provider_map_
.begin(),
371 provider_map_
.end());
375 FileSystemURL
FileSystemContext::CrackFileSystemURL(
376 const FileSystemURL
& url
) const {
378 return FileSystemURL();
380 // The returned value in case there is no crackers which can crack the url.
381 // This is valid situation for non isolated/external file systems.
382 FileSystemURL current
= url
;
384 // File system may be mounted multiple times (e.g., an isolated filesystem on
385 // top of an external filesystem). Hence cracking needs to be iterated.
387 FileSystemURL cracked
= current
;
388 for (size_t i
= 0; i
< url_crackers_
.size(); ++i
) {
389 if (!url_crackers_
[i
]->HandlesFileSystemMountType(current
.type()))
391 cracked
= url_crackers_
[i
]->CrackFileSystemURL(current
);
392 if (cracked
.is_valid())
395 if (cracked
== current
)
402 FileSystemFileUtil
* FileSystemContext::GetFileUtil(
403 FileSystemType type
) const {
404 FileSystemMountPointProvider
* mount_point_provider
=
405 GetMountPointProvider(type
);
406 if (!mount_point_provider
)
408 return mount_point_provider
->GetFileUtil(type
);
411 } // namespace fileapi