Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / fileapi / file_system_context.cc
blob72558d9522434e606dfe2c76e5dacea702188a3a
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"
7 #include "base/bind.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"
35 #endif
37 using quota::QuotaClient;
39 namespace fileapi {
41 namespace {
43 QuotaClient* CreateQuotaClient(
44 FileSystemContext* context,
45 bool is_incognito) {
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);
57 } // namespace
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),
68 sandbox_provider_(
69 new SandboxMountPointProvider(
70 quota_manager_proxy,
71 task_runners_->file_task_runner(),
72 partition_path,
73 options)),
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()));
91 #endif
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.
106 return
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);
121 FileSystemQuotaUtil*
122 FileSystemContext::GetQuotaUtil(FileSystemType type) const {
123 FileSystemMountPointProvider* mount_point_provider =
124 GetMountPointProvider(type);
125 if (!mount_point_provider)
126 return NULL;
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)
135 return NULL;
136 return mount_point_provider->GetAsyncFileUtil(type);
139 CopyOrMoveFileValidatorFactory*
140 FileSystemContext::GetCopyOrMoveFileValidatorFactory(
141 FileSystemType type, base::PlatformFileError* error_code) const {
142 DCHECK(error_code);
143 *error_code = base::PLATFORM_FILE_OK;
144 FileSystemMountPointProvider* mount_point_provider =
145 GetMountPointProvider(type);
146 if (!mount_point_provider)
147 return NULL;
148 return mount_point_provider->GetCopyOrMoveFileValidatorFactory(
149 type, error_code);
152 FileSystemMountPointProvider* FileSystemContext::GetMountPointProvider(
153 FileSystemType type) const {
154 switch (type) {
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();
172 #else
173 return isolated_provider_.get();
174 #endif
175 default:
176 if (provider_map_.find(type) != provider_map_.end())
177 return provider_map_.find(type)->second;
178 // Fall through.
179 case kFileSystemTypeUnknown:
180 NOTREACHED();
181 return NULL;
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)
195 return NULL;
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,
214 FileSystemType type,
215 bool create,
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());
223 return;
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,
237 FileSystemType type,
238 bool create,
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,
258 FileSystemType type,
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);
265 return;
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()) {
274 if (error_code)
275 *error_code = base::PLATFORM_FILE_ERROR_INVALID_URL;
276 return NULL;
279 FileSystemMountPointProvider* mount_point_provider =
280 GetMountPointProvider(url.type());
281 if (!mount_point_provider) {
282 if (error_code)
283 *error_code = base::PLATFORM_FILE_ERROR_FAILED;
284 return NULL;
287 base::PlatformFileError fs_error = base::PLATFORM_FILE_OK;
288 FileSystemOperation* operation =
289 mount_point_provider->CreateFileSystemOperation(url, this, &fs_error);
291 if (error_code)
292 *error_code = fs_error;
293 return operation;
296 scoped_ptr<webkit_blob::FileStreamReader>
297 FileSystemContext::CreateFileStreamReader(
298 const FileSystemURL& url,
299 int64 offset,
300 const base::Time& expected_modification_time) {
301 if (!url.is_valid())
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,
313 int64 offset) {
314 if (!url.is_valid())
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(
324 FileSystemType type,
325 FileSystemMountPointProvider* provider) {
326 DCHECK(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(
354 const GURL& origin,
355 FileSystemType type,
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)) {
368 return;
370 STLDeleteContainerPairSecondPointers(provider_map_.begin(),
371 provider_map_.end());
372 delete this;
375 FileSystemURL FileSystemContext::CrackFileSystemURL(
376 const FileSystemURL& url) const {
377 if (!url.is_valid())
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.
386 for (;;) {
387 FileSystemURL cracked = current;
388 for (size_t i = 0; i < url_crackers_.size(); ++i) {
389 if (!url_crackers_[i]->HandlesFileSystemMountType(current.type()))
390 continue;
391 cracked = url_crackers_[i]->CrackFileSystemURL(current);
392 if (cracked.is_valid())
393 break;
395 if (cracked == current)
396 break;
397 current = cracked;
399 return current;
402 FileSystemFileUtil* FileSystemContext::GetFileUtil(
403 FileSystemType type) const {
404 FileSystemMountPointProvider* mount_point_provider =
405 GetMountPointProvider(type);
406 if (!mount_point_provider)
407 return NULL;
408 return mount_point_provider->GetFileUtil(type);
411 } // namespace fileapi