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