• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
CanHandleURL(const fileapi::FileSystemURL & url)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 
FileSystemBackend(FileSystemBackendDelegate * drive_delegate,scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,scoped_refptr<fileapi::ExternalMountPoints> mount_points,fileapi::ExternalMountPoints * system_mount_points)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 
~FileSystemBackend()56 FileSystemBackend::~FileSystemBackend() {
57 }
58 
AddSystemMountPoints()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       fileapi::FileSystemMountOption(),
67       chromeos::CrosDisksClient::GetArchiveMountPoint());
68   system_mount_points_->RegisterFileSystem(
69       "removable",
70       fileapi::kFileSystemTypeNativeLocal,
71       fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_SYNC),
72       chromeos::CrosDisksClient::GetRemovableDiskMountPoint());
73   system_mount_points_->RegisterFileSystem(
74       "oem",
75       fileapi::kFileSystemTypeRestrictedNativeLocal,
76       fileapi::FileSystemMountOption(),
77       base::FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
78 }
79 
CanHandleType(fileapi::FileSystemType type) const80 bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type) const {
81   switch (type) {
82     case fileapi::kFileSystemTypeExternal:
83     case fileapi::kFileSystemTypeDrive:
84     case fileapi::kFileSystemTypeRestrictedNativeLocal:
85     case fileapi::kFileSystemTypeNativeLocal:
86     case fileapi::kFileSystemTypeNativeForPlatformApp:
87       return true;
88     default:
89       return false;
90   }
91 }
92 
Initialize(fileapi::FileSystemContext * context)93 void FileSystemBackend::Initialize(fileapi::FileSystemContext* context) {
94 }
95 
OpenFileSystem(const GURL & origin_url,fileapi::FileSystemType type,fileapi::OpenFileSystemMode mode,const OpenFileSystemCallback & callback)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)
103   NOTREACHED();
104   callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY);
105 }
106 
GetQuotaUtil()107 fileapi::FileSystemQuotaUtil* FileSystemBackend::GetQuotaUtil() {
108   // No quota support.
109   return NULL;
110 }
111 
IsAccessAllowed(const fileapi::FileSystemURL & url) const112 bool FileSystemBackend::IsAccessAllowed(
113     const fileapi::FileSystemURL& url) const {
114   if (!url.is_valid())
115     return false;
116 
117   // Permit access to mount points from internal WebUI.
118   const GURL& origin_url = url.origin();
119   if (origin_url.SchemeIs(kChromeUIScheme))
120     return true;
121 
122   // No extra check is needed for isolated file systems.
123   if (url.mount_type() == fileapi::kFileSystemTypeIsolated)
124     return true;
125 
126   if (!CanHandleURL(url))
127     return false;
128 
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) {
134     return true;
135   }
136 
137   // Check first to make sure this extension has fileBrowserHander permissions.
138   if (!special_storage_policy_->IsFileHandler(extension_id))
139     return false;
140 
141   return file_access_permissions_->HasAccessPermission(extension_id,
142                                                        url.virtual_path());
143 }
144 
GrantFullAccessToExtension(const std::string & 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))
149     return;
150 
151   std::vector<fileapi::MountPoints::MountPointInfo> files;
152   mount_points_->AddMountPointInfosTo(&files);
153   system_mount_points_->AddMountPointInfosTo(&files);
154 
155   for (size_t i = 0; i < files.size(); ++i) {
156     file_access_permissions_->GrantAccessPermission(
157         extension_id,
158         base::FilePath::FromUTF8Unsafe(files[i].name));
159   }
160 }
161 
GrantFileAccessToExtension(const std::string & extension_id,const base::FilePath & virtual_path)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))
167     return;
168 
169   std::string id;
170   fileapi::FileSystemType type;
171   base::FilePath path;
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)) {
177     return;
178   }
179 
180   if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
181     LOG(ERROR) << "Can't grant access for restricted mount point";
182     return;
183   }
184 
185   file_access_permissions_->GrantAccessPermission(extension_id, virtual_path);
186 }
187 
RevokeAccessForExtension(const std::string & extension_id)188 void FileSystemBackend::RevokeAccessForExtension(
189       const std::string& extension_id) {
190   file_access_permissions_->RevokePermissions(extension_id);
191 }
192 
GetRootDirectories() const193 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);
197 
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);
201   return root_dirs;
202 }
203 
GetAsyncFileUtil(fileapi::FileSystemType type)204 fileapi::AsyncFileUtil* FileSystemBackend::GetAsyncFileUtil(
205     fileapi::FileSystemType type) {
206   if (type == fileapi::kFileSystemTypeDrive)
207     return drive_delegate_->GetAsyncFileUtil(type);
208 
209   DCHECK(type == fileapi::kFileSystemTypeNativeLocal ||
210          type == fileapi::kFileSystemTypeRestrictedNativeLocal);
211   return local_file_util_.get();
212 }
213 
214 fileapi::CopyOrMoveFileValidatorFactory*
GetCopyOrMoveFileValidatorFactory(fileapi::FileSystemType type,base::PlatformFileError * error_code)215 FileSystemBackend::GetCopyOrMoveFileValidatorFactory(
216     fileapi::FileSystemType type, base::PlatformFileError* error_code) {
217   DCHECK(error_code);
218   *error_code = base::PLATFORM_FILE_OK;
219   return NULL;
220 }
221 
CreateFileSystemOperation(const fileapi::FileSystemURL & url,fileapi::FileSystemContext * context,base::PlatformFileError * error_code) const222 fileapi::FileSystemOperation* FileSystemBackend::CreateFileSystemOperation(
223     const fileapi::FileSystemURL& url,
224     fileapi::FileSystemContext* context,
225     base::PlatformFileError* error_code) const {
226   DCHECK(url.is_valid());
227 
228   if (!IsAccessAllowed(url)) {
229     *error_code = base::PLATFORM_FILE_ERROR_SECURITY;
230     return NULL;
231   }
232 
233   DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
234          url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal ||
235          url.type() == fileapi::kFileSystemTypeDrive);
236   return fileapi::FileSystemOperation::Create(
237       url, context,
238       make_scoped_ptr(new fileapi::FileSystemOperationContext(context)));
239 }
240 
241 scoped_ptr<webkit_blob::FileStreamReader>
CreateFileStreamReader(const fileapi::FileSystemURL & url,int64 offset,const base::Time & expected_modification_time,fileapi::FileSystemContext * context) const242 FileSystemBackend::CreateFileStreamReader(
243     const fileapi::FileSystemURL& url,
244     int64 offset,
245     const base::Time& expected_modification_time,
246     fileapi::FileSystemContext* context) const {
247   DCHECK(url.is_valid());
248 
249   if (!IsAccessAllowed(url))
250     return scoped_ptr<webkit_blob::FileStreamReader>();
251 
252   if (url.type() == fileapi::kFileSystemTypeDrive) {
253     return drive_delegate_->CreateFileStreamReader(
254         url, offset, expected_modification_time, context);
255   }
256 
257   return scoped_ptr<webkit_blob::FileStreamReader>(
258       webkit_blob::FileStreamReader::CreateForFileSystemFile(
259           context, url, offset, expected_modification_time));
260 }
261 
262 scoped_ptr<fileapi::FileStreamWriter>
CreateFileStreamWriter(const fileapi::FileSystemURL & url,int64 offset,fileapi::FileSystemContext * context) const263 FileSystemBackend::CreateFileStreamWriter(
264     const fileapi::FileSystemURL& url,
265     int64 offset,
266     fileapi::FileSystemContext* context) const {
267   DCHECK(url.is_valid());
268 
269   if (!IsAccessAllowed(url))
270     return scoped_ptr<fileapi::FileStreamWriter>();
271 
272   if (url.type() == fileapi::kFileSystemTypeDrive)
273     return drive_delegate_->CreateFileStreamWriter(url, offset, context);
274 
275   if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal)
276     return scoped_ptr<fileapi::FileStreamWriter>();
277 
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));
282 }
283 
GetVirtualPath(const base::FilePath & filesystem_path,base::FilePath * virtual_path)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);
289 }
290 
291 }  // namespace chromeos
292