Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: chrome/browser/extensions/api/file_handlers/app_file_handler_util.cc

Issue 2666763005: API delegate for non-native file systems (Closed)
Patch Set: rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" 5 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
6 6
7 #include "base/files/file.h" 7 #include "base/files/file.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "build/build_config.h" 10 #include "build/build_config.h"
11 #include "chrome/browser/profiles/profile.h"
11 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/child_process_security_policy.h" 13 #include "content/public/browser/child_process_security_policy.h"
14 #include "extensions/browser/api/extensions_api_client.h"
13 #include "extensions/browser/entry_info.h" 15 #include "extensions/browser/entry_info.h"
14 #include "extensions/browser/extension_prefs.h" 16 #include "extensions/browser/extension_prefs.h"
15 #include "extensions/browser/granted_file_entry.h" 17 #include "extensions/browser/granted_file_entry.h"
16 #include "extensions/common/permissions/permissions_data.h" 18 #include "extensions/common/permissions/permissions_data.h"
17 #include "net/base/mime_util.h" 19 #include "net/base/mime_util.h"
18 #include "storage/browser/fileapi/isolated_context.h" 20 #include "storage/browser/fileapi/isolated_context.h"
19 #include "storage/common/fileapi/file_system_mount_option.h" 21 #include "storage/common/fileapi/file_system_mount_option.h"
20 #include "storage/common/fileapi/file_system_types.h" 22 #include "storage/common/fileapi/file_system_types.h"
21 23
22 #if defined(OS_CHROMEOS) 24 #if defined(OS_CHROMEOS)
23 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" 25 #include "extensions/browser/api/file_handlers/non_native_file_system_delegate.h "
24 #endif 26 #endif
25 27
26 namespace extensions { 28 namespace extensions {
27 29
28 namespace app_file_handler_util { 30 namespace app_file_handler_util {
29 31
30 const char kInvalidParameters[] = "Invalid parameters"; 32 const char kInvalidParameters[] = "Invalid parameters";
31 const char kSecurityError[] = "Security error"; 33 const char kSecurityError[] = "Security error";
32 34
33 namespace { 35 namespace {
34 36
35 bool FileHandlerCanHandleFileWithExtension( 37 bool FileHandlerCanHandleFileWithExtension(const FileHandlerInfo& handler,
36 const FileHandlerInfo& handler, 38 const base::FilePath& path) {
37 const base::FilePath& path) {
38 for (std::set<std::string>::const_iterator extension = 39 for (std::set<std::string>::const_iterator extension =
39 handler.extensions.begin(); 40 handler.extensions.begin();
40 extension != handler.extensions.end(); ++extension) { 41 extension != handler.extensions.end(); ++extension) {
41 if (*extension == "*") 42 if (*extension == "*")
42 return true; 43 return true;
43 44
44 // Accept files whose extension or combined extension (e.g. ".tar.gz") 45 // Accept files whose extension or combined extension (e.g. ".tar.gz")
45 // match the supported extensions of file handler. 46 // match the supported extensions of file handler.
46 base::FilePath::StringType handler_extention( 47 base::FilePath::StringType handler_extention(
47 base::FilePath::kExtensionSeparator + 48 base::FilePath::kExtensionSeparator +
48 base::FilePath::FromUTF8Unsafe(*extension).value()); 49 base::FilePath::FromUTF8Unsafe(*extension).value());
49 if (base::FilePath::CompareEqualIgnoreCase( 50 if (base::FilePath::CompareEqualIgnoreCase(handler_extention,
50 handler_extention, path.Extension()) || 51 path.Extension()) ||
51 base::FilePath::CompareEqualIgnoreCase( 52 base::FilePath::CompareEqualIgnoreCase(handler_extention,
52 handler_extention, path.FinalExtension())) { 53 path.FinalExtension())) {
53 return true; 54 return true;
54 } 55 }
55 56
56 // Also accept files with no extension for handlers that support an 57 // Also accept files with no extension for handlers that support an
57 // empty extension, i.e. both "foo" and "foo." match. 58 // empty extension, i.e. both "foo" and "foo." match.
58 if (extension->empty() && 59 if (extension->empty() &&
59 path.MatchesExtension(base::FilePath::StringType())) { 60 path.MatchesExtension(base::FilePath::StringType())) {
60 return true; 61 return true;
61 } 62 }
62 } 63 }
63 return false; 64 return false;
64 } 65 }
65 66
66 bool FileHandlerCanHandleFileWithMimeType( 67 bool FileHandlerCanHandleFileWithMimeType(const FileHandlerInfo& handler,
67 const FileHandlerInfo& handler, 68 const std::string& mime_type) {
68 const std::string& mime_type) {
69 for (std::set<std::string>::const_iterator type = handler.types.begin(); 69 for (std::set<std::string>::const_iterator type = handler.types.begin();
70 type != handler.types.end(); ++type) { 70 type != handler.types.end(); ++type) {
71 if (net::MatchesMimeType(*type, mime_type)) 71 if (net::MatchesMimeType(*type, mime_type))
72 return true; 72 return true;
73 } 73 }
74 return false; 74 return false;
75 } 75 }
76 76
77 bool PrepareNativeLocalFileForWritableApp(const base::FilePath& path, 77 bool PrepareNativeLocalFileForWritableApp(const base::FilePath& path,
78 bool is_directory) { 78 bool is_directory) {
79 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); 79 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
80 80
81 // Don't allow links. 81 // Don't allow links.
82 if (base::PathExists(path) && base::IsLink(path)) 82 if (base::PathExists(path) && base::IsLink(path))
83 return false; 83 return false;
84 84
85 if (is_directory) 85 if (is_directory)
86 return base::DirectoryExists(path); 86 return base::DirectoryExists(path);
87 87
88 // Create the file if it doesn't already exist. 88 // Create the file if it doesn't already exist.
89 int creation_flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ; 89 int creation_flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ;
90 base::File file(path, creation_flags); 90 base::File file(path, creation_flags);
91 91
92 return file.IsValid(); 92 return file.IsValid();
93 } 93 }
94 94
95 // Checks whether a list of paths are all OK for writing and calls a provided 95 // Checks whether a list of paths are all OK for writing and calls a provided
96 // on_success or on_failure callback when done. A file is OK for writing if it 96 // on_success or on_failure callback when done. A path is OK for writing if it
97 // is not a symlink, is not in a blacklisted path and can be opened for writing; 97 // is not a symlink, is not in a blacklisted path and can be opened for writing.
98 // files are created if they do not exist. 98 // Creates files if they do not exist, but fails for non-existent directory
99 // paths. On Chrome OS, also fails for non-local files that don't already exist.
99 class WritableFileChecker 100 class WritableFileChecker
100 : public base::RefCountedThreadSafe<WritableFileChecker> { 101 : public base::RefCountedThreadSafe<WritableFileChecker> {
101 public: 102 public:
102 WritableFileChecker( 103 WritableFileChecker(
103 const std::vector<base::FilePath>& paths, 104 const std::vector<base::FilePath>& paths,
104 Profile* profile, 105 Profile* profile,
105 const std::set<base::FilePath>& directory_paths, 106 const std::set<base::FilePath>& directory_paths,
106 const base::Closure& on_success, 107 const base::Closure& on_success,
107 const base::Callback<void(const base::FilePath&)>& on_failure); 108 const base::Callback<void(const base::FilePath&)>& on_failure);
108 109
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 const base::Closure& on_success, 143 const base::Closure& on_success,
143 const base::Callback<void(const base::FilePath&)>& on_failure) 144 const base::Callback<void(const base::FilePath&)>& on_failure)
144 : paths_(paths), 145 : paths_(paths),
145 profile_(profile), 146 profile_(profile),
146 directory_paths_(directory_paths), 147 directory_paths_(directory_paths),
147 outstanding_tasks_(1), 148 outstanding_tasks_(1),
148 on_success_(on_success), 149 on_success_(on_success),
149 on_failure_(on_failure) {} 150 on_failure_(on_failure) {}
150 151
151 void WritableFileChecker::Check() { 152 void WritableFileChecker::Check() {
152 outstanding_tasks_ = paths_.size(); 153 outstanding_tasks_ = paths_.size();
153 for (const auto& path : paths_) { 154 for (const auto& path : paths_) {
154 bool is_directory = directory_paths_.find(path) != directory_paths_.end(); 155 bool is_directory = directory_paths_.find(path) != directory_paths_.end();
155 #if defined(OS_CHROMEOS) 156 #if defined(OS_CHROMEOS)
156 if (file_manager::util::IsUnderNonNativeLocalPath(profile_, path)) { 157 NonNativeFileSystemDelegate* delegate =
157 if (is_directory) { 158 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
158 file_manager::util::IsNonNativeLocalPathDirectory( 159 if (delegate && delegate->IsUnderNonNativeLocalPath(profile_, path)) {
159 profile_, path, 160 if (is_directory) {
160 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path)); 161 delegate->IsNonNativeLocalPathDirectory(
161 } else { 162 profile_,
162 file_manager::util::PrepareNonNativeLocalFileForWritableApp( 163 path,
163 profile_, path, 164 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
164 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path)); 165 } else {
165 } 166 delegate->PrepareNonNativeLocalFileForWritableApp(
166 continue; 167 profile_,
168 path,
169 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
167 } 170 }
171 continue;
172 }
168 #endif 173 #endif
169 content::BrowserThread::PostTaskAndReplyWithResult( 174 content::BrowserThread::PostTaskAndReplyWithResult(
170 content::BrowserThread::FILE, FROM_HERE, 175 content::BrowserThread::FILE, FROM_HERE,
171 base::Bind(&PrepareNativeLocalFileForWritableApp, path, is_directory), 176 base::Bind(&PrepareNativeLocalFileForWritableApp, path, is_directory),
172 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path)); 177 base::Bind(&WritableFileChecker::OnPrepareFileDone, this, path));
173 } 178 }
174 } 179 }
175 180
176 WritableFileChecker::~WritableFileChecker() {} 181 WritableFileChecker::~WritableFileChecker() {}
177 182
178 void WritableFileChecker::TaskDone() { 183 void WritableFileChecker::TaskDone() {
179 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 184 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
180 if (--outstanding_tasks_ == 0) { 185 if (--outstanding_tasks_ == 0) {
181 if (error_path_.empty()) 186 if (error_path_.empty())
182 on_success_.Run(); 187 on_success_.Run();
183 else 188 else
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 252
248 bool FileHandlerCanHandleEntry(const FileHandlerInfo& handler, 253 bool FileHandlerCanHandleEntry(const FileHandlerInfo& handler,
249 const EntryInfo& entry) { 254 const EntryInfo& entry) {
250 if (entry.is_directory) 255 if (entry.is_directory)
251 return handler.include_directories; 256 return handler.include_directories;
252 257
253 return FileHandlerCanHandleFileWithMimeType(handler, entry.mime_type) || 258 return FileHandlerCanHandleFileWithMimeType(handler, entry.mime_type) ||
254 FileHandlerCanHandleFileWithExtension(handler, entry.path); 259 FileHandlerCanHandleFileWithExtension(handler, entry.path);
255 } 260 }
256 261
257 GrantedFileEntry CreateFileEntry( 262 GrantedFileEntry CreateFileEntry(Profile* profile,
258 Profile* profile, 263 const Extension* extension,
259 const Extension* extension, 264 int renderer_id,
260 int renderer_id, 265 const base::FilePath& path,
261 const base::FilePath& path, 266 bool is_directory) {
262 bool is_directory) {
263 GrantedFileEntry result; 267 GrantedFileEntry result;
264 storage::IsolatedContext* isolated_context = 268 storage::IsolatedContext* isolated_context =
265 storage::IsolatedContext::GetInstance(); 269 storage::IsolatedContext::GetInstance();
266 DCHECK(isolated_context); 270 DCHECK(isolated_context);
267 271
268 result.filesystem_id = isolated_context->RegisterFileSystemForPath( 272 result.filesystem_id = isolated_context->RegisterFileSystemForPath(
269 storage::kFileSystemTypeNativeForPlatformApp, 273 storage::kFileSystemTypeNativeForPlatformApp, std::string(), path,
270 std::string(),
271 path,
272 &result.registered_name); 274 &result.registered_name);
273 275
274 content::ChildProcessSecurityPolicy* policy = 276 content::ChildProcessSecurityPolicy* policy =
275 content::ChildProcessSecurityPolicy::GetInstance(); 277 content::ChildProcessSecurityPolicy::GetInstance();
276 policy->GrantReadFileSystem(renderer_id, result.filesystem_id); 278 policy->GrantReadFileSystem(renderer_id, result.filesystem_id);
277 if (HasFileSystemWritePermission(extension)) { 279 if (HasFileSystemWritePermission(extension)) {
278 if (is_directory) { 280 if (is_directory) {
279 policy->GrantCreateReadWriteFileSystem(renderer_id, result.filesystem_id); 281 policy->GrantCreateReadWriteFileSystem(renderer_id, result.filesystem_id);
280 } else { 282 } else {
281 policy->GrantWriteFileSystem(renderer_id, result.filesystem_id); 283 policy->GrantWriteFileSystem(renderer_id, result.filesystem_id);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 content::ChildProcessSecurityPolicy* policy = 326 content::ChildProcessSecurityPolicy* policy =
325 content::ChildProcessSecurityPolicy::GetInstance(); 327 content::ChildProcessSecurityPolicy::GetInstance();
326 if (!policy->CanReadFileSystem(render_process_id, filesystem_id)) { 328 if (!policy->CanReadFileSystem(render_process_id, filesystem_id)) {
327 *error = kSecurityError; 329 *error = kSecurityError;
328 return false; 330 return false;
329 } 331 }
330 332
331 storage::IsolatedContext* context = storage::IsolatedContext::GetInstance(); 333 storage::IsolatedContext* context = storage::IsolatedContext::GetInstance();
332 base::FilePath relative_path = 334 base::FilePath relative_path =
333 base::FilePath::FromUTF8Unsafe(filesystem_path); 335 base::FilePath::FromUTF8Unsafe(filesystem_path);
334 base::FilePath virtual_path = context->CreateVirtualRootPath(filesystem_id) 336 base::FilePath virtual_path =
335 .Append(relative_path); 337 context->CreateVirtualRootPath(filesystem_id).Append(relative_path);
336 storage::FileSystemType type; 338 storage::FileSystemType type;
337 storage::FileSystemMountOption mount_option; 339 storage::FileSystemMountOption mount_option;
338 std::string cracked_id; 340 std::string cracked_id;
339 if (!context->CrackVirtualPath( 341 if (!context->CrackVirtualPath(virtual_path, &filesystem_id, &type,
340 virtual_path, &filesystem_id, &type, &cracked_id, file_path, 342 &cracked_id, file_path, &mount_option)) {
341 &mount_option)) {
342 *error = kInvalidParameters; 343 *error = kInvalidParameters;
343 return false; 344 return false;
344 } 345 }
345 346
346 // The file system API is only intended to operate on file entries that 347 // The file system API is only intended to operate on file entries that
347 // correspond to a native file, selected by the user so only allow file 348 // correspond to a native file, selected by the user so only allow file
348 // systems returned by the file system API or from a drag and drop operation. 349 // systems returned by the file system API or from a drag and drop operation.
349 if (type != storage::kFileSystemTypeNativeForPlatformApp && 350 if (type != storage::kFileSystemTypeNativeForPlatformApp &&
350 type != storage::kFileSystemTypeDragged) { 351 type != storage::kFileSystemTypeDragged) {
351 *error = kInvalidParameters; 352 *error = kInvalidParameters;
352 return false; 353 return false;
353 } 354 }
354 355
355 return true; 356 return true;
356 } 357 }
357 358
358 } // namespace app_file_handler_util 359 } // namespace app_file_handler_util
359 360
360 } // namespace extensions 361 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698