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 "chrome/browser/chromeos/fileapi/file_system_backend.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/synchronization/lock.h"
13 #include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
14 #include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h"
15 #include "chromeos/dbus/cros_disks_client.h"
16 #include "webkit/browser/blob/file_stream_reader.h"
17 #include "webkit/browser/fileapi/async_file_util.h"
18 #include "webkit/browser/fileapi/external_mount_points.h"
19 #include "webkit/browser/fileapi/file_stream_writer.h"
20 #include "webkit/browser/fileapi/file_system_context.h"
21 #include "webkit/browser/fileapi/file_system_operation.h"
22 #include "webkit/browser/fileapi/file_system_operation_context.h"
23 #include "webkit/browser/fileapi/file_system_url.h"
24 #include "webkit/browser/fileapi/isolated_context.h"
28 const char kChromeUIScheme[] = "chrome";
35 bool FileSystemBackend::CanHandleURL(const fileapi::FileSystemURL& url) {
38 return url.type() == fileapi::kFileSystemTypeNativeLocal ||
39 url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
40 url.type() == fileapi::kFileSystemTypeDrive;
43 FileSystemBackend::FileSystemBackend(
44 FileSystemBackendDelegate* drive_delegate,
45 scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
46 scoped_refptr<fileapi::ExternalMountPoints> mount_points,
47 fileapi::ExternalMountPoints* system_mount_points)
48 : special_storage_policy_(special_storage_policy),
49 file_access_permissions_(new FileAccessPermissions()),
50 local_file_util_(fileapi::AsyncFileUtil::CreateForLocalFileSystem()),
51 drive_delegate_(drive_delegate),
52 mount_points_(mount_points),
53 system_mount_points_(system_mount_points) {
56 FileSystemBackend::~FileSystemBackend() {
59 void FileSystemBackend::AddSystemMountPoints() {
60 // RegisterFileSystem() is no-op if the mount point with the same name
61 // already exists, hence it's safe to call without checking if a mount
62 // point already exists or not.
63 system_mount_points_->RegisterFileSystem(
65 fileapi::kFileSystemTypeNativeLocal,
66 chromeos::CrosDisksClient::GetArchiveMountPoint());
67 system_mount_points_->RegisterFileSystem(
69 fileapi::kFileSystemTypeNativeLocal,
70 chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
71 system_mount_points_->RegisterFileSystem(
73 fileapi::kFileSystemTypeRestrictedNativeLocal,
74 base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
77 bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type) const {
79 case fileapi::kFileSystemTypeExternal:
80 case fileapi::kFileSystemTypeDrive:
81 case fileapi::kFileSystemTypeRestrictedNativeLocal:
82 case fileapi::kFileSystemTypeNativeLocal:
83 case fileapi::kFileSystemTypeNativeForPlatformApp:
90 void FileSystemBackend::Initialize(fileapi::FileSystemContext* context) {
93 void FileSystemBackend::OpenFileSystem(
94 const GURL& origin_url,
95 fileapi::FileSystemType type,
96 fileapi::OpenFileSystemMode mode,
97 const OpenFileSystemCallback& callback) {
98 // TODO(nhiroki): Deprecate OpenFileSystem for non-sandboxed filesystem.
99 // (http://crbug.com/297412)
101 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY);
104 fileapi::FileSystemQuotaUtil* FileSystemBackend::GetQuotaUtil() {
109 bool FileSystemBackend::IsAccessAllowed(
110 const fileapi::FileSystemURL& url) const {
114 // Permit access to mount points from internal WebUI.
115 const GURL& origin_url = url.origin();
116 if (origin_url.SchemeIs(kChromeUIScheme))
119 // No extra check is needed for isolated file systems.
120 if (url.mount_type() == fileapi::kFileSystemTypeIsolated)
123 if (!CanHandleURL(url))
126 std::string extension_id = origin_url.host();
127 // TODO(mtomasz): Temporarily whitelist TimeScapes. Remove this in M-31.
128 // See: crbug.com/271946
129 if (extension_id == "mlbmkoenclnokonejhlfakkeabdlmpek" &&
130 url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal) {
134 // Check first to make sure this extension has fileBrowserHander permissions.
135 if (!special_storage_policy_->IsFileHandler(extension_id))
138 return file_access_permissions_->HasAccessPermission(extension_id,
142 void FileSystemBackend::GrantFullAccessToExtension(
143 const std::string& extension_id) {
144 DCHECK(special_storage_policy_->IsFileHandler(extension_id));
145 if (!special_storage_policy_->IsFileHandler(extension_id))
148 std::vector<fileapi::MountPoints::MountPointInfo> files;
149 mount_points_->AddMountPointInfosTo(&files);
150 system_mount_points_->AddMountPointInfosTo(&files);
152 for (size_t i = 0; i < files.size(); ++i) {
153 file_access_permissions_->GrantAccessPermission(
155 base::FilePath::FromUTF8Unsafe(files[i].name));
159 void FileSystemBackend::GrantFileAccessToExtension(
160 const std::string& extension_id, const base::FilePath& virtual_path) {
161 // All we care about here is access from extensions for now.
162 DCHECK(special_storage_policy_->IsFileHandler(extension_id));
163 if (!special_storage_policy_->IsFileHandler(extension_id))
167 fileapi::FileSystemType type;
169 if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &path) &&
170 !system_mount_points_->CrackVirtualPath(virtual_path,
171 &id, &type, &path)) {
175 if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
176 LOG(ERROR) << "Can't grant access for restricted mount point";
180 file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
183 void FileSystemBackend::RevokeAccessForExtension(
184 const std::string& extension_id) {
185 file_access_permissions_->RevokePermissions(extension_id);
188 std::vector<base::FilePath> FileSystemBackend::GetRootDirectories() const {
189 std::vector<fileapi::MountPoints::MountPointInfo> mount_points;
190 mount_points_->AddMountPointInfosTo(&mount_points);
191 system_mount_points_->AddMountPointInfosTo(&mount_points);
193 std::vector<base::FilePath> root_dirs;
194 for (size_t i = 0; i < mount_points.size(); ++i)
195 root_dirs.push_back(mount_points[i].path);
199 fileapi::AsyncFileUtil* FileSystemBackend::GetAsyncFileUtil(
200 fileapi::FileSystemType type) {
201 if (type == fileapi::kFileSystemTypeDrive)
202 return drive_delegate_->GetAsyncFileUtil(type);
204 DCHECK(type == fileapi::kFileSystemTypeNativeLocal ||
205 type == fileapi::kFileSystemTypeRestrictedNativeLocal);
206 return local_file_util_.get();
209 fileapi::CopyOrMoveFileValidatorFactory*
210 FileSystemBackend::GetCopyOrMoveFileValidatorFactory(
211 fileapi::FileSystemType type, base::PlatformFileError* error_code) {
213 *error_code = base::PLATFORM_FILE_OK;
217 fileapi::FileSystemOperation* FileSystemBackend::CreateFileSystemOperation(
218 const fileapi::FileSystemURL& url,
219 fileapi::FileSystemContext* context,
220 base::PlatformFileError* error_code) const {
221 DCHECK(url.is_valid());
223 if (!IsAccessAllowed(url)) {
224 *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
228 DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
229 url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
230 url.type() == fileapi::kFileSystemTypeDrive);
231 return fileapi::FileSystemOperation::Create(
233 make_scoped_ptr(new fileapi::FileSystemOperationContext(context)));
236 scoped_ptr<webkit_blob::FileStreamReader>
237 FileSystemBackend::CreateFileStreamReader(
238 const fileapi::FileSystemURL& url,
240 const base::Time& expected_modification_time,
241 fileapi::FileSystemContext* context) const {
242 DCHECK(url.is_valid());
244 if (!IsAccessAllowed(url))
245 return scoped_ptr<webkit_blob::FileStreamReader>();
247 if (url.type() == fileapi::kFileSystemTypeDrive) {
248 return drive_delegate_->CreateFileStreamReader(
249 url, offset, expected_modification_time, context);
252 return scoped_ptr<webkit_blob::FileStreamReader>(
253 webkit_blob::FileStreamReader::CreateForFileSystemFile(
254 context, url, offset, expected_modification_time));
257 scoped_ptr<fileapi::FileStreamWriter>
258 FileSystemBackend::CreateFileStreamWriter(
259 const fileapi::FileSystemURL& url,
261 fileapi::FileSystemContext* context) const {
262 DCHECK(url.is_valid());
264 if (!IsAccessAllowed(url))
265 return scoped_ptr<fileapi::FileStreamWriter>();
267 if (url.type() == fileapi::kFileSystemTypeDrive)
268 return drive_delegate_->CreateFileStreamWriter(url, offset, context);
270 if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal)
271 return scoped_ptr<fileapi::FileStreamWriter>();
273 DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal);
274 return scoped_ptr<fileapi::FileStreamWriter>(
275 fileapi::FileStreamWriter::CreateForLocalFile(
276 context->default_file_task_runner(), url.path(), offset));
279 bool FileSystemBackend::GetVirtualPath(
280 const base::FilePath& filesystem_path,
281 base::FilePath* virtual_path) {
282 return mount_points_->GetVirtualPath(filesystem_path, virtual_path) ||
283 system_mount_points_->GetVirtualPath(filesystem_path, virtual_path);
286 } // namespace chromeos