Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "chrome/browser/extensions/extension_prefs.h" | 9 #include "chrome/browser/extensions/extension_prefs.h" |
| 10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 const FileHandlerInfo& handler, | 52 const FileHandlerInfo& handler, |
| 53 const std::string& mime_type) { | 53 const std::string& mime_type) { |
| 54 for (std::set<std::string>::const_iterator type = handler.types.begin(); | 54 for (std::set<std::string>::const_iterator type = handler.types.begin(); |
| 55 type != handler.types.end(); ++type) { | 55 type != handler.types.end(); ++type) { |
| 56 if (net::MatchesMimeType(*type, mime_type)) | 56 if (net::MatchesMimeType(*type, mime_type)) |
| 57 return true; | 57 return true; |
| 58 } | 58 } |
| 59 return false; | 59 return false; |
| 60 } | 60 } |
| 61 | 61 |
| 62 bool DoCheckWritableFile(const base::FilePath& path) { | 62 bool DoCheckWritableFile(const base::FilePath& path, bool is_directory) { |
| 63 // Don't allow links. | 63 // Don't allow links. |
| 64 if (base::PathExists(path) && file_util::IsLink(path)) | 64 if (base::PathExists(path) && file_util::IsLink(path)) |
| 65 return false; | 65 return false; |
| 66 | 66 |
| 67 if (is_directory) | |
| 68 // CreateDirectory returns true if the directory already exists. | |
| 69 return file_util::CreateDirectory(path); | |
|
benwells
2013/08/29 00:04:24
I'm not sure about this. Can we return file_util::
Sam McNally
2013/08/29 00:16:08
Done.
| |
| 70 | |
| 67 // Create the file if it doesn't already exist. | 71 // Create the file if it doesn't already exist. |
| 68 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 72 base::PlatformFileError error = base::PLATFORM_FILE_OK; |
| 69 int creation_flags = base::PLATFORM_FILE_CREATE | | 73 int creation_flags = base::PLATFORM_FILE_CREATE | |
| 70 base::PLATFORM_FILE_READ | | 74 base::PLATFORM_FILE_READ | |
| 71 base::PLATFORM_FILE_WRITE; | 75 base::PLATFORM_FILE_WRITE; |
| 72 base::PlatformFile file = base::CreatePlatformFile(path, creation_flags, | 76 base::PlatformFile file = base::CreatePlatformFile(path, creation_flags, |
| 73 NULL, &error); | 77 NULL, &error); |
| 74 // Close the file so we don't keep a lock open. | 78 // Close the file so we don't keep a lock open. |
| 75 if (file != base::kInvalidPlatformFileValue) | 79 if (file != base::kInvalidPlatformFileValue) |
| 76 base::ClosePlatformFile(file); | 80 base::ClosePlatformFile(file); |
| 77 if (error != base::PLATFORM_FILE_OK && | 81 if (error != base::PLATFORM_FILE_OK && |
| 78 error != base::PLATFORM_FILE_ERROR_EXISTS) { | 82 error != base::PLATFORM_FILE_ERROR_EXISTS) { |
| 79 return false; | 83 return false; |
| 80 } | 84 } |
| 81 | 85 |
| 82 return true; | 86 return true; |
| 83 } | 87 } |
| 84 | 88 |
| 85 // Checks whether a list of paths are all OK for writing and calls a provided | 89 // Checks whether a list of paths are all OK for writing and calls a provided |
| 86 // on_success or on_failure callback when done. A file is OK for writing if it | 90 // on_success or on_failure callback when done. A file is OK for writing if it |
| 87 // is not a symlink, is not in a blacklisted path and can be opened for writing; | 91 // is not a symlink, is not in a blacklisted path and can be opened for writing; |
| 88 // files are created if they do not exist. | 92 // files are created if they do not exist. |
| 89 class WritableFileChecker | 93 class WritableFileChecker |
| 90 : public base::RefCountedThreadSafe<WritableFileChecker> { | 94 : public base::RefCountedThreadSafe<WritableFileChecker> { |
| 91 public: | 95 public: |
| 92 WritableFileChecker( | 96 WritableFileChecker( |
| 93 const std::vector<base::FilePath>& paths, | 97 const std::vector<base::FilePath>& paths, |
| 94 Profile* profile, | 98 Profile* profile, |
| 99 bool is_directory, | |
| 95 const base::Closure& on_success, | 100 const base::Closure& on_success, |
| 96 const base::Callback<void(const base::FilePath&)>& on_failure); | 101 const base::Callback<void(const base::FilePath&)>& on_failure); |
| 97 | 102 |
| 98 void Check(); | 103 void Check(); |
| 99 | 104 |
| 100 private: | 105 private: |
| 101 friend class base::RefCountedThreadSafe<WritableFileChecker>; | 106 friend class base::RefCountedThreadSafe<WritableFileChecker>; |
| 102 virtual ~WritableFileChecker(); | 107 virtual ~WritableFileChecker(); |
| 103 | 108 |
| 104 // Called when a work item is completed. If all work items are done, this | 109 // Called when a work item is completed. If all work items are done, this |
| 105 // calls the success or failure callback. | 110 // calls the success or failure callback. |
| 106 void TaskDone(); | 111 void TaskDone(); |
| 107 | 112 |
| 108 // Reports an error in completing a work item. This may be called more than | 113 // Reports an error in completing a work item. This may be called more than |
| 109 // once, but only the last message will be retained. | 114 // once, but only the last message will be retained. |
| 110 void Error(const base::FilePath& error_path); | 115 void Error(const base::FilePath& error_path); |
| 111 | 116 |
| 112 void CheckLocalWritableFiles(); | 117 void CheckLocalWritableFiles(); |
| 113 | 118 |
| 114 #if defined(OS_CHROMEOS) | 119 #if defined(OS_CHROMEOS) |
| 115 void CheckRemoteWritableFile(const base::FilePath& remote_path, | 120 void CheckRemoteWritableFile(const base::FilePath& remote_path, |
| 116 drive::FileError error, | 121 drive::FileError error, |
| 117 const base::FilePath& local_path); | 122 const base::FilePath& local_path); |
| 118 #endif | 123 #endif |
| 119 | 124 |
| 120 const std::vector<base::FilePath> paths_; | 125 const std::vector<base::FilePath> paths_; |
| 121 Profile* profile_; | 126 Profile* profile_; |
| 127 const bool is_directory_; | |
| 122 int outstanding_tasks_; | 128 int outstanding_tasks_; |
| 123 base::FilePath error_path_; | 129 base::FilePath error_path_; |
| 124 base::Closure on_success_; | 130 base::Closure on_success_; |
| 125 base::Callback<void(const base::FilePath&)> on_failure_; | 131 base::Callback<void(const base::FilePath&)> on_failure_; |
| 126 }; | 132 }; |
| 127 | 133 |
| 128 WritableFileChecker::WritableFileChecker( | 134 WritableFileChecker::WritableFileChecker( |
| 129 const std::vector<base::FilePath>& paths, | 135 const std::vector<base::FilePath>& paths, |
| 130 Profile* profile, | 136 Profile* profile, |
| 137 bool is_directory, | |
| 131 const base::Closure& on_success, | 138 const base::Closure& on_success, |
| 132 const base::Callback<void(const base::FilePath&)>& on_failure) | 139 const base::Callback<void(const base::FilePath&)>& on_failure) |
| 133 : paths_(paths), | 140 : paths_(paths), |
| 134 profile_(profile), | 141 profile_(profile), |
| 142 is_directory_(is_directory), | |
| 135 outstanding_tasks_(1), | 143 outstanding_tasks_(1), |
| 136 on_success_(on_success), | 144 on_success_(on_success), |
| 137 on_failure_(on_failure) {} | 145 on_failure_(on_failure) {} |
| 138 | 146 |
| 139 void WritableFileChecker::Check() { | 147 void WritableFileChecker::Check() { |
| 140 #if defined(OS_CHROMEOS) | 148 #if defined(OS_CHROMEOS) |
| 141 if (drive::util::IsUnderDriveMountPoint(paths_[0])) { | 149 if (drive::util::IsUnderDriveMountPoint(paths_[0])) { |
| 142 outstanding_tasks_ = paths_.size(); | 150 outstanding_tasks_ = paths_.size(); |
| 143 for (std::vector<base::FilePath>::const_iterator it = paths_.begin(); | 151 for (std::vector<base::FilePath>::const_iterator it = paths_.begin(); |
| 144 it != paths_.end(); | 152 it != paths_.end(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 error_path_ = error_path; | 185 error_path_ = error_path; |
| 178 TaskDone(); | 186 TaskDone(); |
| 179 } | 187 } |
| 180 | 188 |
| 181 void WritableFileChecker::CheckLocalWritableFiles() { | 189 void WritableFileChecker::CheckLocalWritableFiles() { |
| 182 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | 190 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
| 183 std::string error; | 191 std::string error; |
| 184 for (std::vector<base::FilePath>::const_iterator it = paths_.begin(); | 192 for (std::vector<base::FilePath>::const_iterator it = paths_.begin(); |
| 185 it != paths_.end(); | 193 it != paths_.end(); |
| 186 ++it) { | 194 ++it) { |
| 187 if (!DoCheckWritableFile(*it)) { | 195 if (!DoCheckWritableFile(*it, is_directory_)) { |
| 188 content::BrowserThread::PostTask( | 196 content::BrowserThread::PostTask( |
| 189 content::BrowserThread::UI, | 197 content::BrowserThread::UI, |
| 190 FROM_HERE, | 198 FROM_HERE, |
| 191 base::Bind(&WritableFileChecker::Error, this, *it)); | 199 base::Bind(&WritableFileChecker::Error, this, *it)); |
| 192 return; | 200 return; |
| 193 } | 201 } |
| 194 } | 202 } |
| 195 content::BrowserThread::PostTask( | 203 content::BrowserThread::PostTask( |
| 196 content::BrowserThread::UI, | 204 content::BrowserThread::UI, |
| 197 FROM_HERE, | 205 FROM_HERE, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 const std::string& mime_type, | 291 const std::string& mime_type, |
| 284 const base::FilePath& path) { | 292 const base::FilePath& path) { |
| 285 return FileHandlerCanHandleFileWithMimeType(handler, mime_type) || | 293 return FileHandlerCanHandleFileWithMimeType(handler, mime_type) || |
| 286 FileHandlerCanHandleFileWithExtension(handler, path); | 294 FileHandlerCanHandleFileWithExtension(handler, path); |
| 287 } | 295 } |
| 288 | 296 |
| 289 GrantedFileEntry CreateFileEntry( | 297 GrantedFileEntry CreateFileEntry( |
| 290 Profile* profile, | 298 Profile* profile, |
| 291 const Extension* extension, | 299 const Extension* extension, |
| 292 int renderer_id, | 300 int renderer_id, |
| 293 const base::FilePath& path) { | 301 const base::FilePath& path, |
| 302 bool is_directory) { | |
| 294 GrantedFileEntry result; | 303 GrantedFileEntry result; |
| 295 fileapi::IsolatedContext* isolated_context = | 304 fileapi::IsolatedContext* isolated_context = |
| 296 fileapi::IsolatedContext::GetInstance(); | 305 fileapi::IsolatedContext::GetInstance(); |
| 297 DCHECK(isolated_context); | 306 DCHECK(isolated_context); |
| 298 | 307 |
| 299 result.filesystem_id = isolated_context->RegisterFileSystemForPath( | 308 result.filesystem_id = isolated_context->RegisterFileSystemForPath( |
| 300 fileapi::kFileSystemTypeNativeForPlatformApp, path, | 309 fileapi::kFileSystemTypeNativeForPlatformApp, path, |
| 301 &result.registered_name); | 310 &result.registered_name); |
| 302 | 311 |
| 303 content::ChildProcessSecurityPolicy* policy = | 312 content::ChildProcessSecurityPolicy* policy = |
| 304 content::ChildProcessSecurityPolicy::GetInstance(); | 313 content::ChildProcessSecurityPolicy::GetInstance(); |
| 305 policy->GrantReadFileSystem(renderer_id, result.filesystem_id); | 314 policy->GrantReadFileSystem(renderer_id, result.filesystem_id); |
| 306 if (HasFileSystemWritePermission(extension)) | 315 if (HasFileSystemWritePermission(extension)) { |
| 307 policy->GrantWriteFileSystem(renderer_id, result.filesystem_id); | 316 policy->GrantWriteFileSystem(renderer_id, result.filesystem_id); |
| 317 if (is_directory) | |
| 318 policy->GrantCreateFileForFileSystem(renderer_id, result.filesystem_id); | |
| 319 } | |
| 308 | 320 |
| 309 result.id = result.filesystem_id + ":" + result.registered_name; | 321 result.id = result.filesystem_id + ":" + result.registered_name; |
| 310 return result; | 322 return result; |
| 311 } | 323 } |
| 312 | 324 |
| 313 void CheckWritableFiles( | 325 void CheckWritableFiles( |
| 314 const std::vector<base::FilePath>& paths, | 326 const std::vector<base::FilePath>& paths, |
| 315 Profile* profile, | 327 Profile* profile, |
| 328 bool is_directory, | |
| 316 const base::Closure& on_success, | 329 const base::Closure& on_success, |
| 317 const base::Callback<void(const base::FilePath&)>& on_failure) { | 330 const base::Callback<void(const base::FilePath&)>& on_failure) { |
| 318 scoped_refptr<WritableFileChecker> checker( | 331 scoped_refptr<WritableFileChecker> checker(new WritableFileChecker( |
| 319 new WritableFileChecker(paths, profile, on_success, on_failure)); | 332 paths, profile, is_directory, on_success, on_failure)); |
| 320 checker->Check(); | 333 checker->Check(); |
| 321 } | 334 } |
| 322 | 335 |
| 336 GrantedFileEntry::GrantedFileEntry() {} | |
| 337 | |
| 323 bool HasFileSystemWritePermission(const Extension* extension) { | 338 bool HasFileSystemWritePermission(const Extension* extension) { |
| 324 return extension->HasAPIPermission(APIPermission::kFileSystemWrite); | 339 return extension->HasAPIPermission(APIPermission::kFileSystemWrite); |
| 325 } | 340 } |
| 326 | 341 |
| 327 } // namespace app_file_handler_util | 342 } // namespace app_file_handler_util |
| 328 | 343 |
| 329 } // namespace extensions | 344 } // namespace extensions |
| OLD | NEW |