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

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

Issue 2967223002: Move fileSystem API FilePicker class to own file (Closed)
Patch Set: CHECK web_contents Created 3 years, 5 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
« no previous file with comments | « chrome/browser/extensions/api/file_system/file_system_api.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "chrome/browser/extensions/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" 14 #include "apps/saved_files_service.h"
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/callback.h"
16 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
17 #include "base/files/file_util.h" 18 #include "base/files/file_util.h"
18 #include "base/macros.h" 19 #include "base/macros.h"
19 #include "base/memory/ptr_util.h" 20 #include "base/memory/ptr_util.h"
20 #include "base/path_service.h" 21 #include "base/path_service.h"
21 #include "base/strings/string_util.h" 22 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 23 #include "base/strings/stringprintf.h"
23 #include "base/strings/sys_string_conversions.h" 24 #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"
30 #include "chrome/browser/extensions/api/file_system/file_entry_picker.h"
29 #include "chrome/browser/platform_util.h" 31 #include "chrome/browser/platform_util.h"
30 #include "chrome/browser/profiles/profile.h" 32 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h" 33 #include "chrome/browser/ui/apps/directory_access_confirmation_dialog.h"
32 #include "chrome/browser/ui/chrome_select_file_policy.h" 34 #include "chrome/browser/ui/chrome_select_file_policy.h"
33 #include "chrome/common/chrome_paths.h" 35 #include "chrome/common/chrome_paths.h"
34 #include "chrome/common/extensions/api/file_system.h" 36 #include "chrome/common/extensions/api/file_system.h"
35 #include "chrome/grit/generated_resources.h" 37 #include "chrome/grit/generated_resources.h"
36 #include "content/public/browser/browser_thread.h" 38 #include "content/public/browser/browser_thread.h"
37 #include "content/public/browser/child_process_security_policy.h" 39 #include "content/public/browser/child_process_security_policy.h"
38 #include "content/public/browser/render_frame_host.h" 40 #include "content/public/browser/render_frame_host.h"
(...skipping 13 matching lines...) Expand all
52 #include "extensions/common/permissions/permissions_data.h" 54 #include "extensions/common/permissions/permissions_data.h"
53 #include "net/base/mime_util.h" 55 #include "net/base/mime_util.h"
54 #include "storage/browser/fileapi/external_mount_points.h" 56 #include "storage/browser/fileapi/external_mount_points.h"
55 #include "storage/browser/fileapi/file_system_operation_runner.h" 57 #include "storage/browser/fileapi/file_system_operation_runner.h"
56 #include "storage/browser/fileapi/isolated_context.h" 58 #include "storage/browser/fileapi/isolated_context.h"
57 #include "storage/common/fileapi/file_system_types.h" 59 #include "storage/common/fileapi/file_system_types.h"
58 #include "storage/common/fileapi/file_system_util.h" 60 #include "storage/common/fileapi/file_system_util.h"
59 #include "ui/base/l10n/l10n_util.h" 61 #include "ui/base/l10n/l10n_util.h"
60 #include "ui/base/ui_base_types.h" 62 #include "ui/base/ui_base_types.h"
61 #include "ui/shell_dialogs/select_file_dialog.h" 63 #include "ui/shell_dialogs/select_file_dialog.h"
62 #include "ui/shell_dialogs/selected_file_info.h" 64 #include "ui/shell_dialogs/select_file_policy.h"
63 65
64 #if defined(OS_MACOSX) 66 #if defined(OS_MACOSX)
65 #include <CoreFoundation/CoreFoundation.h> 67 #include <CoreFoundation/CoreFoundation.h>
66 #include "base/mac/foundation_util.h" 68 #include "base/mac/foundation_util.h"
67 #endif 69 #endif
68 70
69 #if defined(OS_CHROMEOS) 71 #if defined(OS_CHROMEOS)
70 #include "base/strings/string16.h" 72 #include "base/strings/string16.h"
71 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" 73 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
72 #include "chrome/browser/chromeos/file_manager/volume_manager.h" 74 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 std::unique_ptr<base::File::Info> file_info( 203 std::unique_ptr<base::File::Info> file_info(
202 result == base::File::FILE_OK ? new base::File::Info(info) : NULL); 204 result == base::File::FILE_OK ? new base::File::Info(info) : NULL);
203 content::BrowserThread::PostTask( 205 content::BrowserThread::PostTask(
204 content::BrowserThread::UI, FROM_HERE, 206 content::BrowserThread::UI, FROM_HERE,
205 base::BindOnce(callback, base::Passed(&file_info))); 207 base::BindOnce(callback, base::Passed(&file_info)));
206 } 208 }
207 209
208 // Gets a WebContents instance handle for a platform app hosted in 210 // Gets a WebContents instance handle for a platform app hosted in
209 // |render_frame_host|. If not found, then returns NULL. 211 // |render_frame_host|. If not found, then returns NULL.
210 content::WebContents* GetWebContentsForRenderFrameHost( 212 content::WebContents* GetWebContentsForRenderFrameHost(
211 Profile* profile, 213 content::BrowserContext* browser_context,
212 content::RenderFrameHost* render_frame_host) { 214 content::RenderFrameHost* render_frame_host) {
213 content::WebContents* web_contents = 215 content::WebContents* web_contents =
214 content::WebContents::FromRenderFrameHost(render_frame_host); 216 content::WebContents::FromRenderFrameHost(render_frame_host);
215 // Check if there is an app window associated with the web contents; if not, 217 // Check if there is an app window associated with the web contents; if not,
216 // return null. 218 // return null.
217 return AppWindowRegistry::Get(profile)->GetAppWindowForWebContents( 219 return AppWindowRegistry::Get(browser_context)
218 web_contents) 220 ->GetAppWindowForWebContents(web_contents)
219 ? web_contents 221 ? web_contents
220 : nullptr; 222 : nullptr;
221 } 223 }
222 224
223 #if defined(OS_CHROMEOS) 225 #if defined(OS_CHROMEOS)
224 // Fills a list of volumes mounted in the system. 226 // Fills a list of volumes mounted in the system.
225 void FillVolumeList(Profile* profile, 227 void FillVolumeList(Profile* profile,
226 std::vector<api::file_system::Volume>* result) { 228 std::vector<api::file_system::Volume>* result) {
227 file_manager::VolumeManager* const volume_manager = 229 file_manager::VolumeManager* const volume_manager =
228 file_manager::VolumeManager::Get(profile); 230 file_manager::VolumeManager::Get(profile);
229 DCHECK(volume_manager); 231 DCHECK(volume_manager);
230 232
231 const auto& volume_list = volume_manager->GetVolumeList(); 233 const auto& volume_list = volume_manager->GetVolumeList();
232 // Convert volume_list to result_volume_list. 234 // Convert volume_list to result_volume_list.
233 for (const auto& volume : volume_list) { 235 for (const auto& volume : volume_list) {
234 api::file_system::Volume result_volume; 236 api::file_system::Volume result_volume;
235 result_volume.volume_id = volume->volume_id(); 237 result_volume.volume_id = volume->volume_id();
236 result_volume.writable = !volume->is_read_only(); 238 result_volume.writable = !volume->is_read_only();
237 result->push_back(std::move(result_volume)); 239 result->push_back(std::move(result_volume));
238 } 240 }
239 } 241 }
240 #endif 242 #endif
241 243
244 // Creates and shows a SelectFileDialog, or returns false if the dialog could
245 // not be created.
246 bool ShowSelectFileDialog(
247 scoped_refptr<UIThreadExtensionFunction> extension_function,
248 ui::SelectFileDialog::Type type,
249 const base::FilePath& default_path,
250 const ui::SelectFileDialog::FileTypeInfo* file_types,
251 FileEntryPicker::FilesSelectedCallback files_selected_callback,
252 base::OnceClosure file_selection_canceled_callback) {
253 // TODO(asargent/benwells) - As a short term remediation for
254 // crbug.com/179010 we're adding the ability for a whitelisted extension to
255 // use this API since chrome.fileBrowserHandler.selectFile is ChromeOS-only.
256 // Eventually we'd like a better solution and likely this code will go back
257 // to being platform-app only.
258 content::WebContents* const web_contents =
259 extension_function->extension()->is_platform_app()
260 ? GetWebContentsForRenderFrameHost(
261 extension_function->browser_context(),
262 extension_function->render_frame_host())
263 : extension_function->GetAssociatedWebContents();
264 if (!web_contents)
265 return false;
266
267 // The file picker will hold a reference to the UIThreadExtensionFunction
268 // instance, preventing its destruction (and subsequent sending of the
269 // function response) until the user has selected a file or cancelled the
270 // picker. At that point, the picker will delete itself, which will also free
271 // the function instance.
272 new FileEntryPicker(web_contents, default_path, *file_types, type,
273 std::move(files_selected_callback),
274 std::move(file_selection_canceled_callback));
275 return true;
276 }
277
242 } // namespace 278 } // namespace
243 279
244 namespace file_system_api { 280 namespace file_system_api {
245 281
246 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs, 282 base::FilePath GetLastChooseEntryDirectory(const ExtensionPrefs* prefs,
247 const std::string& extension_id) { 283 const std::string& extension_id) {
248 base::FilePath path; 284 base::FilePath path;
249 std::string string_path; 285 std::string string_path;
250 if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory, 286 if (prefs->ReadPrefAsString(extension_id, kLastChooseEntryDirectory,
251 &string_path)) { 287 &string_path)) {
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 return RespondNow(Error(app_file_handler_util::kInvalidParameters)); 474 return RespondNow(Error(app_file_handler_util::kInvalidParameters));
439 475
440 content::ChildProcessSecurityPolicy* policy = 476 content::ChildProcessSecurityPolicy* policy =
441 content::ChildProcessSecurityPolicy::GetInstance(); 477 content::ChildProcessSecurityPolicy::GetInstance();
442 int renderer_id = render_frame_host()->GetProcess()->GetID(); 478 int renderer_id = render_frame_host()->GetProcess()->GetID();
443 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id); 479 bool is_writable = policy->CanReadWriteFileSystem(renderer_id, filesystem_id);
444 480
445 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable))); 481 return RespondNow(OneArgument(base::MakeUnique<base::Value>(is_writable)));
446 } 482 }
447 483
448 // Handles showing a dialog to the user to ask for the filename for a file to
449 // save or open.
450 class FileSystemChooseEntryFunction::FilePicker
451 : public ui::SelectFileDialog::Listener {
452 public:
453 FilePicker(FileSystemChooseEntryFunction* function,
454 content::WebContents* web_contents,
455 const base::FilePath& suggested_name,
456 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
457 ui::SelectFileDialog::Type picker_type)
458 : function_(function) {
459 select_file_dialog_ = ui::SelectFileDialog::Create(
460 this, new ChromeSelectFilePolicy(web_contents));
461 gfx::NativeWindow owning_window =
462 web_contents ? platform_util::GetTopLevel(web_contents->GetNativeView())
463 : NULL;
464
465 if (g_skip_picker_for_test) {
466 if (g_use_suggested_path_for_test) {
467 content::BrowserThread::PostTask(
468 content::BrowserThread::UI, FROM_HERE,
469 base::BindOnce(
470 &FileSystemChooseEntryFunction::FilePicker::FileSelected,
471 base::Unretained(this), suggested_name, 1,
472 static_cast<void*>(NULL)));
473 } else if (g_path_to_be_picked_for_test) {
474 content::BrowserThread::PostTask(
475 content::BrowserThread::UI, FROM_HERE,
476 base::BindOnce(
477 &FileSystemChooseEntryFunction::FilePicker::FileSelected,
478 base::Unretained(this), *g_path_to_be_picked_for_test, 1,
479 static_cast<void*>(NULL)));
480 } else if (g_paths_to_be_picked_for_test) {
481 content::BrowserThread::PostTask(
482 content::BrowserThread::UI, FROM_HERE,
483 base::BindOnce(
484 &FileSystemChooseEntryFunction::FilePicker::MultiFilesSelected,
485 base::Unretained(this), *g_paths_to_be_picked_for_test,
486 static_cast<void*>(NULL)));
487 } else {
488 content::BrowserThread::PostTask(
489 content::BrowserThread::UI, FROM_HERE,
490 base::BindOnce(&FileSystemChooseEntryFunction::FilePicker::
491 FileSelectionCanceled,
492 base::Unretained(this), static_cast<void*>(NULL)));
493 }
494 return;
495 }
496
497 select_file_dialog_->SelectFile(
498 picker_type, base::string16(), suggested_name, &file_type_info, 0,
499 base::FilePath::StringType(), owning_window, NULL);
500 }
501
502 ~FilePicker() override {}
503
504 private:
505 // ui::SelectFileDialog::Listener implementation.
506 void FileSelected(const base::FilePath& path,
507 int index,
508 void* params) override {
509 std::vector<base::FilePath> paths;
510 paths.push_back(path);
511 MultiFilesSelected(paths, params);
512 }
513
514 void FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file,
515 int index,
516 void* params) override {
517 // Normally, file.local_path is used because it is a native path to the
518 // local read-only cached file in the case of remote file system like
519 // Chrome OS's Google Drive integration. Here, however, |file.file_path| is
520 // necessary because we need to create a FileEntry denoting the remote file,
521 // not its cache. On other platforms than Chrome OS, they are the same.
522 //
523 // TODO(kinaba): remove this, once after the file picker implements proper
524 // switch of the path treatment depending on the |allowed_paths|.
525 FileSelected(file.file_path, index, params);
526 }
527
528 void MultiFilesSelected(const std::vector<base::FilePath>& files,
529 void* params) override {
530 function_->FilesSelected(files);
531 delete this;
532 }
533
534 void MultiFilesSelectedWithExtraInfo(
535 const std::vector<ui::SelectedFileInfo>& files,
536 void* params) override {
537 std::vector<base::FilePath> paths;
538 for (std::vector<ui::SelectedFileInfo>::const_iterator it = files.begin();
539 it != files.end(); ++it) {
540 paths.push_back(it->file_path);
541 }
542 MultiFilesSelected(paths, params);
543 }
544
545 void FileSelectionCanceled(void* params) override {
546 function_->FileSelectionCanceled();
547 delete this;
548 }
549
550 scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
551 scoped_refptr<FileSystemChooseEntryFunction> function_;
552
553 DISALLOW_COPY_AND_ASSIGN(FilePicker);
554 };
555
556 void FileSystemChooseEntryFunction::ShowPicker( 484 void FileSystemChooseEntryFunction::ShowPicker(
557 const ui::SelectFileDialog::FileTypeInfo& file_type_info, 485 const ui::SelectFileDialog::FileTypeInfo& file_type_info,
558 ui::SelectFileDialog::Type picker_type) { 486 ui::SelectFileDialog::Type picker_type) {
559 // TODO(asargent/benwells) - As a short term remediation for crbug.com/179010 487 if (g_skip_picker_for_test) {
560 // we're adding the ability for a whitelisted extension to use this API since 488 std::vector<base::FilePath> test_paths;
561 // chrome.fileBrowserHandler.selectFile is ChromeOS-only. Eventually we'd 489 if (g_use_suggested_path_for_test)
562 // like a better solution and likely this code will go back to being 490 test_paths.push_back(initial_path_);
563 // platform-app only. 491 else if (g_path_to_be_picked_for_test)
564 content::WebContents* const web_contents = 492 test_paths.push_back(*g_path_to_be_picked_for_test);
565 extension_->is_platform_app() 493 else if (g_paths_to_be_picked_for_test)
566 ? GetWebContentsForRenderFrameHost(GetProfile(), render_frame_host()) 494 test_paths = *g_paths_to_be_picked_for_test;
567 : GetAssociatedWebContents(); 495
568 if (!web_contents) { 496 content::BrowserThread::PostTask(
569 error_ = kInvalidCallingPage; 497 content::BrowserThread::UI, FROM_HERE,
570 SendResponse(false); 498 test_paths.size() > 0
499 ? base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected,
500 this, test_paths)
501 : base::BindOnce(
502 &FileSystemChooseEntryFunction::FileSelectionCanceled, this));
571 return; 503 return;
572 } 504 }
573 505
574 // The file picker will hold a reference to this function instance, preventing 506 // The callbacks passed to the dialog will retain references to this
575 // its destruction (and subsequent sending of the function response) until the 507 // UIThreadExtenisonFunction, preventing its destruction (and subsequent
576 // user has selected a file or cancelled the picker. At that point, the picker 508 // sending of the function response) until the user has selected a file or
577 // will delete itself, which will also free the function instance. 509 // cancelled the picker.
578 new FilePicker(this, web_contents, initial_path_, file_type_info, 510 if (!ShowSelectFileDialog(
579 picker_type); 511 this, picker_type, initial_path_, &file_type_info,
512 base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected, this),
513 base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
514 this))) {
515 error_ = kInvalidCallingPage;
516 SendResponse(false);
517 }
580 } 518 }
581 519
582 // static 520 // static
583 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( 521 void FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
584 base::FilePath* path) { 522 base::FilePath* path) {
585 g_skip_picker_for_test = true; 523 g_skip_picker_for_test = true;
586 g_use_suggested_path_for_test = false; 524 g_use_suggested_path_for_test = false;
587 g_path_to_be_picked_for_test = path; 525 g_path_to_be_picked_for_test = path;
588 g_paths_to_be_picked_for_test = NULL; 526 g_paths_to_be_picked_for_test = NULL;
589 } 527 }
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 return RespondNow(Error(kNotSupportedOnNonKioskSessionError)); 1173 return RespondNow(Error(kNotSupportedOnNonKioskSessionError));
1236 std::vector<api::file_system::Volume> result_volume_list; 1174 std::vector<api::file_system::Volume> result_volume_list;
1237 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list); 1175 FillVolumeList(chrome_details_.GetProfile(), &result_volume_list);
1238 1176
1239 return RespondNow(ArgumentList( 1177 return RespondNow(ArgumentList(
1240 api::file_system::GetVolumeList::Results::Create(result_volume_list))); 1178 api::file_system::GetVolumeList::Results::Create(result_volume_list)));
1241 } 1179 }
1242 #endif 1180 #endif
1243 1181
1244 } // namespace extensions 1182 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/file_system/file_system_api.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698