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 "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.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/copy_or_move_file_validator.h"
24 #include "webkit/fileapi/external_mount_points.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_url.h"
28 #include "webkit/fileapi/file_system_util.h"
29 #include "webkit/fileapi/isolated_context.h"
30 #include "webkit/fileapi/isolated_file_util.h"
31 #include "webkit/fileapi/local_file_stream_writer.h"
32 #include "webkit/fileapi/local_file_system_operation.h"
33 #include "webkit/glue/webkit_glue.h"
37 const char kChromeUIScheme
[] = "chrome";
44 bool CrosMountPointProvider::CanHandleURL(const fileapi::FileSystemURL
& url
) {
47 return url
.type() == fileapi::kFileSystemTypeNativeLocal
||
48 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
||
49 url
.type() == fileapi::kFileSystemTypeDrive
;
52 CrosMountPointProvider::CrosMountPointProvider(
53 scoped_refptr
<quota::SpecialStoragePolicy
> special_storage_policy
,
54 scoped_refptr
<fileapi::ExternalMountPoints
> mount_points
,
55 fileapi::ExternalMountPoints
* system_mount_points
)
56 : special_storage_policy_(special_storage_policy
),
57 file_access_permissions_(new FileAccessPermissions()),
58 local_file_util_(new fileapi::AsyncFileUtilAdapter(
59 new fileapi::IsolatedFileUtil())),
60 mount_points_(mount_points
),
61 system_mount_points_(system_mount_points
) {
62 // Add default system mount points.
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 CrosMountPointProvider::~CrosMountPointProvider() {
80 void CrosMountPointProvider::ValidateFileSystemRoot(
81 const GURL
& origin_url
,
82 fileapi::FileSystemType type
,
84 const ValidateFileSystemCallback
& callback
) {
85 DCHECK(fileapi::IsolatedContext::IsIsolatedType(type
));
86 // Nothing to validate for external filesystem.
87 callback
.Run(base::PLATFORM_FILE_OK
);
90 base::FilePath
CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
91 const fileapi::FileSystemURL
& url
,
93 DCHECK(fileapi::IsolatedContext::IsIsolatedType(url
.mount_type()));
95 return base::FilePath();
97 base::FilePath root_path
;
98 std::string mount_name
= url
.filesystem_id();
99 if (!mount_points_
->GetRegisteredPath(mount_name
, &root_path
) &&
100 !system_mount_points_
->GetRegisteredPath(mount_name
, &root_path
)) {
101 return base::FilePath();
104 return root_path
.DirName();
107 fileapi::FileSystemQuotaUtil
* CrosMountPointProvider::GetQuotaUtil() {
112 void CrosMountPointProvider::DeleteFileSystem(
113 const GURL
& origin_url
,
114 fileapi::FileSystemType type
,
115 fileapi::FileSystemContext
* context
,
116 const DeleteFileSystemCallback
& callback
) {
118 callback
.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION
);
121 bool CrosMountPointProvider::IsAccessAllowed(
122 const fileapi::FileSystemURL
& url
) const {
126 // Permit access to mount points from internal WebUI.
127 const GURL
& origin_url
= url
.origin();
128 if (origin_url
.SchemeIs(kChromeUIScheme
))
131 // No extra check is needed for isolated file systems.
132 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
)
135 if (!CanHandleURL(url
))
138 std::string extension_id
= origin_url
.host();
139 // Check first to make sure this extension has fileBrowserHander permissions.
140 if (!special_storage_policy_
->IsFileHandler(extension_id
))
143 return file_access_permissions_
->HasAccessPermission(extension_id
,
147 void CrosMountPointProvider::GrantFullAccessToExtension(
148 const std::string
& extension_id
) {
149 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
150 if (!special_storage_policy_
->IsFileHandler(extension_id
))
153 std::vector
<fileapi::MountPoints::MountPointInfo
> files
;
154 mount_points_
->AddMountPointInfosTo(&files
);
155 system_mount_points_
->AddMountPointInfosTo(&files
);
157 for (size_t i
= 0; i
< files
.size(); ++i
) {
158 file_access_permissions_
->GrantAccessPermission(
160 base::FilePath::FromUTF8Unsafe(files
[i
].name
));
164 void CrosMountPointProvider::GrantFileAccessToExtension(
165 const std::string
& extension_id
, const base::FilePath
& virtual_path
) {
166 // All we care about here is access from extensions for now.
167 DCHECK(special_storage_policy_
->IsFileHandler(extension_id
));
168 if (!special_storage_policy_
->IsFileHandler(extension_id
))
172 fileapi::FileSystemType type
;
174 if (!mount_points_
->CrackVirtualPath(virtual_path
, &id
, &type
, &path
) &&
175 !system_mount_points_
->CrackVirtualPath(virtual_path
,
176 &id
, &type
, &path
)) {
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 CrosMountPointProvider::RevokeAccessForExtension(
189 const std::string
& extension_id
) {
190 file_access_permissions_
->RevokePermissions(extension_id
);
193 std::vector
<base::FilePath
> CrosMountPointProvider::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::FileSystemFileUtil
* CrosMountPointProvider::GetFileUtil(
205 fileapi::FileSystemType type
) {
206 DCHECK(type
== fileapi::kFileSystemTypeNativeLocal
||
207 type
== fileapi::kFileSystemTypeRestrictedNativeLocal
);
208 return local_file_util_
->sync_file_util();
211 fileapi::AsyncFileUtil
* CrosMountPointProvider::GetAsyncFileUtil(
212 fileapi::FileSystemType type
) {
213 DCHECK(type
== fileapi::kFileSystemTypeNativeLocal
||
214 type
== fileapi::kFileSystemTypeRestrictedNativeLocal
);
215 return local_file_util_
.get();
218 fileapi::CopyOrMoveFileValidatorFactory
*
219 CrosMountPointProvider::GetCopyOrMoveFileValidatorFactory(
220 fileapi::FileSystemType type
, base::PlatformFileError
* error_code
) {
222 *error_code
= base::PLATFORM_FILE_OK
;
226 void CrosMountPointProvider::InitializeCopyOrMoveFileValidatorFactory(
227 fileapi::FileSystemType type
,
228 scoped_ptr
<fileapi::CopyOrMoveFileValidatorFactory
> factory
) {
232 fileapi::FilePermissionPolicy
CrosMountPointProvider::GetPermissionPolicy(
233 const fileapi::FileSystemURL
& url
, int permissions
) const {
234 if (url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
&&
235 (permissions
& ~fileapi::kReadFilePermissions
)) {
236 // Restricted file system is read-only.
237 return fileapi::FILE_PERMISSION_ALWAYS_DENY
;
240 if (!IsAccessAllowed(url
))
241 return fileapi::FILE_PERMISSION_ALWAYS_DENY
;
243 // Permit access to mount points from internal WebUI.
244 const GURL
& origin_url
= url
.origin();
245 if (origin_url
.SchemeIs(kChromeUIScheme
))
246 return fileapi::FILE_PERMISSION_ALWAYS_ALLOW
;
248 if (url
.mount_type() == fileapi::kFileSystemTypeIsolated
) {
249 // Permissions in isolated filesystems should be examined with
250 // FileSystem permission.
251 return fileapi::FILE_PERMISSION_USE_FILESYSTEM_PERMISSION
;
254 // Also apply system's file permission by default.
255 return fileapi::FILE_PERMISSION_USE_FILE_PERMISSION
;
258 fileapi::FileSystemOperation
* CrosMountPointProvider::CreateFileSystemOperation(
259 const fileapi::FileSystemURL
& url
,
260 fileapi::FileSystemContext
* context
,
261 base::PlatformFileError
* error_code
) const {
262 DCHECK(url
.is_valid());
264 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
265 fileapi::RemoteFileSystemProxyInterface
* remote_proxy
=
266 GetRemoteProxy(url
.filesystem_id());
268 *error_code
= base::PLATFORM_FILE_ERROR_NOT_FOUND
;
271 return new chromeos::RemoteFileSystemOperation(remote_proxy
);
274 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
||
275 url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
);
276 scoped_ptr
<fileapi::FileSystemOperationContext
> operation_context(
277 new fileapi::FileSystemOperationContext(context
));
278 return new fileapi::LocalFileSystemOperation(context
,
279 operation_context
.Pass());
282 scoped_ptr
<webkit_blob::FileStreamReader
>
283 CrosMountPointProvider::CreateFileStreamReader(
284 const fileapi::FileSystemURL
& url
,
286 const base::Time
& expected_modification_time
,
287 fileapi::FileSystemContext
* context
) const {
288 // For now we return a generic Reader implementation which utilizes
289 // CreateSnapshotFile internally (i.e. will download everything first).
290 // TODO(satorux,zel): implement more efficient reader for remote cases.
291 return scoped_ptr
<webkit_blob::FileStreamReader
>(
292 new fileapi::FileSystemFileStreamReader(
293 context
, url
, offset
, expected_modification_time
));
296 scoped_ptr
<fileapi::FileStreamWriter
>
297 CrosMountPointProvider::CreateFileStreamWriter(
298 const fileapi::FileSystemURL
& url
,
300 fileapi::FileSystemContext
* context
) const {
301 DCHECK(url
.is_valid());
303 if (url
.type() == fileapi::kFileSystemTypeDrive
) {
304 fileapi::RemoteFileSystemProxyInterface
* remote_proxy
=
305 GetRemoteProxy(url
.filesystem_id());
307 return scoped_ptr
<fileapi::FileStreamWriter
>();
308 return scoped_ptr
<fileapi::FileStreamWriter
>(
309 new fileapi::RemoteFileStreamWriter(remote_proxy
, url
, offset
));
312 if (url
.type() == fileapi::kFileSystemTypeRestrictedNativeLocal
)
313 return scoped_ptr
<fileapi::FileStreamWriter
>();
315 DCHECK(url
.type() == fileapi::kFileSystemTypeNativeLocal
);
316 return scoped_ptr
<fileapi::FileStreamWriter
>(
317 new fileapi::LocalFileStreamWriter(url
.path(), offset
));
320 bool CrosMountPointProvider::GetVirtualPath(
321 const base::FilePath
& filesystem_path
,
322 base::FilePath
* virtual_path
) {
323 return mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
) ||
324 system_mount_points_
->GetVirtualPath(filesystem_path
, virtual_path
);
327 fileapi::RemoteFileSystemProxyInterface
* CrosMountPointProvider::GetRemoteProxy(
328 const std::string
& mount_name
) const {
329 fileapi::RemoteFileSystemProxyInterface
* proxy
=
330 mount_points_
->GetRemoteFileSystemProxy(mount_name
);
333 return system_mount_points_
->GetRemoteFileSystemProxy(mount_name
);
336 } // namespace chromeos