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/chromeos/fileapi/cros_mount_point_provider.h"
7 #include "base/chromeos/chromeos_version.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop.h"
11 #include "base/stringprintf.h"
12 #include "base/synchronization/lock.h"
13 #include "base/utf_string_conversions.h"
14 #include "chromeos/dbus/cros_disks_client.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebFileSystem.h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
18 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
19 #include "webkit/chromeos/fileapi/file_access_permissions.h"
20 #include "webkit/chromeos/fileapi/remote_file_stream_writer.h"
21 #include "webkit/chromeos/fileapi/remote_file_system_operation.h"
22 #include "webkit/fileapi/async_file_util_adapter.h"
23 #include "webkit/fileapi/external_mount_points.h"
24 #include "webkit/fileapi/file_system_context.h"
25 #include "webkit/fileapi/file_system_file_stream_reader.h"
26 #include "webkit/fileapi/file_system_operation_context.h"
27 #include "webkit/fileapi/file_system_task_runners.h"
28 #include "webkit/fileapi/file_system_url.h"
29 #include "webkit/fileapi/file_system_util.h"
30 #include "webkit/fileapi/isolated_context.h"
31 #include "webkit/fileapi/isolated_file_util.h"
32 #include "webkit/fileapi/local_file_stream_writer.h"
33 #include "webkit/fileapi/local_file_system_operation.h"
34 #include "webkit/glue/webkit_glue.h"
38 const char kChromeUIScheme
[] = "chrome";
45 bool CrosMountPointProvider::CanHandleURL(const fileapi::FileSystemURL
& url
) {
48 return url
.type() == fileapi::kFileSystemTypeNativeLocal
||
49 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
||
50 url
.type() == fileapi::kFileSystemTypeDrive
;
53 CrosMountPointProvider::CrosMountPointProvider(
54 scoped_refptr
<quota::SpecialStoragePolicy
> special_storage_policy
,
55 scoped_refptr
<fileapi::ExternalMountPoints
> mount_points
,
56 fileapi::ExternalMountPoints
* system_mount_points
)
57 : special_storage_policy_(special_storage_policy
),
58 file_access_permissions_(new FileAccessPermissions()),
59 local_file_util_(new fileapi::AsyncFileUtilAdapter(
60 new fileapi::IsolatedFileUtil())),
61 mount_points_(mount_points
),
62 system_mount_points_(system_mount_points
) {
63 // Add default system mount points.
64 system_mount_points_
->RegisterFileSystem(
66 fileapi::kFileSystemTypeNativeLocal
,
67 chromeos::CrosDisksClient::GetArchiveMountPoint());
68 system_mount_points_
->RegisterFileSystem(
70 fileapi::kFileSystemTypeNativeLocal
,
71 chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
72 system_mount_points_
->RegisterFileSystem(
74 fileapi::kFileSystemTypeRestrictedNativeLocal
,
75 base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
78 CrosMountPointProvider::~CrosMountPointProvider() {
81 bool CrosMountPointProvider::CanHandleType(fileapi::FileSystemType type
) const {
83 case fileapi::kFileSystemTypeExternal
:
84 case fileapi::kFileSystemTypeDrive
:
85 case fileapi::kFileSystemTypeRestrictedNativeLocal
:
86 case fileapi::kFileSystemTypeNativeLocal
:
87 case fileapi::kFileSystemTypeNativeForPlatformApp
:
94 void CrosMountPointProvider::ValidateFileSystemRoot(
95 const GURL
& origin_url
,
96 fileapi::FileSystemType type
,
98 const ValidateFileSystemCallback
& callback
) {
99 DCHECK(fileapi::IsolatedContext::IsIsolatedType(type
));
100 // Nothing to validate for external filesystem.
101 callback
.Run(base::PLATFORM_FILE_OK
);
104 base::FilePath
CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
105 const fileapi::FileSystemURL
& url
,
107 DCHECK(fileapi::IsolatedContext::IsIsolatedType(url
.mount_type()));
109 return base::FilePath();
111 base::FilePath root_path
;
112 std::string mount_name
= url
.filesystem_id();
113 if (!mount_points_
->GetRegisteredPath(mount_name
, &root_path
) &&
114 !system_mount_points_
->GetRegisteredPath(mount_name
, &root_path
)) {
115 return base::FilePath();
118 return root_path
.DirName();
121 fileapi::FileSystemQuotaUtil
* CrosMountPointProvider::GetQuotaUtil() {
126 void CrosMountPointProvider::DeleteFileSystem(
127 const GURL
& origin_url
,
128 fileapi::FileSystemType type
,
129 fileapi::FileSystemContext
* context
,
130 const DeleteFileSystemCallback
& callback
) {
132 callback
.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION
);
135 bool CrosMountPointProvider::IsAccessAllowed(
136 const fileapi::FileSystemURL
& url
) const {
140 // Permit access to mount points from internal WebUI.
141 const GURL
& origin_url
= url
.origin();
142 if (origin_url
.SchemeIs(kChromeUIScheme
))
145 // No extra check is needed for isolated file systems.
146 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
)
149 if (!CanHandleURL(url
))
152 std::string extension_id
= origin_url
.host();
153 // Check first to make sure this extension has fileBrowserHander permissions.
154 if (!special_storage_policy_
->IsFileHandler(extension_id
))
157 return file_access_permissions_
->HasAccessPermission(extension_id
,
161 void CrosMountPointProvider::GrantFullAccessToExtension(
162 const std::string
& extension_id
) {
163 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
164 if (!special_storage_policy_
->IsFileHandler(extension_id
))
167 std::vector
<fileapi::MountPoints::MountPointInfo
> files
;
168 mount_points_
->AddMountPointInfosTo(&files
);
169 system_mount_points_
->AddMountPointInfosTo(&files
);
171 for (size_t i
= 0; i
< files
.size(); ++i
) {
172 file_access_permissions_
->GrantAccessPermission(
174 base::FilePath::FromUTF8Unsafe(files
[i
].name
));
178 void CrosMountPointProvider::GrantFileAccessToExtension(
179 const std::string
& extension_id
, const base::FilePath
& virtual_path
) {
180 // All we care about here is access from extensions for now.
181 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
182 if (!special_storage_policy_
->IsFileHandler(extension_id
))
186 fileapi::FileSystemType type
;
188 if (!mount_points_
->CrackVirtualPath(virtual_path
, &id
, &type
, &path
) &&
189 !system_mount_points_
->CrackVirtualPath(virtual_path
,
190 &id
, &type
, &path
)) {
194 if (type
== fileapi::kFileSystemTypeRestrictedNativeLocal
) {
195 LOG(ERROR
) << "Can't grant access for restricted mount point";
199 file_access_permissions_
->GrantAccessPermission(extension_id
, virtual_path
);
202 void CrosMountPointProvider::RevokeAccessForExtension(
203 const std::string
& extension_id
) {
204 file_access_permissions_
->RevokePermissions(extension_id
);
207 std::vector
<base::FilePath
> CrosMountPointProvider::GetRootDirectories() const {
208 std::vector
<fileapi::MountPoints::MountPointInfo
> mount_points
;
209 mount_points_
->AddMountPointInfosTo(&mount_points
);
210 system_mount_points_
->AddMountPointInfosTo(&mount_points
);
212 std::vector
<base::FilePath
> root_dirs
;
213 for (size_t i
= 0; i
< mount_points
.size(); ++i
)
214 root_dirs
.push_back(mount_points
[i
].path
);
218 fileapi::FileSystemFileUtil
* CrosMountPointProvider::GetFileUtil(
219 fileapi::FileSystemType type
) {
220 DCHECK(type
== fileapi::kFileSystemTypeNativeLocal
||
221 type
== fileapi::kFileSystemTypeRestrictedNativeLocal
);
222 return local_file_util_
->sync_file_util();
225 fileapi::AsyncFileUtil
* CrosMountPointProvider::GetAsyncFileUtil(
226 fileapi::FileSystemType type
) {
227 DCHECK(type
== fileapi::kFileSystemTypeNativeLocal
||
228 type
== fileapi::kFileSystemTypeRestrictedNativeLocal
);
229 return local_file_util_
.get();
232 fileapi::CopyOrMoveFileValidatorFactory
*
233 CrosMountPointProvider::GetCopyOrMoveFileValidatorFactory(
234 fileapi::FileSystemType type
, base::PlatformFileError
* error_code
) {
236 *error_code
= base::PLATFORM_FILE_OK
;
240 void CrosMountPointProvider::InitializeCopyOrMoveFileValidatorFactory(
241 fileapi::FileSystemType type
,
242 scoped_ptr
<fileapi::CopyOrMoveFileValidatorFactory
> factory
) {
246 fileapi::FilePermissionPolicy
CrosMountPointProvider::GetPermissionPolicy(
247 const fileapi::FileSystemURL
& url
, int permissions
) const {
248 if (url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
&&
249 (permissions
& ~fileapi::kReadFilePermissions
)) {
250 // Restricted file system is read-only.
251 return fileapi::FILE_PERMISSION_ALWAYS_DENY
;
254 if (!IsAccessAllowed(url
))
255 return fileapi::FILE_PERMISSION_ALWAYS_DENY
;
257 // Permit access to mount points from internal WebUI.
258 const GURL
& origin_url
= url
.origin();
259 if (origin_url
.SchemeIs(kChromeUIScheme
))
260 return fileapi::FILE_PERMISSION_ALWAYS_ALLOW
;
262 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
) {
263 // Permissions in isolated filesystems should be examined with
264 // FileSystem permission.
265 return fileapi::FILE_PERMISSION_USE_FILESYSTEM_PERMISSION
;
268 // Also apply system's file permission by default.
269 return fileapi::FILE_PERMISSION_USE_FILE_PERMISSION
;
272 fileapi::FileSystemOperation
* CrosMountPointProvider::CreateFileSystemOperation(
273 const fileapi::FileSystemURL
& url
,
274 fileapi::FileSystemContext
* context
,
275 base::PlatformFileError
* error_code
) const {
276 DCHECK(url
.is_valid());
278 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
279 fileapi::RemoteFileSystemProxyInterface
* remote_proxy
=
280 GetRemoteProxy(url
.filesystem_id());
282 *error_code
= base::PLATFORM_FILE_ERROR_NOT_FOUND
;
285 return new chromeos::RemoteFileSystemOperation(remote_proxy
);
288 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
||
289 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
);
290 scoped_ptr
<fileapi::FileSystemOperationContext
> operation_context(
291 new fileapi::FileSystemOperationContext(context
));
292 return new fileapi::LocalFileSystemOperation(context
,
293 operation_context
.Pass());
296 scoped_ptr
<webkit_blob::FileStreamReader
>
297 CrosMountPointProvider::CreateFileStreamReader(
298 const fileapi::FileSystemURL
& url
,
300 const base::Time
& expected_modification_time
,
301 fileapi::FileSystemContext
* context
) const {
302 DCHECK(url
.is_valid());
304 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
305 fileapi::RemoteFileSystemProxyInterface
* remote_proxy
=
306 GetRemoteProxy(url
.filesystem_id());
308 return scoped_ptr
<webkit_blob::FileStreamReader
>();
309 return remote_proxy
->CreateFileStreamReader(
310 context
->task_runners()->file_task_runner(),
311 url
, offset
, expected_modification_time
);
314 return scoped_ptr
<webkit_blob::FileStreamReader
>(
315 new fileapi::FileSystemFileStreamReader(
316 context
, url
, offset
, expected_modification_time
));
319 scoped_ptr
<fileapi::FileStreamWriter
>
320 CrosMountPointProvider::CreateFileStreamWriter(
321 const fileapi::FileSystemURL
& url
,
323 fileapi::FileSystemContext
* context
) const {
324 DCHECK(url
.is_valid());
326 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
327 fileapi::RemoteFileSystemProxyInterface
* remote_proxy
=
328 GetRemoteProxy(url
.filesystem_id());
330 return scoped_ptr
<fileapi::FileStreamWriter
>();
331 return scoped_ptr
<fileapi::FileStreamWriter
>(
332 new fileapi::RemoteFileStreamWriter(remote_proxy
, url
, offset
));
335 if (url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
)
336 return scoped_ptr
<fileapi::FileStreamWriter
>();
338 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
);
339 return scoped_ptr
<fileapi::FileStreamWriter
>(
340 new fileapi::LocalFileStreamWriter(url
.path(), offset
));
343 bool CrosMountPointProvider::GetVirtualPath(
344 const base::FilePath
& filesystem_path
,
345 base::FilePath
* virtual_path
) {
346 return mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
) ||
347 system_mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
);
350 fileapi::RemoteFileSystemProxyInterface
* CrosMountPointProvider::GetRemoteProxy(
351 const std::string
& mount_name
) const {
352 fileapi::RemoteFileSystemProxyInterface
* proxy
=
353 mount_points_
->GetRemoteFileSystemProxy(mount_name
);
356 return system_mount_points_
->GetRemoteFileSystemProxy(mount_name
);
359 } // namespace chromeos