- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / fileapi / file_system_backend.cc
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.
4
5 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
6
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"
25
26 namespace {
27
28 const char kChromeUIScheme[] = "chrome";
29
30 }  // namespace
31
32 namespace chromeos {
33
34 // static
35 bool FileSystemBackend::CanHandleURL(const fileapi::FileSystemURL& url) {
36   if (!url.is_valid())
37     return false;
38   return url.type() == fileapi::kFileSystemTypeNativeLocal ||
39          url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
40          url.type() == fileapi::kFileSystemTypeDrive;
41 }
42
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) {
54 }
55
56 FileSystemBackend::~FileSystemBackend() {
57 }
58
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(
64       "archive",
65       fileapi::kFileSystemTypeNativeLocal,
66       chromeos::CrosDisksClient::GetArchiveMountPoint());
67   system_mount_points_->RegisterFileSystem(
68       "removable",
69       fileapi::kFileSystemTypeNativeLocal,
70       chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
71   system_mount_points_->RegisterFileSystem(
72       "oem",
73       fileapi::kFileSystemTypeRestrictedNativeLocal,
74       base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
75 }
76
77 bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type) const {
78   switch (type) {
79     case fileapi::kFileSystemTypeExternal:
80     case fileapi::kFileSystemTypeDrive:
81     case fileapi::kFileSystemTypeRestrictedNativeLocal:
82     case fileapi::kFileSystemTypeNativeLocal:
83     case fileapi::kFileSystemTypeNativeForPlatformApp:
84       return true;
85     default:
86       return false;
87   }
88 }
89
90 void FileSystemBackend::Initialize(fileapi::FileSystemContext* context) {
91 }
92
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)
100   NOTREACHED();
101   callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY);
102 }
103
104 fileapi::FileSystemQuotaUtil* FileSystemBackend::GetQuotaUtil() {
105   // No quota support.
106   return NULL;
107 }
108
109 bool FileSystemBackend::IsAccessAllowed(
110     const fileapi::FileSystemURL& url) const {
111   if (!url.is_valid())
112     return false;
113
114   // Permit access to mount points from internal WebUI.
115   const GURL& origin_url = url.origin();
116   if (origin_url.SchemeIs(kChromeUIScheme))
117     return true;
118
119   // No extra check is needed for isolated file systems.
120   if (url.mount_type() == fileapi::kFileSystemTypeIsolated)
121     return true;
122
123   if (!CanHandleURL(url))
124     return false;
125
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) {
131     return true;
132   }
133
134   // Check first to make sure this extension has fileBrowserHander permissions.
135   if (!special_storage_policy_->IsFileHandler(extension_id))
136     return false;
137
138   return file_access_permissions_->HasAccessPermission(extension_id,
139                                                        url.virtual_path());
140 }
141
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))
146     return;
147
148   std::vector<fileapi::MountPoints::MountPointInfo> files;
149   mount_points_->AddMountPointInfosTo(&files);
150   system_mount_points_->AddMountPointInfosTo(&files);
151
152   for (size_t i = 0; i < files.size(); ++i) {
153     file_access_permissions_->GrantAccessPermission(
154         extension_id,
155         base::FilePath::FromUTF8Unsafe(files[i].name));
156   }
157 }
158
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))
164     return;
165
166   std::string id;
167   fileapi::FileSystemType type;
168   base::FilePath path;
169   if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &path) &&
170       !system_mount_points_->CrackVirtualPath(virtual_path,
171                                               &id, &type, &path)) {
172     return;
173   }
174
175   if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
176     LOG(ERROR) << "Can't grant access for restricted mount point";
177     return;
178   }
179
180   file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
181 }
182
183 void FileSystemBackend::RevokeAccessForExtension(
184       const std::string& extension_id) {
185   file_access_permissions_->RevokePermissions(extension_id);
186 }
187
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);
192
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);
196   return root_dirs;
197 }
198
199 fileapi::AsyncFileUtil* FileSystemBackend::GetAsyncFileUtil(
200     fileapi::FileSystemType type) {
201   if (type == fileapi::kFileSystemTypeDrive)
202     return drive_delegate_->GetAsyncFileUtil(type);
203
204   DCHECK(type == fileapi::kFileSystemTypeNativeLocal ||
205          type == fileapi::kFileSystemTypeRestrictedNativeLocal);
206   return local_file_util_.get();
207 }
208
209 fileapi::CopyOrMoveFileValidatorFactory*
210 FileSystemBackend::GetCopyOrMoveFileValidatorFactory(
211     fileapi::FileSystemType type, base::PlatformFileError* error_code) {
212   DCHECK(error_code);
213   *error_code = base::PLATFORM_FILE_OK;
214   return NULL;
215 }
216
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());
222
223   if (!IsAccessAllowed(url)) {
224     *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
225     return NULL;
226   }
227
228   DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
229          url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
230          url.type() == fileapi::kFileSystemTypeDrive);
231   return fileapi::FileSystemOperation::Create(
232       url, context,
233       make_scoped_ptr(new fileapi::FileSystemOperationContext(context)));
234 }
235
236 scoped_ptr<webkit_blob::FileStreamReader>
237 FileSystemBackend::CreateFileStreamReader(
238     const fileapi::FileSystemURL& url,
239     int64 offset,
240     const base::Time& expected_modification_time,
241     fileapi::FileSystemContext* context) const {
242   DCHECK(url.is_valid());
243
244   if (!IsAccessAllowed(url))
245     return scoped_ptr<webkit_blob::FileStreamReader>();
246
247   if (url.type() == fileapi::kFileSystemTypeDrive) {
248     return drive_delegate_->CreateFileStreamReader(
249         url, offset, expected_modification_time, context);
250   }
251
252   return scoped_ptr<webkit_blob::FileStreamReader>(
253       webkit_blob::FileStreamReader::CreateForFileSystemFile(
254           context, url, offset, expected_modification_time));
255 }
256
257 scoped_ptr<fileapi::FileStreamWriter>
258 FileSystemBackend::CreateFileStreamWriter(
259     const fileapi::FileSystemURL& url,
260     int64 offset,
261     fileapi::FileSystemContext* context) const {
262   DCHECK(url.is_valid());
263
264   if (!IsAccessAllowed(url))
265     return scoped_ptr<fileapi::FileStreamWriter>();
266
267   if (url.type() == fileapi::kFileSystemTypeDrive)
268     return drive_delegate_->CreateFileStreamWriter(url, offset, context);
269
270   if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal)
271     return scoped_ptr<fileapi::FileStreamWriter>();
272
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));
277 }
278
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);
284 }
285
286 }  // namespace chromeos