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 fileapi::FileSystemMountOption(),
67 chromeos::CrosDisksClient::GetArchiveMountPoint());
68 system_mount_points_
->RegisterFileSystem(
70 fileapi::kFileSystemTypeNativeLocal
,
71 fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_SYNC
),
72 chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
73 system_mount_points_
->RegisterFileSystem(
75 fileapi::kFileSystemTypeRestrictedNativeLocal
,
76 fileapi::FileSystemMountOption(),
77 base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
80 bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type
) const {
82 case fileapi::kFileSystemTypeExternal
:
83 case fileapi::kFileSystemTypeDrive
:
84 case fileapi::kFileSystemTypeRestrictedNativeLocal
:
85 case fileapi::kFileSystemTypeNativeLocal
:
86 case fileapi::kFileSystemTypeNativeForPlatformApp
:
93 void FileSystemBackend::Initialize(fileapi::FileSystemContext
* context
) {
96 void FileSystemBackend::OpenFileSystem(
97 const GURL
& origin_url
,
98 fileapi::FileSystemType type
,
99 fileapi::OpenFileSystemMode mode
,
100 const OpenFileSystemCallback
& callback
) {
101 // TODO(nhiroki): Deprecate OpenFileSystem for non-sandboxed filesystem.
102 // (http://crbug.com/297412)
104 callback
.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY
);
107 fileapi::FileSystemQuotaUtil
* FileSystemBackend::GetQuotaUtil() {
112 bool FileSystemBackend::IsAccessAllowed(
113 const fileapi::FileSystemURL
& url
) const {
117 // Permit access to mount points from internal WebUI.
118 const GURL
& origin_url
= url
.origin();
119 if (origin_url
.SchemeIs(kChromeUIScheme
))
122 // No extra check is needed for isolated file systems.
123 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
)
126 if (!CanHandleURL(url
))
129 std::string extension_id
= origin_url
.host();
130 // TODO(mtomasz): Temporarily whitelist TimeScapes. Remove this in M-31.
131 // See: crbug.com/271946
132 if (extension_id
== "mlbmkoenclnokonejhlfakkeabdlmpek" &&
133 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
) {
137 // Check first to make sure this extension has fileBrowserHander permissions.
138 if (!special_storage_policy_
->IsFileHandler(extension_id
))
141 return file_access_permissions_
->HasAccessPermission(extension_id
,
145 void FileSystemBackend::GrantFullAccessToExtension(
146 const std::string
& extension_id
) {
147 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
148 if (!special_storage_policy_
->IsFileHandler(extension_id
))
151 std::vector
<fileapi::MountPoints::MountPointInfo
> files
;
152 mount_points_
->AddMountPointInfosTo(&files
);
153 system_mount_points_
->AddMountPointInfosTo(&files
);
155 for (size_t i
= 0; i
< files
.size(); ++i
) {
156 file_access_permissions_
->GrantAccessPermission(
158 base::FilePath::FromUTF8Unsafe(files
[i
].name
));
162 void FileSystemBackend::GrantFileAccessToExtension(
163 const std::string
& extension_id
, const base::FilePath
& virtual_path
) {
164 // All we care about here is access from extensions for now.
165 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
166 if (!special_storage_policy_
->IsFileHandler(extension_id
))
170 fileapi::FileSystemType type
;
172 fileapi::FileSystemMountOption option
;
173 if (!mount_points_
->CrackVirtualPath(virtual_path
,
174 &id
, &type
, &path
, &option
) &&
175 !system_mount_points_
->CrackVirtualPath(virtual_path
,
176 &id
, &type
, &path
, &option
)) {
180 if (type
== fileapi::kFileSystemTypeRestrictedNativeLocal
) {
181 LOG(ERROR
) << "Can't grant access for restricted mount point";
185 file_access_permissions_
->GrantAccessPermission(extension_id
, virtual_path
);
188 void FileSystemBackend::RevokeAccessForExtension(
189 const std::string
& extension_id
) {
190 file_access_permissions_
->RevokePermissions(extension_id
);
193 std::vector
<base::FilePath
> FileSystemBackend::GetRootDirectories() const {
194 std::vector
<fileapi::MountPoints::MountPointInfo
> mount_points
;
195 mount_points_
->AddMountPointInfosTo(&mount_points
);
196 system_mount_points_
->AddMountPointInfosTo(&mount_points
);
198 std::vector
<base::FilePath
> root_dirs
;
199 for (size_t i
= 0; i
< mount_points
.size(); ++i
)
200 root_dirs
.push_back(mount_points
[i
].path
);
204 fileapi::AsyncFileUtil
* FileSystemBackend::GetAsyncFileUtil(
205 fileapi::FileSystemType type
) {
206 if (type
== fileapi::kFileSystemTypeDrive
)
207 return drive_delegate_
->GetAsyncFileUtil(type
);
209 DCHECK(type
== fileapi::kFileSystemTypeNativeLocal
||
210 type
== fileapi::kFileSystemTypeRestrictedNativeLocal
);
211 return local_file_util_
.get();
214 fileapi::CopyOrMoveFileValidatorFactory
*
215 FileSystemBackend::GetCopyOrMoveFileValidatorFactory(
216 fileapi::FileSystemType type
, base::PlatformFileError
* error_code
) {
218 *error_code
= base::PLATFORM_FILE_OK
;
222 fileapi::FileSystemOperation
* FileSystemBackend::CreateFileSystemOperation(
223 const fileapi::FileSystemURL
& url
,
224 fileapi::FileSystemContext
* context
,
225 base::PlatformFileError
* error_code
) const {
226 DCHECK(url
.is_valid());
228 if (!IsAccessAllowed(url
)) {
229 *error_code
= base::PLATFORM_FILE_ERROR_SECURITY
;
233 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
||
234 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
||
235 url
.type() == fileapi::kFileSystemTypeDrive
);
236 return fileapi::FileSystemOperation::Create(
238 make_scoped_ptr(new fileapi::FileSystemOperationContext(context
)));
241 scoped_ptr
<webkit_blob::FileStreamReader
>
242 FileSystemBackend::CreateFileStreamReader(
243 const fileapi::FileSystemURL
& url
,
245 const base::Time
& expected_modification_time
,
246 fileapi::FileSystemContext
* context
) const {
247 DCHECK(url
.is_valid());
249 if (!IsAccessAllowed(url
))
250 return scoped_ptr
<webkit_blob::FileStreamReader
>();
252 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
253 return drive_delegate_
->CreateFileStreamReader(
254 url
, offset
, expected_modification_time
, context
);
257 return scoped_ptr
<webkit_blob::FileStreamReader
>(
258 webkit_blob::FileStreamReader::CreateForFileSystemFile(
259 context
, url
, offset
, expected_modification_time
));
262 scoped_ptr
<fileapi::FileStreamWriter
>
263 FileSystemBackend::CreateFileStreamWriter(
264 const fileapi::FileSystemURL
& url
,
266 fileapi::FileSystemContext
* context
) const {
267 DCHECK(url
.is_valid());
269 if (!IsAccessAllowed(url
))
270 return scoped_ptr
<fileapi::FileStreamWriter
>();
272 if (url
.type() == fileapi::kFileSystemTypeDrive
)
273 return drive_delegate_
->CreateFileStreamWriter(url
, offset
, context
);
275 if (url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
)
276 return scoped_ptr
<fileapi::FileStreamWriter
>();
278 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
);
279 return scoped_ptr
<fileapi::FileStreamWriter
>(
280 fileapi::FileStreamWriter::CreateForLocalFile(
281 context
->default_file_task_runner(), url
.path(), offset
));
284 bool FileSystemBackend::GetVirtualPath(
285 const base::FilePath
& filesystem_path
,
286 base::FilePath
* virtual_path
) {
287 return mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
) ||
288 system_mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
);
291 } // namespace chromeos