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

Side by Side Diff: extensions/browser/api/file_system/file_system_api.cc

Issue 2937753002: test
Patch Set: Created 3 years, 6 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_system/file_system_api.h" 5 #include "extensions/browser/api/file_system/file_system_api.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "apps/saved_files_service.h"
15 #include "base/bind.h" 14 #include "base/bind.h"
16 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
17 #include "base/files/file_util.h" 16 #include "base/files/file_util.h"
18 #include "base/macros.h" 17 #include "base/macros.h"
19 #include "base/memory/ptr_util.h" 18 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/weak_ptr.h"
20 #include "base/path_service.h" 21 #include "base/path_service.h"
22 #include "base/strings/string16.h"
21 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
23 #include "base/strings/sys_string_conversions.h"
24 #include "base/strings/utf_string_conversions.h" 25 #include "base/strings/utf_string_conversions.h"
25 #include "base/task_scheduler/post_task.h" 26 #include "base/task_scheduler/post_task.h"
26 #include "base/value_conversions.h" 27 #include "base/value_conversions.h"
27 #include "base/values.h" 28 #include "base/values.h"
28 #include "build/build_config.h" 29 #include "build/build_config.h"
29 #include "chrome/browser/platform_util.h" 30 #include "content/public/browser/browser_context.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h"
32 #include "chrome/browser/ui/chrome_select_file_policy.h"
33 #include "chrome/common/chrome_paths.h"
34 #include "chrome/common/extensions/api/file_system.h"
35 #include "chrome/grit/generated_resources.h"
36 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
37 #include "content/public/browser/child_process_security_policy.h" 32 #include "content/public/browser/child_process_security_policy.h"
38 #include "content/public/browser/render_frame_host.h" 33 #include "content/public/browser/render_frame_host.h"
39 #include "content/public/browser/render_process_host.h" 34 #include "content/public/browser/render_process_host.h"
40 #include "content/public/browser/storage_partition.h" 35 #include "content/public/browser/storage_partition.h"
41 #include "content/public/browser/web_contents.h" 36 #include "content/public/browser/web_contents.h"
37 #include "extensions/browser/api/extensions_api_client.h"
42 #include "extensions/browser/api/file_handlers/app_file_handler_util.h" 38 #include "extensions/browser/api/file_handlers/app_file_handler_util.h"
39 #include "extensions/browser/api/file_system/file_system_delegate.h"
40 #include "extensions/browser/api/file_system/saved_files_service_delegate.h"
43 #include "extensions/browser/app_window/app_window.h" 41 #include "extensions/browser/app_window/app_window.h"
44 #include "extensions/browser/app_window/app_window_registry.h" 42 #include "extensions/browser/app_window/app_window_registry.h"
45 #include "extensions/browser/extension_prefs.h" 43 #include "extensions/browser/extension_prefs.h"
46 #include "extensions/browser/extension_system.h"
47 #include "extensions/browser/extension_util.h" 44 #include "extensions/browser/extension_util.h"
48 #include "extensions/browser/granted_file_entry.h" 45 #include "extensions/browser/granted_file_entry.h"
49 #include "extensions/browser/path_util.h" 46 #include "extensions/browser/path_util.h"
47 #include "extensions/common/api/file_system.h"
50 #include "extensions/common/permissions/api_permission.h" 48 #include "extensions/common/permissions/api_permission.h"
51 #include "extensions/common/permissions/permissions_data.h" 49 #include "extensions/common/permissions/permissions_data.h"
52 #include "net/base/mime_util.h" 50 #include "net/base/mime_util.h"
53 #include "storage/browser/fileapi/external_mount_points.h" 51 #include "storage/browser/fileapi/external_mount_points.h"
52 #include "storage/browser/fileapi/file_system_context.h"
54 #include "storage/browser/fileapi/file_system_operation_runner.h" 53 #include "storage/browser/fileapi/file_system_operation_runner.h"
55 #include "storage/browser/fileapi/isolated_context.h" 54 #include "storage/browser/fileapi/isolated_context.h"
56 #include "storage/common/fileapi/file_system_types.h" 55 #include "storage/common/fileapi/file_system_types.h"
57 #include "storage/common/fileapi/file_system_util.h" 56 #include "storage/common/fileapi/file_system_util.h"
58 #include "ui/base/l10n/l10n_util.h" 57 #include "ui/base/l10n/l10n_util.h"
59 #include "ui/base/ui_base_types.h"
60 #include "ui/shell_dialogs/select_file_dialog.h" 58 #include "ui/shell_dialogs/select_file_dialog.h"
59 #include "ui/shell_dialogs/select_file_policy.h"
61 #include "ui/shell_dialogs/selected_file_info.h" 60 #include "ui/shell_dialogs/selected_file_info.h"
62 61
63 #if defined(OS_MACOSX) 62 #if defined(OS_MACOSX)
64 #include <CoreFoundation/CoreFoundation.h> 63 #include <CoreFoundation/CoreFoundation.h>
65 #include "base/mac/foundation_util.h" 64 #include "base/mac/foundation_util.h"
66 #endif 65 #endif
67 66
68 #if defined(OS_CHROMEOS) 67 #if defined(OS_CHROMEOS)
69 #include "base/strings/string16.h" 68 #include "extensions/browser/api/file_handlers/non_native_file_system_delegate.h "
70 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
71 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
72 #include "extensions/browser/event_router.h"
73 #include "extensions/browser/extension_registry.h"
74 #include "extensions/common/constants.h"
75 #include "url/url_constants.h"
76 #endif 69 #endif
77 70
78 using apps::SavedFileEntry; 71 // using apps::SavedFilesService;
79 using apps::SavedFilesService;
80 using storage::IsolatedContext;
81 72
82 const char kInvalidCallingPage[] = "Invalid calling page. This function can't " 73 const char kInvalidCallingPage[] =
74 "Invalid calling page. This function can't "
83 "be called from a background page."; 75 "be called from a background page.";
84 const char kUserCancelled[] = "User cancelled"; 76 const char kUserCancelled[] = "User cancelled";
85 const char kWritableFileErrorFormat[] = "Error opening %s"; 77 const char kWritableFileErrorFormat[] = "Error opening %s";
86 const char kRequiresFileSystemWriteError[] = 78 const char kRequiresFileSystemWriteError[] =
87 "Operation requires fileSystem.write permission"; 79 "Operation requires fileSystem.write permission";
88 const char kRequiresFileSystemDirectoryError[] = 80 const char kRequiresFileSystemDirectoryError[] =
89 "Operation requires fileSystem.directory permission"; 81 "Operation requires fileSystem.directory permission";
90 const char kMultipleUnsupportedError[] = 82 const char kMultipleUnsupportedError[] =
91 "acceptsMultiple: true is only supported for 'openFile'"; 83 "acceptsMultiple: true is only supported for 'openFile'";
92 const char kUnknownIdError[] = "Unknown id"; 84 const char kUnknownIdError[] = "Unknown id";
93
94 #if !defined(OS_CHROMEOS)
95 const char kNotSupportedOnCurrentPlatformError[] = 85 const char kNotSupportedOnCurrentPlatformError[] =
96 "Operation not supported on the current platform."; 86 "Operation not supported on the current platform.";
97 #else 87
88 #if defined(OS_CHROMEOS)
98 const char kNotSupportedOnNonKioskSessionError[] = 89 const char kNotSupportedOnNonKioskSessionError[] =
99 "Operation only supported for kiosk apps running in a kiosk session."; 90 "Operation only supported for kiosk apps running in a kiosk session.";
100 const char kVolumeNotFoundError[] = "Volume not found.";
101 const char kSecurityError[] = "Security error.";
102 const char kConsentImpossible[] =
103 "Impossible to ask for user consent as there is no app window visible.";
104 #endif 91 #endif
105 92
106 namespace extensions { 93 namespace extensions {
107 94
108 namespace file_system = api::file_system; 95 namespace file_system = api::file_system;
109 namespace ChooseEntry = file_system::ChooseEntry; 96 namespace ChooseEntry = file_system::ChooseEntry;
110 97
111 namespace { 98 namespace {
112 99
113 bool g_skip_picker_for_test = false; 100 bool g_skip_picker_for_test = false;
(...skipping 17 matching lines...) Expand all
131 std::vector<std::string>* list = accept_option.mime_types.get(); 118 std::vector<std::string>* list = accept_option.mime_types.get();
132 bool valid_type = false; 119 bool valid_type = false;
133 for (std::vector<std::string>::const_iterator iter = list->begin(); 120 for (std::vector<std::string>::const_iterator iter = list->begin();
134 iter != list->end(); ++iter) { 121 iter != list->end(); ++iter) {
135 std::vector<base::FilePath::StringType> inner; 122 std::vector<base::FilePath::StringType> inner;
136 std::string accept_type = base::ToLowerASCII(*iter); 123 std::string accept_type = base::ToLowerASCII(*iter);
137 net::GetExtensionsForMimeType(accept_type, &inner); 124 net::GetExtensionsForMimeType(accept_type, &inner);
138 if (inner.empty()) 125 if (inner.empty())
139 continue; 126 continue;
140 127
141 if (valid_type) 128 if (valid_type) {
142 description_id = 0; // We already have an accept type with label; if 129 description_id = 0; // We already have an accept type with label; if
143 // we find another, give up and use the default. 130 // we find another, give up and use the default.
144 else if (accept_type == "image/*") 131 } else {
145 description_id = IDS_IMAGE_FILES; 132 FileSystemDelegate* delegate =
146 else if (accept_type == "audio/*") 133 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
147 description_id = IDS_AUDIO_FILES; 134 DCHECK(delegate);
148 else if (accept_type == "video/*") 135 delegate->GetDescriptionIdForAcceptType(accept_type, &description_id);
149 description_id = IDS_VIDEO_FILES; 136 }
150 137
151 extension_set.insert(inner.begin(), inner.end()); 138 extension_set.insert(inner.begin(), inner.end());
152 valid_type = true; 139 valid_type = true;
153 } 140 }
154 } 141 }
155 142
156 if (accept_option.extensions.get()) { 143 if (accept_option.extensions.get()) {
157 std::vector<std::string>* list = accept_option.extensions.get(); 144 std::vector<std::string>* list = accept_option.extensions.get();
158 for (std::vector<std::string>::const_iterator iter = list->begin(); 145 for (std::vector<std::string>::const_iterator iter = list->begin();
159 iter != list->end(); ++iter) { 146 iter != list->end(); ++iter) {
(...skipping 16 matching lines...) Expand all
176 *description = l10n_util::GetStringUTF16(description_id); 163 *description = l10n_util::GetStringUTF16(description_id);
177 164
178 return true; 165 return true;
179 } 166 }
180 167
181 // Key for the path of the directory of the file last chosen by the user in 168 // Key for the path of the directory of the file last chosen by the user in
182 // response to a chrome.fileSystem.chooseEntry() call. 169 // response to a chrome.fileSystem.chooseEntry() call.
183 const char kLastChooseEntryDirectory[] = "last_choose_file_directory"; 170 const char kLastChooseEntryDirectory[] = "last_choose_file_directory";
184 171
185 const int kGraylistedPaths[] = { 172 const int kGraylistedPaths[] = {
186 base::DIR_HOME, 173 base::DIR_HOME,
187 #if defined(OS_WIN) 174 #if defined(OS_WIN)
188 base::DIR_PROGRAM_FILES, 175 base::DIR_PROGRAM_FILES, base::DIR_PROGRAM_FILESX86, base::DIR_WINDOWS,
189 base::DIR_PROGRAM_FILESX86,
190 base::DIR_WINDOWS,
191 #endif 176 #endif
192 }; 177 };
193 178
194 typedef base::Callback<void(std::unique_ptr<base::File::Info>)> 179 typedef base::Callback<void(std::unique_ptr<base::File::Info>)>
195 FileInfoOptCallback; 180 FileInfoOptCallback;
196 181
197 // Passes optional file info to the UI thread depending on |result| and |info|. 182 // Passes optional file info to the UI thread depending on |result| and |info|.
198 void PassFileInfoToUIThread(const FileInfoOptCallback& callback, 183 void PassFileInfoToUIThread(const FileInfoOptCallback& callback,
199 base::File::Error result, 184 base::File::Error result,
200 const base::File::Info& info) { 185 const base::File::Info& info) {
201 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 186 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
202 std::unique_ptr<base::File::Info> file_info( 187 std::unique_ptr<base::File::Info> file_info(
203 result == base::File::FILE_OK ? new base::File::Info(info) : NULL); 188 result == base::File::FILE_OK ? new base::File::Info(info) : NULL);
204 content::BrowserThread::PostTask( 189 content::BrowserThread::PostTask(
205 content::BrowserThread::UI, FROM_HERE, 190 content::BrowserThread::UI, FROM_HERE,
206 base::BindOnce(callback, base::Passed(&file_info))); 191 base::BindOnce(callback, base::Passed(&file_info)));
207 } 192 }
208 193
209 // Gets a WebContents instance handle for a platform app hosted in 194 // Gets a WebContents instance handle for a platform app hosted in
210 // |render_frame_host|. If not found, then returns NULL. 195 // |render_frame_host|. If not found, then returns NULL.
211 content::WebContents* GetWebContentsForRenderFrameHost( 196 content::WebContents* GetWebContentsForRenderFrameHost(
212 Profile* profile, 197 content::BrowserContext* browser_context,
213 content::RenderFrameHost* render_frame_host) { 198 content::RenderFrameHost* render_frame_host) {
214 content::WebContents* web_contents = 199 content::WebContents* web_contents =
215 content::WebContents::FromRenderFrameHost(render_frame_host); 200 content::WebContents::FromRenderFrameHost(render_frame_host);
216 // Check if there is an app window associated with the web contents; if not, 201 // Check if there is an app window associated with the web contents; if not,
217 // return null. 202 // return null.
218 return AppWindowRegistry::Get(profile) 203 return AppWindowRegistry::Get(browser_context)
219 ->GetAppWindowForWebContents(web_contents) 204 ->GetAppWindowForWebContents(web_contents)
220 ? web_contents 205 ? web_contents
221 : nullptr; 206 : nullptr;
222 } 207 }
223 208
224 #if defined(OS_CHROMEOS)
225 // Fills a list of volumes mounted in the system.
226 void FillVolumeList(Profile* profile,
227 std::vector<api::file_system::Volume>* result) {
228 file_manager::VolumeManager* const volume_manager =
229 file_manager::VolumeManager::Get(profile);
230 DCHECK(volume_manager);
231
232 const auto& volume_list = volume_manager->GetVolumeList();
233 // Convert volume_list to result_volume_list.
234 for (const auto& volume : volume_list) {
235 api::file_system::Volume result_volume;
236 result_volume.volume_id = volume->volume_id();
237 result_volume.writable = !volume->is_read_only();
238 result->push_back(std::move(result_volume));
239 }
240 }
241 #endif
242
243 } // namespace 209 } // namespace
244 210
245 namespace file_system_api { 211 namespace file_system_api {
246 212
247 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, 213 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
248 const std::string& extension_id) { 214 const std::string& extension_id) {
249 base::FilePath path; 215 base::FilePath path;
250 std::string string_path; 216 std::string string_path;
251 if (prefs->ReadPrefAsString(extension_id, 217 if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory,
252 kLastChooseEntryDirectory,
253 &string_path)) { 218 &string_path)) {
254 path = base::FilePath::FromUTF8Unsafe(string_path); 219 path = base::FilePath::FromUTF8Unsafe(string_path);
255 } 220 }
256 return path; 221 return path;
257 } 222 }
258 223
259 void SetLastChooseEntryDirectory(ExtensionPrefs* prefs, 224 void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
260 const std::string& extension_id, 225 const std::string& extension_id,
261 const base::FilePath& path) { 226 const base::FilePath& path) {
262 prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory, 227 prefs->UpdateExtensionPref(extension_id, kLastChooseEntryDirectory,
263 base::CreateFilePathValue(path)); 228 base::CreateFilePathValue(path));
264 } 229 }
265 230
266 #if defined(OS_CHROMEOS)
267 void DispatchVolumeListChangeEvent(Profile* profile) {
268 DCHECK(profile);
269 EventRouter* const event_router = EventRouter::Get(profile);
270 if (!event_router) // Possible on shutdown.
271 return;
272
273 ExtensionRegistry* const registry = ExtensionRegistry::Get(profile);
274 if (!registry) // Possible on shutdown.
275 return;
276
277 ConsentProviderDelegate consent_provider_delegate(profile, nullptr);
278 ConsentProvider consent_provider(&consent_provider_delegate);
279 api::file_system::VolumeListChangedEvent event_args;
280 FillVolumeList(profile, &event_args.volumes);
281 for (const auto& extension : registry->enabled_extensions()) {
282 if (!consent_provider.IsGrantable(*extension.get()))
283 continue;
284 event_router->DispatchEventToExtension(
285 extension->id(),
286 base::MakeUnique<Event>(
287 events::FILE_SYSTEM_ON_VOLUME_LIST_CHANGED,
288 api::file_system::OnVolumeListChanged::kEventName,
289 api::file_system::OnVolumeListChanged::Create(event_args)));
290 }
291 }
292 #endif
293
294 } // namespace file_system_api 231 } // namespace file_system_api
295 232
296 #if defined(OS_CHROMEOS)
297 using file_system_api::ConsentProvider;
298 #endif
299
300 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() { 233 ExtensionFunction::ResponseAction FileSystemGetDisplayPathFunction::Run() {
301 std::string filesystem_name; 234 std::string filesystem_name;
302 std::string filesystem_path; 235 std::string filesystem_path;
303 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 236 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
304 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 237 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
305 238
306 base::FilePath file_path; 239 base::FilePath file_path;
307 std::string error; 240 std::string error;
308 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 241 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
309 filesystem_name, filesystem_path, 242 filesystem_name, filesystem_path,
(...skipping 13 matching lines...) Expand all
323 const std::vector<base::FilePath>& paths) { 256 const std::vector<base::FilePath>& paths) {
324 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 257 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
325 // TODO(cmihail): Path directory set should be initialized only with the 258 // TODO(cmihail): Path directory set should be initialized only with the
326 // paths that are actually directories, but for now we will consider 259 // paths that are actually directories, but for now we will consider
327 // all paths directories in case is_directory_ is true, otherwise 260 // all paths directories in case is_directory_ is true, otherwise
328 // all paths files, as this was the previous logic. 261 // all paths files, as this was the previous logic.
329 std::set<base::FilePath> path_directory_set_ = 262 std::set<base::FilePath> path_directory_set_ =
330 is_directory_ ? std::set<base::FilePath>(paths.begin(), paths.end()) 263 is_directory_ ? std::set<base::FilePath>(paths.begin(), paths.end())
331 : std::set<base::FilePath>{}; 264 : std::set<base::FilePath>{};
332 app_file_handler_util::PrepareFilesForWritableApp( 265 app_file_handler_util::PrepareFilesForWritableApp(
333 paths, GetProfile(), path_directory_set_, 266 paths, browser_context(), path_directory_set_,
334 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse, 267 base::Bind(&FileSystemEntryFunction::RegisterFileSystemsAndSendResponse,
335 this, paths), 268 this, paths),
336 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this)); 269 base::Bind(&FileSystemEntryFunction::HandleWritableFileError, this));
337 } 270 }
338 271
339 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse( 272 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse(
340 const std::vector<base::FilePath>& paths) { 273 const std::vector<base::FilePath>& paths) {
341 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 274 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
342 if (!render_frame_host()) 275 if (!render_frame_host())
343 return; 276 return;
344 277
345 std::unique_ptr<base::DictionaryValue> result = CreateResult(); 278 std::unique_ptr<base::DictionaryValue> result = CreateResult();
346 for (const auto& path : paths) 279 for (const auto& path : paths)
347 AddEntryToResult(path, std::string(), result.get()); 280 AddEntryToResult(path, std::string(), result.get());
348 SetResult(std::move(result)); 281 Respond(OneArgument(std::move(result)));
349 SendResponse(true);
350 } 282 }
351 283
352 std::unique_ptr<base::DictionaryValue> FileSystemEntryFunction::CreateResult() { 284 std::unique_ptr<base::DictionaryValue> FileSystemEntryFunction::CreateResult() {
353 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 285 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
354 result->Set("entries", base::MakeUnique<base::ListValue>()); 286 result->Set("entries", base::MakeUnique<base::ListValue>());
355 result->SetBoolean("multiple", multiple_); 287 result->SetBoolean("multiple", multiple_);
356 return result; 288 return result;
357 } 289 }
358 290
359 void FileSystemEntryFunction::AddEntryToResult(const base::FilePath& path, 291 void FileSystemEntryFunction::AddEntryToResult(const base::FilePath& path,
360 const std::string& id_override, 292 const std::string& id_override,
361 base::DictionaryValue* result) { 293 base::DictionaryValue* result) {
362 GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry( 294 GrantedFileEntry file_entry = app_file_handler_util::CreateFileEntry(
363 GetProfile(), 295 browser_context(), extension(),
364 extension(), 296 render_frame_host()->GetProcess()->GetID(), path, is_directory_);
365 render_frame_host()->GetProcess()->GetID(),
366 path,
367 is_directory_);
368 base::ListValue* entries; 297 base::ListValue* entries;
369 bool success = result->GetList("entries", &entries); 298 bool success = result->GetList("entries", &entries);
370 DCHECK(success); 299 DCHECK(success);
371 300
372 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue()); 301 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
373 entry->SetString("fileSystemId", file_entry.filesystem_id); 302 entry->SetString("fileSystemId", file_entry.filesystem_id);
374 entry->SetString("baseName", file_entry.registered_name); 303 entry->SetString("baseName", file_entry.registered_name);
375 if (id_override.empty()) 304 if (id_override.empty())
376 entry->SetString("id", file_entry.id); 305 entry->SetString("id", file_entry.id);
377 else 306 else
378 entry->SetString("id", id_override); 307 entry->SetString("id", id_override);
379 entry->SetBoolean("isDirectory", is_directory_); 308 entry->SetBoolean("isDirectory", is_directory_);
380 entries->Append(std::move(entry)); 309 entries->Append(std::move(entry));
381 } 310 }
382 311
383 void FileSystemEntryFunction::HandleWritableFileError( 312 void FileSystemEntryFunction::HandleWritableFileError(
384 const base::FilePath& error_path) { 313 const base::FilePath& error_path) {
385 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 314 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
386 error_ = base::StringPrintf(kWritableFileErrorFormat, 315 Respond(Error(base::StringPrintf(
387 error_path.BaseName().AsUTF8Unsafe().c_str()); 316 kWritableFileErrorFormat, error_path.BaseName().AsUTF8Unsafe().c_str())));
388 SendResponse(false);
389 } 317 }
390 318
391 bool FileSystemGetWritableEntryFunction::RunAsync() { 319 ExtensionFunction::ResponseAction FileSystemGetWritableEntryFunction::Run() {
392 std::string filesystem_name; 320 std::string filesystem_name;
393 std::string filesystem_path; 321 std::string filesystem_path;
394 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 322 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
395 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 323 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
396 324
397 if (!app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { 325 if (!app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
398 error_ = kRequiresFileSystemWriteError; 326 return RespondNow(Error(kRequiresFileSystemWriteError));
399 return false;
400 } 327 }
401 328
329 std::string error;
402 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 330 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
403 filesystem_name, filesystem_path, 331 filesystem_name, filesystem_path,
404 render_frame_host()->GetProcess()->GetID(), &path_, &error_)) 332 render_frame_host()->GetProcess()->GetID(), &path_, &error)) {
405 return false; 333 return RespondNow(Error(error));
334 }
406 335
407 base::PostTaskWithTraitsAndReply( 336 base::PostTaskWithTraitsAndReply(
408 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 337 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
409 base::BindOnce(&FileSystemGetWritableEntryFunction::SetIsDirectoryAsync, 338 base::BindOnce(&FileSystemGetWritableEntryFunction::SetIsDirectoryAsync,
410 this), 339 this),
411 base::BindOnce( 340 base::BindOnce(
412 &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse, 341 &FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse,
413 this)); 342 this));
414 return true; 343 return RespondLater();
415 } 344 }
416 345
417 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() { 346 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() {
418 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 347 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
419 if (is_directory_ && 348 if (is_directory_ && !extension_->permissions_data()->HasAPIPermission(
420 !extension_->permissions_data()->HasAPIPermission( 349 APIPermission::kFileSystemDirectory)) {
421 APIPermission::kFileSystemDirectory)) { 350 Respond(Error(kRequiresFileSystemDirectoryError));
422 error_ = kRequiresFileSystemDirectoryError; 351 return;
423 SendResponse(false);
424 } 352 }
425 std::vector<base::FilePath> paths; 353 std::vector<base::FilePath> paths;
426 paths.push_back(path_); 354 paths.push_back(path_);
427 PrepareFilesForWritableApp(paths); 355 PrepareFilesForWritableApp(paths);
428 } 356 }
429 357
430 void FileSystemGetWritableEntryFunction::SetIsDirectoryAsync() { 358 void FileSystemGetWritableEntryFunction::SetIsDirectoryAsync() {
431 if (base::DirectoryExists(path_)) { 359 if (base::DirectoryExists(path_)) {
432 is_directory_ = true; 360 is_directory_ = true;
433 } 361 }
434 } 362 }
435 363
436 ExtensionFunction::ResponseAction FileSystemIsWritableEntryFunction::Run() { 364 ExtensionFunction::ResponseAction FileSystemIsWritableEntryFunction::Run() {
437 std::string filesystem_name; 365 std::string filesystem_name;
438 std::string filesystem_path; 366 std::string filesystem_path;
439 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name)); 367 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
440 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path)); 368 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
441 369
442 std::string filesystem_id; 370 std::string filesystem_id;
443 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) 371 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id))
444 return RespondNow(Error(app_file_handler_util::kInvalidParameters)); 372 return RespondNow(Error(app_file_handler_util::kInvalidParameters));
445 373
446 content::ChildProcessSecurityPolicy* policy = 374 content::ChildProcessSecurityPolicy* policy =
447 content::ChildProcessSecurityPolicy::GetInstance(); 375 content::ChildProcessSecurityPolicy::GetInstance();
448 int renderer_id = render_frame_host()->GetProcess()->GetID(); 376 int renderer_id = render_frame_host()->GetProcess()->GetID();
449 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, 377 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id);
450 filesystem_id);
451 378
452 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable))); 379 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable)));
453 } 380 }
454 381
455 // Handles showing a dialog to the user to ask for the filename for a file to 382 // Handles showing a dialog to the user to ask for the filename for a file to
456 // save or open. 383 // save or open.
457 class FileSystemChooseEntryFunction::FilePicker 384 class FileSystemChooseEntryFunction::FilePicker
458 : public ui::SelectFileDialog::Listener { 385 : public ui::SelectFileDialog::Listener {
459 public: 386 public:
460 FilePicker(FileSystemChooseEntryFunction* function, 387 FilePicker(FileSystemChooseEntryFunction* function,
461 content::WebContents* web_contents, 388 content::WebContents* web_contents,
462 const base::FilePath& suggested_name, 389 const base::FilePath& suggested_name,
463 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 390 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
464 ui::SelectFileDialog::Type picker_type) 391 ui::SelectFileDialog::Type picker_type)
465 : function_(function) { 392 : function_(function) {
466 select_file_dialog_ = ui::SelectFileDialog::Create( 393 FileSystemDelegate* delegate =
467 this, new ChromeSelectFilePolicy(web_contents)); 394 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
468 gfx::NativeWindow owning_window = web_contents ? 395 DCHECK(delegate);
469 platform_util::GetTopLevel(web_contents->GetNativeView()) :
470 NULL;
471 396
397 select_file_dialog_ = delegate->CreateSelectFileDialog(
398 this, delegate->CreateSelectFilePolicy(web_contents));
399
400 // TODO(michaelpg): Use the FileSystemdelegate to override functionality for
401 // tests instead of using global variables.
472 if (g_skip_picker_for_test) { 402 if (g_skip_picker_for_test) {
473 if (g_use_suggested_path_for_test) { 403 if (g_use_suggested_path_for_test) {
474 content::BrowserThread::PostTask( 404 content::BrowserThread::PostTask(
475 content::BrowserThread::UI, FROM_HERE, 405 content::BrowserThread::UI, FROM_HERE,
476 base::BindOnce( 406 base::BindOnce(
477 &FileSystemChooseEntryFunction::FilePicker::FileSelected, 407 &FileSystemChooseEntryFunction::FilePicker::FileSelected,
478 base::Unretained(this), suggested_name, 1, 408 base::Unretained(this), suggested_name, 1,
479 static_cast<void*>(NULL))); 409 static_cast<void*>(NULL)));
480 } else if (g_path_to_be_picked_for_test) { 410 } else if (g_path_to_be_picked_for_test) {
481 content::BrowserThread::PostTask( 411 content::BrowserThread::PostTask(
(...skipping 12 matching lines...) Expand all
494 } else { 424 } else {
495 content::BrowserThread::PostTask( 425 content::BrowserThread::PostTask(
496 content::BrowserThread::UI, FROM_HERE, 426 content::BrowserThread::UI, FROM_HERE,
497 base::BindOnce(&FileSystemChooseEntryFunction::FilePicker:: 427 base::BindOnce(&FileSystemChooseEntryFunction::FilePicker::
498 FileSelectionCanceled, 428 FileSelectionCanceled,
499 base::Unretained(this), static_cast<void*>(NULL))); 429 base::Unretained(this), static_cast<void*>(NULL)));
500 } 430 }
501 return; 431 return;
502 } 432 }
503 433
504 select_file_dialog_->SelectFile(picker_type, 434 delegate->ShowSelectFileDialogForWebContents(
505 base::string16(), 435 select_file_dialog_, web_contents, picker_type, suggested_name,
506 suggested_name, 436 &file_type_info);
507 &file_type_info,
508 0,
509 base::FilePath::StringType(),
510 owning_window,
511 NULL);
512 } 437 }
513 438
514 ~FilePicker() override {} 439 ~FilePicker() override {}
515 440
516 private: 441 private:
517 // ui::SelectFileDialog::Listener implementation. 442 // ui::SelectFileDialog::Listener implementation.
518 void FileSelected(const base::FilePath& path, 443 void FileSelected(const base::FilePath& path,
519 int index, 444 int index,
520 void* params) override { 445 void* params) override {
521 std::vector<base::FilePath> paths; 446 std::vector<base::FilePath> paths;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 void FileSystemChooseEntryFunction::ShowPicker( 493 void FileSystemChooseEntryFunction::ShowPicker(
569 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 494 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
570 ui::SelectFileDialog::Type picker_type) { 495 ui::SelectFileDialog::Type picker_type) {
571 // TODO(asargent/benwells) - As a short term remediation for crbug.com/179010 496 // TODO(asargent/benwells) - As a short term remediation for crbug.com/179010
572 // we're adding the ability for a whitelisted extension to use this API since 497 // we're adding the ability for a whitelisted extension to use this API since
573 // chrome.fileBrowserHandler.selectFile is ChromeOS-only. Eventually we'd 498 // chrome.fileBrowserHandler.selectFile is ChromeOS-only. Eventually we'd
574 // like a better solution and likely this code will go back to being 499 // like a better solution and likely this code will go back to being
575 // platform-app only. 500 // platform-app only.
576 content::WebContents* const web_contents = 501 content::WebContents* const web_contents =
577 extension_->is_platform_app() 502 extension_->is_platform_app()
578 ? GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()) 503 ? GetWebContentsForRenderFrameHost(browser_context(),
504 render_frame_host())
579 : GetAssociatedWebContents(); 505 : GetAssociatedWebContents();
580 if (!web_contents) { 506 if (!web_contents) {
581 error_ = kInvalidCallingPage; 507 Respond(Error(kInvalidCallingPage));
582 SendResponse(false);
583 return; 508 return;
584 } 509 }
585 510
586 // The file picker will hold a reference to this function instance, preventing 511 // The file picker will hold a reference to this function instance, preventing
587 // its destruction (and subsequent sending of the function response) until the 512 // its destruction (and subsequent sending of the function response) until the
588 // user has selected a file or cancelled the picker. At that point, the picker 513 // user has selected a file or cancelled the picker. At that point, the picker
589 // will delete itself, which will also free the function instance. 514 // will delete itself, which will also free the function instance.
590 new FilePicker( 515 new FilePicker(this, web_contents, initial_path_, file_type_info,
591 this, web_contents, initial_path_, file_type_info, picker_type); 516 picker_type);
592 } 517 }
593 518
594 // static 519 // static
595 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( 520 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
596 base::FilePath* path) { 521 base::FilePath* path) {
597 g_skip_picker_for_test = true; 522 g_skip_picker_for_test = true;
598 g_use_suggested_path_for_test = false; 523 g_use_suggested_path_for_test = false;
599 g_path_to_be_picked_for_test = path; 524 g_path_to_be_picked_for_test = path;
600 g_paths_to_be_picked_for_test = NULL; 525 g_paths_to_be_picked_for_test = NULL;
601 } 526 }
602 527
528 // static
603 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest( 529 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest(
604 std::vector<base::FilePath>* paths) { 530 std::vector<base::FilePath>* paths) {
605 g_skip_picker_for_test = true; 531 g_skip_picker_for_test = true;
606 g_use_suggested_path_for_test = false; 532 g_use_suggested_path_for_test = false;
607 g_paths_to_be_picked_for_test = paths; 533 g_paths_to_be_picked_for_test = paths;
608 } 534 }
609 535
610 // static 536 // static
611 void FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest() { 537 void FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest() {
612 g_skip_picker_for_test = true; 538 g_skip_picker_for_test = true;
(...skipping 27 matching lines...) Expand all
640 g_allow_directory_access_for_test = false; 566 g_allow_directory_access_for_test = false;
641 } 567 }
642 568
643 // static 569 // static
644 void FileSystemChooseEntryFunction::StopSkippingDirectoryConfirmationForTest() { 570 void FileSystemChooseEntryFunction::StopSkippingDirectoryConfirmationForTest() {
645 g_skip_directory_confirmation_for_test = false; 571 g_skip_directory_confirmation_for_test = false;
646 } 572 }
647 573
648 // static 574 // static
649 void FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest( 575 void FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
650 const std::string& name, const base::FilePath& path) { 576 const std::string& name,
577 const base::FilePath& path) {
651 // For testing on Chrome OS, where to deal with remote and local paths 578 // For testing on Chrome OS, where to deal with remote and local paths
652 // smoothly, all accessed paths need to be registered in the list of 579 // smoothly, all accessed paths need to be registered in the list of
653 // external mount points. 580 // external mount points.
654 storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( 581 storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
655 name, 582 name, storage::kFileSystemTypeNativeLocal,
656 storage::kFileSystemTypeNativeLocal, 583 storage::FileSystemMountOption(), path);
657 storage::FileSystemMountOption(),
658 path);
659 } 584 }
660 585
661 void FileSystemChooseEntryFunction::FilesSelected( 586 void FileSystemChooseEntryFunction::FilesSelected(
662 const std::vector<base::FilePath>& paths) { 587 const std::vector<base::FilePath>& paths) {
663 DCHECK(!paths.empty()); 588 DCHECK(!paths.empty());
664 base::FilePath last_choose_directory; 589 base::FilePath last_choose_directory;
665 if (is_directory_) { 590 if (is_directory_) {
666 last_choose_directory = paths[0]; 591 last_choose_directory = paths[0];
667 } else { 592 } else {
668 last_choose_directory = paths[0].DirName(); 593 last_choose_directory = paths[0].DirName();
669 } 594 }
670 file_system_api::SetLastChooseEntryDirectory( 595 file_system_api::SetLastChooseEntryDirectory(
671 ExtensionPrefs::Get(GetProfile()), 596 ExtensionPrefs::Get(browser_context()), extension()->id(),
672 extension()->id(),
673 last_choose_directory); 597 last_choose_directory);
674 if (is_directory_) { 598 if (is_directory_) {
675 // Get the WebContents for the app window to be the parent window of the 599 // Get the WebContents for the app window to be the parent window of the
676 // confirmation dialog if necessary. 600 // confirmation dialog if necessary.
677 content::WebContents* const web_contents = 601 content::WebContents* const web_contents = GetWebContentsForRenderFrameHost(
678 GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()); 602 browser_context(), render_frame_host());
679 if (!web_contents) { 603 if (!web_contents) {
680 error_ = kInvalidCallingPage; 604 Respond(Error(kInvalidCallingPage));
681 SendResponse(false);
682 return; 605 return;
683 } 606 }
684 607
685 DCHECK_EQ(paths.size(), 1u); 608 DCHECK_EQ(paths.size(), 1u);
686 bool non_native_path = false; 609 bool non_native_path = false;
687 #if defined(OS_CHROMEOS) 610 #if defined(OS_CHROMEOS)
688 non_native_path = 611 NonNativeFileSystemDelegate* delegate =
689 file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), paths[0]); 612 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
613 non_native_path = delegate && delegate->IsUnderNonNativeLocalPath(
614 browser_context(), paths[0]);
690 #endif 615 #endif
691 616
692 base::PostTaskWithTraits( 617 base::PostTaskWithTraits(
693 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 618 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
694 base::BindOnce( 619 base::BindOnce(
695 &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this, 620 &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this,
696 non_native_path, paths, web_contents)); 621 non_native_path, paths, web_contents));
697 return; 622 return;
698 } 623 }
699 624
700 OnDirectoryAccessConfirmed(paths); 625 OnDirectoryAccessConfirmed(paths);
701 } 626 }
702 627
703 void FileSystemChooseEntryFunction::FileSelectionCanceled() { 628 void FileSystemChooseEntryFunction::FileSelectionCanceled() {
704 error_ = kUserCancelled; 629 Respond(Error(kUserCancelled));
705 SendResponse(false);
706 } 630 }
707 631
708 void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync( 632 void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
709 bool non_native_path, 633 bool non_native_path,
710 const std::vector<base::FilePath>& paths, 634 const std::vector<base::FilePath>& paths,
711 content::WebContents* web_contents) { 635 content::WebContents* web_contents) {
712 const base::FilePath check_path = 636 const base::FilePath check_path =
713 non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]); 637 non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
714 if (check_path.empty()) { 638 if (check_path.empty()) {
715 content::BrowserThread::PostTask( 639 content::BrowserThread::PostTask(
716 content::BrowserThread::UI, FROM_HERE, 640 content::BrowserThread::UI, FROM_HERE,
717 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled, 641 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
718 this)); 642 this));
719 return; 643 return;
720 } 644 }
721 645
722 for (size_t i = 0; i < arraysize(kGraylistedPaths); i++) { 646 for (size_t i = 0; i < arraysize(kGraylistedPaths); i++) {
723 base::FilePath graylisted_path; 647 base::FilePath graylisted_path;
724 if (PathService::Get(kGraylistedPaths[i], &graylisted_path) && 648 if (!PathService::Get(kGraylistedPaths[i], &graylisted_path))
725 (check_path == graylisted_path || 649 continue;
726 check_path.IsParent(graylisted_path))) { 650 if (check_path != graylisted_path && !check_path.IsParent(graylisted_path))
727 if (g_skip_directory_confirmation_for_test) { 651 continue;
728 if (g_allow_directory_access_for_test) {
729 break;
730 } else {
731 content::BrowserThread::PostTask(
732 content::BrowserThread::UI, FROM_HERE,
733 base::BindOnce(
734 &FileSystemChooseEntryFunction::FileSelectionCanceled, this));
735 }
736 return;
737 }
738 652
653 if (g_skip_directory_confirmation_for_test) {
654 if (g_allow_directory_access_for_test)
655 break;
739 content::BrowserThread::PostTask( 656 content::BrowserThread::PostTask(
740 content::BrowserThread::UI, FROM_HERE, 657 content::BrowserThread::UI, FROM_HERE,
741 base::BindOnce( 658 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
742 CreateDirectoryAccessConfirmationDialog, 659 this));
743 app_file_handler_util::HasFileSystemWritePermission(
744 extension_.get()),
745 base::UTF8ToUTF16(extension_->name()), web_contents,
746 base::Bind(
747 &FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
748 this, paths),
749 base::Bind(&FileSystemChooseEntryFunction::FileSelectionCanceled,
750 this)));
751 return; 660 return;
752 } 661 }
662
663 content::BrowserThread::PostTask(
664 content::BrowserThread::UI, FROM_HERE,
665 base::BindOnce(
666 &FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
667 this, paths, web_contents));
668 return;
753 } 669 }
754 670
755 content::BrowserThread::PostTask( 671 content::BrowserThread::PostTask(
756 content::BrowserThread::UI, FROM_HERE, 672 content::BrowserThread::UI, FROM_HERE,
757 base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed, 673 base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
758 this, paths)); 674 this, paths));
759 } 675 }
760 676
677 void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
678 const std::vector<base::FilePath>& paths,
679 content::WebContents* web_contents) {
680 if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
681 FileSelectionCanceled();
682 return;
683 }
684
685 FileSystemDelegate* delegate =
686 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
687 if (!delegate) {
688 Respond(Error(kNotSupportedOnCurrentPlatformError));
689 return;
690 }
691
692 delegate->ConfirmSensitiveDirectoryAccess(
693 app_file_handler_util::HasFileSystemWritePermission(extension_.get()),
694 base::UTF8ToUTF16(extension_->name()), web_contents,
695 base::Bind(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
696 this, paths),
697 base::Bind(&FileSystemChooseEntryFunction::FileSelectionCanceled, this));
698 }
699
761 void FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed( 700 void FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed(
762 const std::vector<base::FilePath>& paths) { 701 const std::vector<base::FilePath>& paths) {
763 if (app_file_handler_util::HasFileSystemWritePermission(extension_.get())) { 702 if (app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
764 PrepareFilesForWritableApp(paths); 703 PrepareFilesForWritableApp(paths);
765 return; 704 return;
766 } 705 }
767 706
768 // Don't need to check the file, it's for reading. 707 // Don't need to check the file, it's for reading.
769 RegisterFileSystemsAndSendResponse(paths); 708 RegisterFileSystemsAndSendResponse(paths);
770 } 709 }
771 710
772 void FileSystemChooseEntryFunction::BuildFileTypeInfo( 711 void FileSystemChooseEntryFunction::BuildFileTypeInfo(
773 ui::SelectFileDialog::FileTypeInfo* file_type_info, 712 ui::SelectFileDialog::FileTypeInfo* file_type_info,
774 const base::FilePath::StringType& suggested_extension, 713 const base::FilePath::StringType& suggested_extension,
775 const AcceptOptions* accepts, 714 const AcceptOptions* accepts,
776 const bool* acceptsAllTypes) { 715 const bool* acceptsAllTypes) {
777 file_type_info->include_all_files = true; 716 file_type_info->include_all_files = true;
778 if (acceptsAllTypes) 717 if (acceptsAllTypes)
779 file_type_info->include_all_files = *acceptsAllTypes; 718 file_type_info->include_all_files = *acceptsAllTypes;
780 719
781 bool need_suggestion = !file_type_info->include_all_files && 720 bool need_suggestion =
782 !suggested_extension.empty(); 721 !file_type_info->include_all_files && !suggested_extension.empty();
783 722
784 if (accepts) { 723 if (accepts) {
785 for (const file_system::AcceptOption& option : *accepts) { 724 for (const file_system::AcceptOption& option : *accepts) {
786 base::string16 description; 725 base::string16 description;
787 std::vector<base::FilePath::StringType> extensions; 726 std::vector<base::FilePath::StringType> extensions;
788 727
789 if (!GetFileTypesFromAcceptOption(option, &extensions, &description)) 728 if (!GetFileTypesFromAcceptOption(option, &extensions, &description))
790 continue; // No extensions were found. 729 continue; // No extensions were found.
791 730
792 file_type_info->extensions.push_back(extensions); 731 file_type_info->extensions.push_back(extensions);
793 file_type_info->extension_description_overrides.push_back(description); 732 file_type_info->extension_description_overrides.push_back(description);
794 733
795 // If we still need to find suggested_extension, hunt for it inside the 734 // If we still need to find suggested_extension, hunt for it inside the
796 // extensions returned from GetFileTypesFromAcceptOption. 735 // extensions returned from GetFileTypesFromAcceptOption.
797 if (need_suggestion && std::find(extensions.begin(), 736 if (need_suggestion &&
798 extensions.end(), suggested_extension) != extensions.end()) { 737 std::find(extensions.begin(), extensions.end(),
738 suggested_extension) != extensions.end()) {
799 need_suggestion = false; 739 need_suggestion = false;
800 } 740 }
801 } 741 }
802 } 742 }
803 743
804 // If there's nothing in our accepted extension list or we couldn't find the 744 // If there's nothing in our accepted extension list or we couldn't find the
805 // suggested extension required, then default to accepting all types. 745 // suggested extension required, then default to accepting all types.
806 if (file_type_info->extensions.empty() || need_suggestion) 746 if (file_type_info->extensions.empty() || need_suggestion)
807 file_type_info->include_all_files = true; 747 file_type_info->include_all_files = true;
808 } 748 }
809 749
810 void FileSystemChooseEntryFunction::BuildSuggestion( 750 void FileSystemChooseEntryFunction::BuildSuggestion(
811 const std::string *opt_name, 751 const std::string* opt_name,
812 base::FilePath* suggested_name, 752 base::FilePath* suggested_name,
813 base::FilePath::StringType* suggested_extension) { 753 base::FilePath::StringType* suggested_extension) {
814 if (opt_name) { 754 if (opt_name) {
815 *suggested_name = base::FilePath::FromUTF8Unsafe(*opt_name); 755 *suggested_name = base::FilePath::FromUTF8Unsafe(*opt_name);
816 756
817 // Don't allow any path components; shorten to the base name. This should 757 // Don't allow any path components; shorten to the base name. This should
818 // result in a relative path, but in some cases may not. Clear the 758 // result in a relative path, but in some cases may not. Clear the
819 // suggestion for safety if this is the case. 759 // suggestion for safety if this is the case.
820 *suggested_name = suggested_name->BaseName(); 760 *suggested_name = suggested_name->BaseName();
821 if (suggested_name->IsAbsolute()) 761 if (suggested_name->IsAbsolute())
822 *suggested_name = base::FilePath(); 762 *suggested_name = base::FilePath();
823 763
824 *suggested_extension = suggested_name->Extension(); 764 *suggested_extension = suggested_name->Extension();
825 if (!suggested_extension->empty()) 765 if (!suggested_extension->empty())
826 suggested_extension->erase(suggested_extension->begin()); // drop the . 766 suggested_extension->erase(suggested_extension->begin()); // drop the .
827 } 767 }
828 } 768 }
829 769
830 void FileSystemChooseEntryFunction::SetInitialPathAndShowPicker( 770 void FileSystemChooseEntryFunction::SetInitialPathAndShowPicker(
831 const base::FilePath& previous_path, 771 const base::FilePath& previous_path,
832 const base::FilePath& suggested_name, 772 const base::FilePath& suggested_name,
833 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 773 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
834 ui::SelectFileDialog::Type picker_type, 774 ui::SelectFileDialog::Type picker_type,
835 bool is_previous_path_directory) { 775 bool is_previous_path_directory) {
836 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 776 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
837 if (is_previous_path_directory) { 777 if (is_previous_path_directory) {
838 initial_path_ = previous_path.Append(suggested_name); 778 initial_path_ = previous_path.Append(suggested_name);
839 } else { 779 } else {
840 base::FilePath documents_dir; 780 FileSystemDelegate* delegate =
841 if (PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir)) { 781 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
842 initial_path_ = documents_dir.Append(suggested_name); 782 DCHECK(delegate);
843 } else { 783 const base::FilePath default_directory = delegate->GetDefaultDirectory();
784 if (!default_directory.empty())
785 initial_path_ = default_directory.Append(suggested_name);
786 else
844 initial_path_ = suggested_name; 787 initial_path_ = suggested_name;
845 }
846 } 788 }
847 ShowPicker(file_type_info, picker_type); 789 ShowPicker(file_type_info, picker_type);
848 } 790 }
849 791
850 bool FileSystemChooseEntryFunction::RunAsync() { 792 ExtensionFunction::ResponseAction FileSystemChooseEntryFunction::Run() {
851 std::unique_ptr<ChooseEntry::Params> params( 793 std::unique_ptr<ChooseEntry::Params> params(
852 ChooseEntry::Params::Create(*args_)); 794 ChooseEntry::Params::Create(*args_));
853 EXTENSION_FUNCTION_VALIDATE(params.get()); 795 EXTENSION_FUNCTION_VALIDATE(params.get());
854 796
855 base::FilePath suggested_name; 797 base::FilePath suggested_name;
856 ui::SelectFileDialog::FileTypeInfo file_type_info; 798 ui::SelectFileDialog::FileTypeInfo file_type_info;
857 ui::SelectFileDialog::Type picker_type = 799 ui::SelectFileDialog::Type picker_type =
858 ui::SelectFileDialog::SELECT_OPEN_FILE; 800 ui::SelectFileDialog::SELECT_OPEN_FILE;
859 801
860 file_system::ChooseEntryOptions* options = params->options.get(); 802 file_system::ChooseEntryOptions* options = params->options.get();
861 if (options) { 803 if (options) {
862 multiple_ = options->accepts_multiple && *options->accepts_multiple; 804 multiple_ = options->accepts_multiple && *options->accepts_multiple;
863 if (multiple_) 805 if (multiple_)
864 picker_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE; 806 picker_type = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE;
865 807
866 if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENWRITABLEFILE && 808 if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENWRITABLEFILE &&
867 !app_file_handler_util::HasFileSystemWritePermission( 809 !app_file_handler_util::HasFileSystemWritePermission(
868 extension_.get())) { 810 extension_.get())) {
869 error_ = kRequiresFileSystemWriteError; 811 return RespondNow(Error(kRequiresFileSystemWriteError));
870 return false;
871 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) { 812 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_SAVEFILE) {
872 if (!app_file_handler_util::HasFileSystemWritePermission( 813 if (!app_file_handler_util::HasFileSystemWritePermission(
873 extension_.get())) { 814 extension_.get())) {
874 error_ = kRequiresFileSystemWriteError; 815 return RespondNow(Error(kRequiresFileSystemWriteError));
875 return false;
876 } 816 }
877 if (multiple_) { 817 if (multiple_) {
878 error_ = kMultipleUnsupportedError; 818 return RespondNow(Error(kMultipleUnsupportedError));
879 return false;
880 } 819 }
881 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE; 820 picker_type = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
882 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) { 821 } else if (options->type == file_system::CHOOSE_ENTRY_TYPE_OPENDIRECTORY) {
883 is_directory_ = true; 822 is_directory_ = true;
884 if (!extension_->permissions_data()->HasAPIPermission( 823 if (!extension_->permissions_data()->HasAPIPermission(
885 APIPermission::kFileSystemDirectory)) { 824 APIPermission::kFileSystemDirectory)) {
886 error_ = kRequiresFileSystemDirectoryError; 825 return RespondNow(Error(kRequiresFileSystemDirectoryError));
887 return false;
888 } 826 }
889 if (multiple_) { 827 if (multiple_) {
890 error_ = kMultipleUnsupportedError; 828 return RespondNow(Error(kMultipleUnsupportedError));
891 return false;
892 } 829 }
893 picker_type = ui::SelectFileDialog::SELECT_FOLDER; 830 picker_type = ui::SelectFileDialog::SELECT_FOLDER;
894 } 831 }
895 832
896 base::FilePath::StringType suggested_extension; 833 base::FilePath::StringType suggested_extension;
897 BuildSuggestion(options->suggested_name.get(), &suggested_name, 834 BuildSuggestion(options->suggested_name.get(), &suggested_name,
898 &suggested_extension); 835 &suggested_extension);
899 836
900 BuildFileTypeInfo(&file_type_info, suggested_extension, 837 BuildFileTypeInfo(&file_type_info, suggested_extension,
901 options->accepts.get(), options->accepts_all_types.get()); 838 options->accepts.get(), options->accepts_all_types.get());
902 } 839 }
903 840
904 file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH; 841 file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
905 842
906 base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory( 843 base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory(
907 ExtensionPrefs::Get(GetProfile()), extension()->id()); 844 ExtensionPrefs::Get(browser_context()), extension()->id());
908 845
909 if (previous_path.empty()) { 846 if (previous_path.empty()) {
910 SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info, 847 SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info,
911 picker_type, false); 848 picker_type, false);
912 return true; 849 return RespondLater();
913 } 850 }
914 851
915 base::Callback<void(bool)> set_initial_path_callback = base::Bind( 852 base::Callback<void(bool)> set_initial_path_callback = base::Bind(
916 &FileSystemChooseEntryFunction::SetInitialPathAndShowPicker, this, 853 &FileSystemChooseEntryFunction::SetInitialPathAndShowPicker, this,
917 previous_path, suggested_name, file_type_info, picker_type); 854 previous_path, suggested_name, file_type_info, picker_type);
918 855
919 // Check whether the |previous_path| is a non-native directory. 856 // Check whether the |previous_path| is a non-native directory.
920 #if defined(OS_CHROMEOS) 857 #if defined(OS_CHROMEOS)
921 if (file_manager::util::IsUnderNonNativeLocalPath(GetProfile(), 858 NonNativeFileSystemDelegate* delegate =
922 previous_path)) { 859 ExtensionsAPIClient::Get()->GetNonNativeFileSystemDelegate();
923 file_manager::util::IsNonNativeLocalPathDirectory( 860 if (delegate &&
924 GetProfile(), previous_path, set_initial_path_callback); 861 delegate->IsUnderNonNativeLocalPath(browser_context(), previous_path)) {
925 return true; 862 delegate->IsNonNativeLocalPathDirectory(browser_context(), previous_path,
863 set_initial_path_callback);
864 return RespondLater();
926 } 865 }
927 #endif 866 #endif
928 base::PostTaskWithTraitsAndReplyWithResult( 867 base::PostTaskWithTraitsAndReplyWithResult(
929 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, 868 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
930 base::Bind(&base::DirectoryExists, previous_path), 869 base::Bind(&base::DirectoryExists, previous_path),
931 set_initial_path_callback); 870 set_initial_path_callback);
932 871
933 return true; 872 return RespondLater();
934 } 873 }
935 874
936 bool FileSystemRetainEntryFunction::RunAsync() { 875 ExtensionFunction::ResponseAction FileSystemRetainEntryFunction::Run() {
937 std::string entry_id; 876 std::string entry_id;
938 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 877 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
939 SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); 878
879 FileSystemDelegate* delegate =
880 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
881 DCHECK(delegate);
882
883 auto saved_files_service_delegate =
884 delegate->CreateSavedFilesServiceDelegate(browser_context());
885
940 // Add the file to the retain list if it is not already on there. 886 // Add the file to the retain list if it is not already on there.
941 if (!saved_files_service->IsRegistered(extension_->id(), entry_id)) { 887 if (!saved_files_service_delegate->IsRegistered(extension_->id(), entry_id)) {
942 std::string filesystem_name; 888 std::string filesystem_name;
943 std::string filesystem_path; 889 std::string filesystem_path;
944 base::FilePath path; 890 base::FilePath path;
945 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name)); 891 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_name));
946 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path)); 892 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &filesystem_path));
893 std::string error;
947 if (!app_file_handler_util::ValidateFileEntryAndGetPath( 894 if (!app_file_handler_util::ValidateFileEntryAndGetPath(
948 filesystem_name, filesystem_path, 895 filesystem_name, filesystem_path,
949 render_frame_host()->GetProcess()->GetID(), &path, &error_)) { 896 render_frame_host()->GetProcess()->GetID(), &path, &error)) {
950 return false; 897 return RespondNow(Error(error));
951 } 898 }
952 899
953 std::string filesystem_id; 900 std::string filesystem_id;
954 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id)) 901 if (!storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id))
955 return false; 902 return RespondNow(Error(kUnknownErrorDoNotUse));
956 903
957 const GURL site = util::GetSiteForExtensionId(extension_id(), GetProfile()); 904 const GURL site =
905 util::GetSiteForExtensionId(extension_id(), browser_context());
958 storage::FileSystemContext* const context = 906 storage::FileSystemContext* const context =
959 content::BrowserContext::GetStoragePartitionForSite(GetProfile(), site) 907 content::BrowserContext::GetStoragePartitionForSite(browser_context(),
908 site)
960 ->GetFileSystemContext(); 909 ->GetFileSystemContext();
961 const storage::FileSystemURL url = context->CreateCrackedFileSystemURL( 910 const storage::FileSystemURL url = context->CreateCrackedFileSystemURL(
962 site, 911 site, storage::kFileSystemTypeIsolated,
963 storage::kFileSystemTypeIsolated, 912 storage::IsolatedContext::GetInstance()
964 IsolatedContext::GetInstance()
965 ->CreateVirtualRootPath(filesystem_id) 913 ->CreateVirtualRootPath(filesystem_id)
966 .Append(base::FilePath::FromUTF8Unsafe(filesystem_path))); 914 .Append(base::FilePath::FromUTF8Unsafe(filesystem_path)));
967 915
968 content::BrowserThread::PostTask( 916 content::BrowserThread::PostTask(
969 content::BrowserThread::IO, FROM_HERE, 917 content::BrowserThread::IO, FROM_HERE,
970 base::BindOnce( 918 base::BindOnce(
971 base::IgnoreResult( 919 base::IgnoreResult(
972 &storage::FileSystemOperationRunner::GetMetadata), 920 &storage::FileSystemOperationRunner::GetMetadata),
973 context->operation_runner()->AsWeakPtr(), url, 921 context->operation_runner()->AsWeakPtr(), url,
974 storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY, 922 storage::FileSystemOperation::GET_METADATA_FIELD_IS_DIRECTORY,
975 base::Bind( 923 base::Bind(
976 &PassFileInfoToUIThread, 924 &PassFileInfoToUIThread,
977 base::Bind(&FileSystemRetainEntryFunction::RetainFileEntry, 925 base::Bind(&FileSystemRetainEntryFunction::RetainFileEntry,
978 this, entry_id, path)))); 926 this, entry_id, path))));
979 return true; 927 return RespondLater();
980 } 928 }
981 929
982 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); 930 saved_files_service_delegate->EnqueueFileEntry(extension_->id(), entry_id);
983 SendResponse(true); 931 return RespondNow(NoArguments());
984 return true;
985 } 932 }
986 933
987 void FileSystemRetainEntryFunction::RetainFileEntry( 934 void FileSystemRetainEntryFunction::RetainFileEntry(
988 const std::string& entry_id, 935 const std::string& entry_id,
989 const base::FilePath& path, 936 const base::FilePath& path,
990 std::unique_ptr<base::File::Info> file_info) { 937 std::unique_ptr<base::File::Info> file_info) {
991 if (!file_info) { 938 if (!file_info) {
992 SendResponse(false); 939 Respond(Error(kUnknownErrorDoNotUse));
993 return; 940 return;
994 } 941 }
995 942
996 SavedFilesService* saved_files_service = SavedFilesService::Get(GetProfile()); 943 FileSystemDelegate* delegate =
997 saved_files_service->RegisterFileEntry( 944 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
998 extension_->id(), entry_id, path, file_info->is_directory); 945 DCHECK(delegate);
999 saved_files_service->EnqueueFileEntry(extension_->id(), entry_id); 946
1000 SendResponse(true); 947 auto saved_files_service_delegate =
948 delegate->CreateSavedFilesServiceDelegate(browser_context());
949 file_system_api::SavedFilesServiceDelegate::File file = {
950 entry_id, path, file_info->is_directory};
951 saved_files_service_delegate->RegisterFileEntry(extension_->id(), file);
952 saved_files_service_delegate->EnqueueFileEntry(extension_->id(), entry_id);
953 Respond(NoArguments());
1001 } 954 }
1002 955
1003 ExtensionFunction::ResponseAction FileSystemIsRestorableFunction::Run() { 956 ExtensionFunction::ResponseAction FileSystemIsRestorableFunction::Run() {
1004 std::string entry_id; 957 std::string entry_id;
1005 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 958 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
959
960 FileSystemDelegate* delegate =
961 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
962 DCHECK(delegate);
963
964 auto saved_files_service_delegate =
965 delegate->CreateSavedFilesServiceDelegate(browser_context());
966
1006 return RespondNow(OneArgument(base::MakeUnique<base::Value>( 967 return RespondNow(OneArgument(base::MakeUnique<base::Value>(
1007 SavedFilesService::Get(Profile::FromBrowserContext(browser_context())) 968 saved_files_service_delegate->IsRegistered(extension_->id(), entry_id))));
1008 ->IsRegistered(extension_->id(), entry_id))));
1009 } 969 }
1010 970
1011 bool FileSystemRestoreEntryFunction::RunAsync() { 971 ExtensionFunction::ResponseAction FileSystemRestoreEntryFunction::Run() {
1012 std::string entry_id; 972 std::string entry_id;
1013 bool needs_new_entry; 973 bool needs_new_entry;
1014 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id)); 974 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &entry_id));
1015 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry)); 975 EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(1, &needs_new_entry));
1016 const SavedFileEntry* file_entry = SavedFilesService::Get( 976 FileSystemDelegate* delegate =
1017 GetProfile())->GetFileEntry(extension_->id(), entry_id); 977 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
1018 if (!file_entry) { 978 DCHECK(delegate);
1019 error_ = kUnknownIdError; 979
1020 return false; 980 auto saved_files_service_delegate =
981 delegate->CreateSavedFilesServiceDelegate(browser_context());
982 file_system_api::SavedFilesServiceDelegate::File file;
983 if (!saved_files_service_delegate->GetRegisteredFileInfo(extension_->id(),
984 entry_id, &file)) {
985 return RespondNow(Error(kUnknownIdError));
1021 } 986 }
1022 987
1023 SavedFilesService::Get(GetProfile()) 988 saved_files_service_delegate->EnqueueFileEntry(extension_->id(), entry_id);
1024 ->EnqueueFileEntry(extension_->id(), entry_id);
1025 989
1026 // Only create a new file entry if the renderer requests one. 990 // Only create a new file entry if the renderer requests one.
1027 // |needs_new_entry| will be false if the renderer already has an Entry for 991 // |needs_new_entry| will be false if the renderer already has an Entry for
1028 // |entry_id|. 992 // |entry_id|.
1029 if (needs_new_entry) { 993 if (needs_new_entry) {
1030 is_directory_ = file_entry->is_directory; 994 is_directory_ = file.is_directory;
1031 std::unique_ptr<base::DictionaryValue> result = CreateResult(); 995 std::unique_ptr<base::DictionaryValue> result = CreateResult();
1032 AddEntryToResult(file_entry->path, file_entry->id, result.get()); 996 AddEntryToResult(file.path, file.id, result.get());
1033 SetResult(std::move(result)); 997 return RespondNow(OneArgument(std::move(result)));
1034 } 998 }
1035 SendResponse(true); 999 return RespondNow(NoArguments());
1036 return true;
1037 } 1000 }
1038 1001
1039 ExtensionFunction::ResponseAction FileSystemObserveDirectoryFunction::Run() { 1002 ExtensionFunction::ResponseAction FileSystemObserveDirectoryFunction::Run() {
1040 NOTIMPLEMENTED(); 1003 NOTIMPLEMENTED();
1041 return RespondNow(Error(kUnknownIdError)); 1004 return RespondNow(Error(kUnknownIdError));
1042 } 1005 }
1043 1006
1044 ExtensionFunction::ResponseAction FileSystemUnobserveEntryFunction::Run() { 1007 ExtensionFunction::ResponseAction FileSystemUnobserveEntryFunction::Run() {
1045 NOTIMPLEMENTED(); 1008 NOTIMPLEMENTED();
1046 return RespondNow(Error(kUnknownIdError)); 1009 return RespondNow(Error(kUnknownIdError));
1047 } 1010 }
1048 1011
1049 ExtensionFunction::ResponseAction FileSystemGetObservedEntriesFunction::Run() { 1012 ExtensionFunction::ResponseAction FileSystemGetObservedEntriesFunction::Run() {
1050 NOTIMPLEMENTED(); 1013 NOTIMPLEMENTED();
1051 return RespondNow(Error(kUnknownIdError)); 1014 return RespondNow(Error(kUnknownIdError));
1052 } 1015 }
1053 1016
1054 #if !defined(OS_CHROMEOS) 1017 #if !defined(OS_CHROMEOS)
1055 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { 1018 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
1056 using api::file_system::RequestFileSystem::Params; 1019 using file_system::RequestFileSystem::Params;
1057 const std::unique_ptr<Params> params(Params::Create(*args_)); 1020 const std::unique_ptr<Params> params(Params::Create(*args_));
1058 EXTENSION_FUNCTION_VALIDATE(params); 1021 EXTENSION_FUNCTION_VALIDATE(params);
1059 1022
1060 NOTIMPLEMENTED(); 1023 NOTIMPLEMENTED();
1061 return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); 1024 return RespondNow(Error(kNotSupportedOnCurrentPlatformError));
1062 } 1025 }
1063 1026
1064 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { 1027 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() {
1065 NOTIMPLEMENTED(); 1028 NOTIMPLEMENTED();
1066 return RespondNow(Error(kNotSupportedOnCurrentPlatformError)); 1029 return RespondNow(Error(kNotSupportedOnCurrentPlatformError));
1067 } 1030 }
1068 #else 1031 #else
1069 1032
1070 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() 1033 FileSystemRequestFileSystemFunction::FileSystemRequestFileSystemFunction() {}
1071 : chrome_details_(this) {
1072 }
1073 1034
1074 FileSystemRequestFileSystemFunction::~FileSystemRequestFileSystemFunction() { 1035 FileSystemRequestFileSystemFunction::~FileSystemRequestFileSystemFunction() {}
1075 }
1076 1036
1077 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() { 1037 ExtensionFunction::ResponseAction FileSystemRequestFileSystemFunction::Run() {
1078 using api::file_system::RequestFileSystem::Params; 1038 using file_system::RequestFileSystem::Params;
1079 const std::unique_ptr<Params> params(Params::Create(*args_)); 1039 const std::unique_ptr<Params> params(Params::Create(*args_));
1080 EXTENSION_FUNCTION_VALIDATE(params); 1040 EXTENSION_FUNCTION_VALIDATE(params);
1081 1041
1042 FileSystemDelegate* delegate =
1043 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
1044 DCHECK(delegate);
1082 // Only kiosk apps in kiosk sessions can use this API. 1045 // Only kiosk apps in kiosk sessions can use this API.
1083 // Additionally it is enabled for whitelisted component extensions and apps. 1046 // Additionally it is enabled for whitelisted component extensions and apps.
1084 file_system_api::ConsentProviderDelegate consent_provider_delegate( 1047 if (!delegate->IsGrantable(browser_context(), render_frame_host(),
1085 chrome_details_.GetProfile(), render_frame_host()); 1048 *extension())) {
1086 file_system_api::ConsentProvider consent_provider(&consent_provider_delegate);
1087
1088 if (!consent_provider.IsGrantable(*extension()))
1089 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 1049 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
1090
1091 using file_manager::VolumeManager;
1092 using file_manager::Volume;
1093 VolumeManager* const volume_manager =
1094 VolumeManager::Get(chrome_details_.GetProfile());
1095 DCHECK(volume_manager);
1096
1097 const bool writable =
1098 params->options.writable.get() && *params->options.writable.get();
1099 if (writable &&
1100 !app_file_handler_util::HasFileSystemWritePermission(extension_.get())) {
1101 return RespondNow(Error(kRequiresFileSystemWriteError));
1102 } 1050 }
1103 1051
1104 base::WeakPtr<file_manager::Volume> volume = 1052 delegate->RequestFileSystem(
1105 volume_manager->FindVolumeById(params->options.volume_id); 1053 browser_context(), this, *extension(), params->options.volume_id,
1106 if (!volume.get()) 1054 params->options.writable.get() && *params->options.writable.get(),
1107 return RespondNow(Error(kVolumeNotFoundError)); 1055 base::Bind(&FileSystemRequestFileSystemFunction::OnGotFileSystem, this),
1056 base::Bind(&FileSystemRequestFileSystemFunction::OnError, this));
1108 1057
1109 const GURL site = 1058 return did_respond() ? AlreadyResponded() : RespondLater();
1110 util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile());
1111 scoped_refptr<storage::FileSystemContext> file_system_context =
1112 content::BrowserContext::GetStoragePartitionForSite(
1113 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1114 storage::ExternalFileSystemBackend* const backend =
1115 file_system_context->external_backend();
1116 DCHECK(backend);
1117
1118 base::FilePath virtual_path;
1119 if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path))
1120 return RespondNow(Error(kSecurityError));
1121
1122 if (writable && (volume->is_read_only()))
1123 return RespondNow(Error(kSecurityError));
1124
1125 consent_provider.RequestConsent(
1126 *extension(), volume, writable,
1127 base::Bind(&FileSystemRequestFileSystemFunction::OnConsentReceived, this,
1128 volume, writable));
1129 return RespondLater();
1130 } 1059 }
1131 1060
1132 void FileSystemRequestFileSystemFunction::OnConsentReceived( 1061 void FileSystemRequestFileSystemFunction::OnGotFileSystem(
1133 const base::WeakPtr<file_manager::Volume>& volume, 1062 const std::string& id,
1134 bool writable, 1063 const std::string& path) {
1135 ConsentProvider::Consent result) {
1136 using file_manager::VolumeManager;
1137 using file_manager::Volume;
1138
1139 // Render frame host can be gone before this callback method is executed.
1140 if (!render_frame_host()) {
1141 Respond(Error(""));
1142 return;
1143 }
1144
1145 switch (result) {
1146 case ConsentProvider::CONSENT_REJECTED:
1147 Respond(Error(kSecurityError));
1148 return;
1149
1150 case ConsentProvider::CONSENT_IMPOSSIBLE:
1151 Respond(Error(kConsentImpossible));
1152 return;
1153
1154 case ConsentProvider::CONSENT_GRANTED:
1155 break;
1156 }
1157
1158 if (!volume.get()) {
1159 Respond(Error(kVolumeNotFoundError));
1160 return;
1161 }
1162
1163 const GURL site =
1164 util::GetSiteForExtensionId(extension_id(), chrome_details_.GetProfile());
1165 scoped_refptr<storage::FileSystemContext> file_system_context =
1166 content::BrowserContext::GetStoragePartitionForSite(
1167 chrome_details_.GetProfile(), site)->GetFileSystemContext();
1168 storage::ExternalFileSystemBackend* const backend =
1169 file_system_context->external_backend();
1170 DCHECK(backend);
1171
1172 base::FilePath virtual_path;
1173 if (!backend->GetVirtualPath(volume->mount_path(), &virtual_path)) {
1174 Respond(Error(kSecurityError));
1175 return;
1176 }
1177
1178 storage::IsolatedContext* const isolated_context =
1179 storage::IsolatedContext::GetInstance();
1180 DCHECK(isolated_context);
1181
1182 const storage::FileSystemURL original_url =
1183 file_system_context->CreateCrackedFileSystemURL(
1184 GURL(std::string(kExtensionScheme) + url::kStandardSchemeSeparator +
1185 extension_id()),
1186 storage::kFileSystemTypeExternal, virtual_path);
1187
1188 // Set a fixed register name, as the automatic one would leak the mount point
1189 // directory.
1190 std::string register_name = "fs";
1191 const std::string file_system_id =
1192 isolated_context->RegisterFileSystemForPath(
1193 storage::kFileSystemTypeNativeForPlatformApp,
1194 std::string() /* file_system_id */, original_url.path(),
1195 &register_name);
1196 if (file_system_id.empty()) {
1197 Respond(Error(kSecurityError));
1198 return;
1199 }
1200
1201 backend->GrantFileAccessToExtension(extension_->id(), virtual_path);
1202
1203 // Grant file permissions to the renderer hosting component.
1204 content::ChildProcessSecurityPolicy* policy =
1205 content::ChildProcessSecurityPolicy::GetInstance();
1206 DCHECK(policy);
1207
1208 // Read-only permisisons.
1209 policy->GrantReadFile(render_frame_host()->GetProcess()->GetID(),
1210 volume->mount_path());
1211 policy->GrantReadFileSystem(render_frame_host()->GetProcess()->GetID(),
1212 file_system_id);
1213
1214 // Additional write permissions.
1215 if (writable) {
1216 policy->GrantCreateReadWriteFile(render_frame_host()->GetProcess()->GetID(),
1217 volume->mount_path());
1218 policy->GrantCopyInto(render_frame_host()->GetProcess()->GetID(),
1219 volume->mount_path());
1220 policy->GrantWriteFileSystem(render_frame_host()->GetProcess()->GetID(),
1221 file_system_id);
1222 policy->GrantDeleteFromFileSystem(
1223 render_frame_host()->GetProcess()->GetID(), file_system_id);
1224 policy->GrantCreateFileForFileSystem(
1225 render_frame_host()->GetProcess()->GetID(), file_system_id);
1226 }
1227
1228 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 1064 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
1229 dict->SetString("file_system_id", file_system_id); 1065 dict->SetString("file_system_id", id);
1230 dict->SetString("file_system_path", register_name); 1066 dict->SetString("file_system_path", path);
1231
1232 Respond(OneArgument(std::move(dict))); 1067 Respond(OneArgument(std::move(dict)));
1233 } 1068 }
1234 1069
1235 FileSystemGetVolumeListFunction::FileSystemGetVolumeListFunction() 1070 void FileSystemRequestFileSystemFunction::OnError(const std::string& error) {
1236 : chrome_details_(this) { 1071 Respond(Error(error));
1237 } 1072 }
1238 1073
1239 FileSystemGetVolumeListFunction::~FileSystemGetVolumeListFunction() { 1074 FileSystemGetVolumeListFunction::FileSystemGetVolumeListFunction() {}
1075
1076 FileSystemGetVolumeListFunction::~FileSystemGetVolumeListFunction() {}
1077
1078 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() {
1079 FileSystemDelegate* delegate =
1080 ExtensionsAPIClient::Get()->GetFileSystemDelegate();
1081 DCHECK(delegate);
1082 // Only kiosk apps in kiosk sessions can use this API.
1083 // Additionally it is enabled for whitelisted component extensions and apps.
1084 if (!delegate->IsGrantable(browser_context(), render_frame_host(),
1085 *extension())) {
1086 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
1087 }
1088
1089 delegate->GetVolumeList(
1090 browser_context(),
1091 base::Bind(&FileSystemGetVolumeListFunction::OnGotVolumeList, this),
1092 base::Bind(&FileSystemGetVolumeListFunction::OnError, this));
1093
1094 return did_respond() ? AlreadyResponded() : RespondLater();
1240 } 1095 }
1241 1096
1242 ExtensionFunction::ResponseAction FileSystemGetVolumeListFunction::Run() { 1097 void FileSystemGetVolumeListFunction::OnGotVolumeList(
1243 // Only kiosk apps in kiosk sessions can use this API. 1098 const std::vector<file_system::Volume>& volumes) {
1244 // Additionally it is enabled for whitelisted component extensions and apps. 1099 Respond(ArgumentList(file_system::GetVolumeList::Results::Create(volumes)));
1245 file_system_api::ConsentProviderDelegate consent_provider_delegate( 1100 }
1246 chrome_details_.GetProfile(), render_frame_host());
1247 file_system_api::ConsentProvider consent_provider(&consent_provider_delegate);
1248 1101
1249 if (!consent_provider.IsGrantable(*extension())) 1102 void FileSystemGetVolumeListFunction::OnError(const std::string& error) {
1250 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 1103 Respond(Error(error));
1251 std::vector<api::file_system::Volume> result_volume_list;
1252 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list);
1253
1254 return RespondNow(ArgumentList(
1255 api::file_system::GetVolumeList::Results::Create(result_volume_list)));
1256 } 1104 }
1257 #endif 1105 #endif
1258 1106
1259 } // namespace extensions 1107 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/api/file_system/file_system_api.h ('k') | extensions/browser/api/file_system/file_system_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698