OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/shell_dialogs/select_file_dialog_win.h" | 5 #include "ui/shell_dialogs/select_file_dialog_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <commdlg.h> | 8 #include <commdlg.h> |
9 #include <shlobj.h> | 9 #include <shlobj.h> |
10 | 10 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 return false; | 76 return false; |
77 } | 77 } |
78 | 78 |
79 return metro_get_save_file_name(ofn) == TRUE; | 79 return metro_get_save_file_name(ofn) == TRUE; |
80 } else { | 80 } else { |
81 return GetSaveFileName(ofn) == TRUE; | 81 return GetSaveFileName(ofn) == TRUE; |
82 } | 82 } |
83 } | 83 } |
84 | 84 |
85 // Distinguish directories from regular files. | 85 // Distinguish directories from regular files. |
86 bool IsDirectory(const FilePath& path) { | 86 bool IsDirectory(const base::FilePath& path) { |
87 base::PlatformFileInfo file_info; | 87 base::PlatformFileInfo file_info; |
88 return file_util::GetFileInfo(path, &file_info) ? | 88 return file_util::GetFileInfo(path, &file_info) ? |
89 file_info.is_directory : file_util::EndsWithSeparator(path); | 89 file_info.is_directory : file_util::EndsWithSeparator(path); |
90 } | 90 } |
91 | 91 |
92 // Get the file type description from the registry. This will be "Text Document" | 92 // Get the file type description from the registry. This will be "Text Document" |
93 // for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't | 93 // for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't |
94 // have an entry for the file type, we return false, true if the description was | 94 // have an entry for the file type, we return false, true if the description was |
95 // found. 'file_ext' must be in form ".txt". | 95 // found. 'file_ext' must be in form ".txt". |
96 static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext, | 96 static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext, |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 const std::wstring& suggested_name, | 259 const std::wstring& suggested_name, |
260 const std::wstring& filter, | 260 const std::wstring& filter, |
261 const std::wstring& def_ext, | 261 const std::wstring& def_ext, |
262 bool ignore_suggested_ext, | 262 bool ignore_suggested_ext, |
263 unsigned* index, | 263 unsigned* index, |
264 std::wstring* final_name) { | 264 std::wstring* final_name) { |
265 DCHECK(final_name); | 265 DCHECK(final_name); |
266 // Having an empty filter makes for a bad user experience. We should always | 266 // Having an empty filter makes for a bad user experience. We should always |
267 // specify a filter when saving. | 267 // specify a filter when saving. |
268 DCHECK(!filter.empty()); | 268 DCHECK(!filter.empty()); |
269 const FilePath suggested_path(suggested_name); | 269 const base::FilePath suggested_path(suggested_name); |
270 std::wstring file_part = suggested_path.BaseName().value(); | 270 std::wstring file_part = suggested_path.BaseName().value(); |
271 // If the suggested_name is a root directory, file_part will be '\', and the | 271 // If the suggested_name is a root directory, file_part will be '\', and the |
272 // call to GetSaveFileName below will fail. | 272 // call to GetSaveFileName below will fail. |
273 if (file_part.size() == 1 && file_part[0] == L'\\') | 273 if (file_part.size() == 1 && file_part[0] == L'\\') |
274 file_part.clear(); | 274 file_part.clear(); |
275 | 275 |
276 // The size of the in/out buffer in number of characters we pass to win32 | 276 // The size of the in/out buffer in number of characters we pass to win32 |
277 // GetSaveFileName. From MSDN "The buffer must be large enough to store the | 277 // GetSaveFileName. From MSDN "The buffer must be large enough to store the |
278 // path and file name string or strings, including the terminating NULL | 278 // path and file name string or strings, including the terminating NULL |
279 // character. ... The buffer should be at least 256 characters long.". | 279 // character. ... The buffer should be at least 256 characters long.". |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 // will start the dialog in the "C:\Documents and Settings\jojo\My Documents\" | 382 // will start the dialog in the "C:\Documents and Settings\jojo\My Documents\" |
383 // directory, and filter for .png file types. | 383 // directory, and filter for .png file types. |
384 // 'owner' is the window to which the dialog box is modal, NULL for a modeless | 384 // 'owner' is the window to which the dialog box is modal, NULL for a modeless |
385 // dialog box. | 385 // dialog box. |
386 // On success, returns true and 'final_name' contains the full path of the file | 386 // On success, returns true and 'final_name' contains the full path of the file |
387 // that the user chose. On error, returns false, and 'final_name' is not | 387 // that the user chose. On error, returns false, and 'final_name' is not |
388 // modified. | 388 // modified. |
389 bool SaveFileAs(HWND owner, | 389 bool SaveFileAs(HWND owner, |
390 const std::wstring& suggested_name, | 390 const std::wstring& suggested_name, |
391 std::wstring* final_name) { | 391 std::wstring* final_name) { |
392 std::wstring file_ext = FilePath(suggested_name).Extension().insert(0, L"*"); | 392 std::wstring file_ext = |
| 393 base::FilePath(suggested_name).Extension().insert(0, L"*"); |
393 std::wstring filter = FormatFilterForExtensions( | 394 std::wstring filter = FormatFilterForExtensions( |
394 std::vector<std::wstring>(1, file_ext), | 395 std::vector<std::wstring>(1, file_ext), |
395 std::vector<std::wstring>(), | 396 std::vector<std::wstring>(), |
396 true); | 397 true); |
397 unsigned index = 1; | 398 unsigned index = 1; |
398 return SaveFileAsWithFilter(owner, | 399 return SaveFileAsWithFilter(owner, |
399 suggested_name, | 400 suggested_name, |
400 filter, | 401 filter, |
401 L"", | 402 L"", |
402 false, | 403 false, |
403 &index, | 404 &index, |
404 final_name); | 405 final_name); |
405 } | 406 } |
406 | 407 |
407 // Implementation of SelectFileDialog that shows a Windows common dialog for | 408 // Implementation of SelectFileDialog that shows a Windows common dialog for |
408 // choosing a file or folder. | 409 // choosing a file or folder. |
409 class SelectFileDialogImpl : public ui::SelectFileDialog, | 410 class SelectFileDialogImpl : public ui::SelectFileDialog, |
410 public ui::BaseShellDialogImpl { | 411 public ui::BaseShellDialogImpl { |
411 public: | 412 public: |
412 explicit SelectFileDialogImpl(Listener* listener, | 413 explicit SelectFileDialogImpl(Listener* listener, |
413 ui::SelectFilePolicy* policy); | 414 ui::SelectFilePolicy* policy); |
414 | 415 |
415 // BaseShellDialog implementation: | 416 // BaseShellDialog implementation: |
416 virtual bool IsRunning(gfx::NativeWindow owning_hwnd) const OVERRIDE; | 417 virtual bool IsRunning(gfx::NativeWindow owning_hwnd) const OVERRIDE; |
417 virtual void ListenerDestroyed() OVERRIDE; | 418 virtual void ListenerDestroyed() OVERRIDE; |
418 | 419 |
419 protected: | 420 protected: |
420 // SelectFileDialog implementation: | 421 // SelectFileDialog implementation: |
421 virtual void SelectFileImpl(Type type, | 422 virtual void SelectFileImpl( |
422 const string16& title, | 423 Type type, |
423 const FilePath& default_path, | 424 const string16& title, |
424 const FileTypeInfo* file_types, | 425 const base::FilePath& default_path, |
425 int file_type_index, | 426 const FileTypeInfo* file_types, |
426 const FilePath::StringType& default_extension, | 427 int file_type_index, |
427 gfx::NativeWindow owning_window, | 428 const base::FilePath::StringType& default_extension, |
428 void* params) OVERRIDE; | 429 gfx::NativeWindow owning_window, |
| 430 void* params) OVERRIDE; |
429 | 431 |
430 private: | 432 private: |
431 virtual ~SelectFileDialogImpl(); | 433 virtual ~SelectFileDialogImpl(); |
432 | 434 |
433 // A struct for holding all the state necessary for displaying a Save dialog. | 435 // A struct for holding all the state necessary for displaying a Save dialog. |
434 struct ExecuteSelectParams { | 436 struct ExecuteSelectParams { |
435 ExecuteSelectParams(Type type, | 437 ExecuteSelectParams(Type type, |
436 const std::wstring& title, | 438 const std::wstring& title, |
437 const FilePath& default_path, | 439 const base::FilePath& default_path, |
438 const FileTypeInfo* file_types, | 440 const FileTypeInfo* file_types, |
439 int file_type_index, | 441 int file_type_index, |
440 const std::wstring& default_extension, | 442 const std::wstring& default_extension, |
441 RunState run_state, | 443 RunState run_state, |
442 HWND owner, | 444 HWND owner, |
443 void* params) | 445 void* params) |
444 : type(type), | 446 : type(type), |
445 title(title), | 447 title(title), |
446 default_path(default_path), | 448 default_path(default_path), |
447 file_type_index(file_type_index), | 449 file_type_index(file_type_index), |
448 default_extension(default_extension), | 450 default_extension(default_extension), |
449 run_state(run_state), | 451 run_state(run_state), |
450 ui_proxy(MessageLoopForUI::current()->message_loop_proxy()), | 452 ui_proxy(MessageLoopForUI::current()->message_loop_proxy()), |
451 owner(owner), | 453 owner(owner), |
452 params(params) { | 454 params(params) { |
453 if (file_types) | 455 if (file_types) |
454 this->file_types = *file_types; | 456 this->file_types = *file_types; |
455 } | 457 } |
456 SelectFileDialog::Type type; | 458 SelectFileDialog::Type type; |
457 std::wstring title; | 459 std::wstring title; |
458 FilePath default_path; | 460 base::FilePath default_path; |
459 FileTypeInfo file_types; | 461 FileTypeInfo file_types; |
460 int file_type_index; | 462 int file_type_index; |
461 std::wstring default_extension; | 463 std::wstring default_extension; |
462 RunState run_state; | 464 RunState run_state; |
463 scoped_refptr<base::MessageLoopProxy> ui_proxy; | 465 scoped_refptr<base::MessageLoopProxy> ui_proxy; |
464 HWND owner; | 466 HWND owner; |
465 void* params; | 467 void* params; |
466 }; | 468 }; |
467 | 469 |
468 // Shows the file selection dialog modal to |owner| and calls the result | 470 // Shows the file selection dialog modal to |owner| and calls the result |
469 // back on the ui thread. Run on the dialog thread. | 471 // back on the ui thread. Run on the dialog thread. |
470 void ExecuteSelectFile(const ExecuteSelectParams& params); | 472 void ExecuteSelectFile(const ExecuteSelectParams& params); |
471 | 473 |
472 // Notifies the listener that a folder was chosen. Run on the ui thread. | 474 // Notifies the listener that a folder was chosen. Run on the ui thread. |
473 void FileSelected(const FilePath& path, int index, | 475 void FileSelected(const base::FilePath& path, int index, |
474 void* params, RunState run_state); | 476 void* params, RunState run_state); |
475 | 477 |
476 // Notifies listener that multiple files were chosen. Run on the ui thread. | 478 // Notifies listener that multiple files were chosen. Run on the ui thread. |
477 void MultiFilesSelected(const std::vector<FilePath>& paths, void* params, | 479 void MultiFilesSelected(const std::vector<base::FilePath>& paths, |
| 480 void* params, |
478 RunState run_state); | 481 RunState run_state); |
479 | 482 |
480 // Notifies the listener that no file was chosen (the action was canceled). | 483 // Notifies the listener that no file was chosen (the action was canceled). |
481 // Run on the ui thread. | 484 // Run on the ui thread. |
482 void FileNotSelected(void* params, RunState run_state); | 485 void FileNotSelected(void* params, RunState run_state); |
483 | 486 |
484 // Runs a Folder selection dialog box, passes back the selected folder in | 487 // Runs a Folder selection dialog box, passes back the selected folder in |
485 // |path| and returns true if the user clicks OK. If the user cancels the | 488 // |path| and returns true if the user clicks OK. If the user cancels the |
486 // dialog box the value in |path| is not modified and returns false. |title| | 489 // dialog box the value in |path| is not modified and returns false. |title| |
487 // is the user-supplied title text to show for the dialog box. Run on the | 490 // is the user-supplied title text to show for the dialog box. Run on the |
488 // dialog thread. | 491 // dialog thread. |
489 bool RunSelectFolderDialog(const std::wstring& title, | 492 bool RunSelectFolderDialog(const std::wstring& title, |
490 HWND owner, | 493 HWND owner, |
491 FilePath* path); | 494 base::FilePath* path); |
492 | 495 |
493 // Runs an Open file dialog box, with similar semantics for input paramaters | 496 // Runs an Open file dialog box, with similar semantics for input paramaters |
494 // as RunSelectFolderDialog. | 497 // as RunSelectFolderDialog. |
495 bool RunOpenFileDialog(const std::wstring& title, | 498 bool RunOpenFileDialog(const std::wstring& title, |
496 const std::wstring& filters, | 499 const std::wstring& filters, |
497 HWND owner, | 500 HWND owner, |
498 FilePath* path); | 501 base::FilePath* path); |
499 | 502 |
500 // Runs an Open file dialog box that supports multi-select, with similar | 503 // Runs an Open file dialog box that supports multi-select, with similar |
501 // semantics for input paramaters as RunOpenFileDialog. | 504 // semantics for input paramaters as RunOpenFileDialog. |
502 bool RunOpenMultiFileDialog(const std::wstring& title, | 505 bool RunOpenMultiFileDialog(const std::wstring& title, |
503 const std::wstring& filter, | 506 const std::wstring& filter, |
504 HWND owner, | 507 HWND owner, |
505 std::vector<FilePath>* paths); | 508 std::vector<base::FilePath>* paths); |
506 | 509 |
507 // The callback function for when the select folder dialog is opened. | 510 // The callback function for when the select folder dialog is opened. |
508 static int CALLBACK BrowseCallbackProc(HWND window, UINT message, | 511 static int CALLBACK BrowseCallbackProc(HWND window, UINT message, |
509 LPARAM parameter, | 512 LPARAM parameter, |
510 LPARAM data); | 513 LPARAM data); |
511 | 514 |
512 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; | 515 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; |
513 | 516 |
514 // Returns the filter to be used while displaying the open/save file dialog. | 517 // Returns the filter to be used while displaying the open/save file dialog. |
515 // This is computed from the extensions for the file types being opened. | 518 // This is computed from the extensions for the file types being opened. |
(...skipping 10 matching lines...) Expand all Loading... |
526 BaseShellDialogImpl(), | 529 BaseShellDialogImpl(), |
527 has_multiple_file_type_choices_(false) { | 530 has_multiple_file_type_choices_(false) { |
528 } | 531 } |
529 | 532 |
530 SelectFileDialogImpl::~SelectFileDialogImpl() { | 533 SelectFileDialogImpl::~SelectFileDialogImpl() { |
531 } | 534 } |
532 | 535 |
533 void SelectFileDialogImpl::SelectFileImpl( | 536 void SelectFileDialogImpl::SelectFileImpl( |
534 Type type, | 537 Type type, |
535 const string16& title, | 538 const string16& title, |
536 const FilePath& default_path, | 539 const base::FilePath& default_path, |
537 const FileTypeInfo* file_types, | 540 const FileTypeInfo* file_types, |
538 int file_type_index, | 541 int file_type_index, |
539 const FilePath::StringType& default_extension, | 542 const base::FilePath::StringType& default_extension, |
540 gfx::NativeWindow owning_window, | 543 gfx::NativeWindow owning_window, |
541 void* params) { | 544 void* params) { |
542 has_multiple_file_type_choices_ = | 545 has_multiple_file_type_choices_ = |
543 file_types ? file_types->extensions.size() > 1 : true; | 546 file_types ? file_types->extensions.size() > 1 : true; |
544 #if defined(USE_AURA) | 547 #if defined(USE_AURA) |
545 // If the owning_window passed in is in metro then we need to forward the | 548 // If the owning_window passed in is in metro then we need to forward the |
546 // file open/save operations to metro. | 549 // file open/save operations to metro. |
547 if (GetShellDialogsDelegate() && | 550 if (GetShellDialogsDelegate() && |
548 GetShellDialogsDelegate()->IsWindowInMetro(owning_window)) { | 551 GetShellDialogsDelegate()->IsWindowInMetro(owning_window)) { |
549 if (type == SELECT_SAVEAS_FILE) { | 552 if (type == SELECT_SAVEAS_FILE) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 void SelectFileDialogImpl::ListenerDestroyed() { | 607 void SelectFileDialogImpl::ListenerDestroyed() { |
605 // Our associated listener has gone away, so we shouldn't call back to it if | 608 // Our associated listener has gone away, so we shouldn't call back to it if |
606 // our worker thread returns after the listener is dead. | 609 // our worker thread returns after the listener is dead. |
607 listener_ = NULL; | 610 listener_ = NULL; |
608 } | 611 } |
609 | 612 |
610 void SelectFileDialogImpl::ExecuteSelectFile( | 613 void SelectFileDialogImpl::ExecuteSelectFile( |
611 const ExecuteSelectParams& params) { | 614 const ExecuteSelectParams& params) { |
612 string16 filter = GetFilterForFileTypes(params.file_types); | 615 string16 filter = GetFilterForFileTypes(params.file_types); |
613 | 616 |
614 FilePath path = params.default_path; | 617 base::FilePath path = params.default_path; |
615 bool success = false; | 618 bool success = false; |
616 unsigned filter_index = params.file_type_index; | 619 unsigned filter_index = params.file_type_index; |
617 if (params.type == SELECT_FOLDER) { | 620 if (params.type == SELECT_FOLDER) { |
618 success = RunSelectFolderDialog(params.title, | 621 success = RunSelectFolderDialog(params.title, |
619 params.run_state.owner, | 622 params.run_state.owner, |
620 &path); | 623 &path); |
621 } else if (params.type == SELECT_SAVEAS_FILE) { | 624 } else if (params.type == SELECT_SAVEAS_FILE) { |
622 std::wstring path_as_wstring = path.value(); | 625 std::wstring path_as_wstring = path.value(); |
623 success = SaveFileAsWithFilter(params.run_state.owner, | 626 success = SaveFileAsWithFilter(params.run_state.owner, |
624 params.default_path.value(), filter, | 627 params.default_path.value(), filter, |
625 params.default_extension, false, &filter_index, &path_as_wstring); | 628 params.default_extension, false, &filter_index, &path_as_wstring); |
626 if (success) | 629 if (success) |
627 path = FilePath(path_as_wstring); | 630 path = base::FilePath(path_as_wstring); |
628 DisableOwner(params.run_state.owner); | 631 DisableOwner(params.run_state.owner); |
629 } else if (params.type == SELECT_OPEN_FILE) { | 632 } else if (params.type == SELECT_OPEN_FILE) { |
630 success = RunOpenFileDialog(params.title, filter, | 633 success = RunOpenFileDialog(params.title, filter, |
631 params.run_state.owner, &path); | 634 params.run_state.owner, &path); |
632 } else if (params.type == SELECT_OPEN_MULTI_FILE) { | 635 } else if (params.type == SELECT_OPEN_MULTI_FILE) { |
633 std::vector<FilePath> paths; | 636 std::vector<base::FilePath> paths; |
634 if (RunOpenMultiFileDialog(params.title, filter, | 637 if (RunOpenMultiFileDialog(params.title, filter, |
635 params.run_state.owner, &paths)) { | 638 params.run_state.owner, &paths)) { |
636 params.ui_proxy->PostTask( | 639 params.ui_proxy->PostTask( |
637 FROM_HERE, | 640 FROM_HERE, |
638 base::Bind(&SelectFileDialogImpl::MultiFilesSelected, this, paths, | 641 base::Bind(&SelectFileDialogImpl::MultiFilesSelected, this, paths, |
639 params.params, params.run_state)); | 642 params.params, params.run_state)); |
640 return; | 643 return; |
641 } | 644 } |
642 } | 645 } |
643 | 646 |
644 if (success) { | 647 if (success) { |
645 params.ui_proxy->PostTask( | 648 params.ui_proxy->PostTask( |
646 FROM_HERE, | 649 FROM_HERE, |
647 base::Bind(&SelectFileDialogImpl::FileSelected, this, path, | 650 base::Bind(&SelectFileDialogImpl::FileSelected, this, path, |
648 filter_index, params.params, params.run_state)); | 651 filter_index, params.params, params.run_state)); |
649 } else { | 652 } else { |
650 params.ui_proxy->PostTask( | 653 params.ui_proxy->PostTask( |
651 FROM_HERE, | 654 FROM_HERE, |
652 base::Bind(&SelectFileDialogImpl::FileNotSelected, this, params.params, | 655 base::Bind(&SelectFileDialogImpl::FileNotSelected, this, params.params, |
653 params.run_state)); | 656 params.run_state)); |
654 } | 657 } |
655 } | 658 } |
656 | 659 |
657 void SelectFileDialogImpl::FileSelected(const FilePath& selected_folder, | 660 void SelectFileDialogImpl::FileSelected(const base::FilePath& selected_folder, |
658 int index, | 661 int index, |
659 void* params, | 662 void* params, |
660 RunState run_state) { | 663 RunState run_state) { |
661 if (listener_) | 664 if (listener_) |
662 listener_->FileSelected(selected_folder, index, params); | 665 listener_->FileSelected(selected_folder, index, params); |
663 EndRun(run_state); | 666 EndRun(run_state); |
664 } | 667 } |
665 | 668 |
666 void SelectFileDialogImpl::MultiFilesSelected( | 669 void SelectFileDialogImpl::MultiFilesSelected( |
667 const std::vector<FilePath>& selected_files, | 670 const std::vector<base::FilePath>& selected_files, |
668 void* params, | 671 void* params, |
669 RunState run_state) { | 672 RunState run_state) { |
670 if (listener_) | 673 if (listener_) |
671 listener_->MultiFilesSelected(selected_files, params); | 674 listener_->MultiFilesSelected(selected_files, params); |
672 EndRun(run_state); | 675 EndRun(run_state); |
673 } | 676 } |
674 | 677 |
675 void SelectFileDialogImpl::FileNotSelected(void* params, RunState run_state) { | 678 void SelectFileDialogImpl::FileNotSelected(void* params, RunState run_state) { |
676 if (listener_) | 679 if (listener_) |
677 listener_->FileSelectionCanceled(params); | 680 listener_->FileSelectionCanceled(params); |
678 EndRun(run_state); | 681 EndRun(run_state); |
679 } | 682 } |
680 | 683 |
681 int CALLBACK SelectFileDialogImpl::BrowseCallbackProc(HWND window, | 684 int CALLBACK SelectFileDialogImpl::BrowseCallbackProc(HWND window, |
682 UINT message, | 685 UINT message, |
683 LPARAM parameter, | 686 LPARAM parameter, |
684 LPARAM data) { | 687 LPARAM data) { |
685 if (message == BFFM_INITIALIZED) { | 688 if (message == BFFM_INITIALIZED) { |
686 // WParam is TRUE since passing a path. | 689 // WParam is TRUE since passing a path. |
687 // data lParam member of the BROWSEINFO structure. | 690 // data lParam member of the BROWSEINFO structure. |
688 SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data); | 691 SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data); |
689 } | 692 } |
690 return 0; | 693 return 0; |
691 } | 694 } |
692 | 695 |
693 bool SelectFileDialogImpl::RunSelectFolderDialog(const std::wstring& title, | 696 bool SelectFileDialogImpl::RunSelectFolderDialog(const std::wstring& title, |
694 HWND owner, | 697 HWND owner, |
695 FilePath* path) { | 698 base::FilePath* path) { |
696 DCHECK(path); | 699 DCHECK(path); |
697 | 700 |
698 wchar_t dir_buffer[MAX_PATH + 1]; | 701 wchar_t dir_buffer[MAX_PATH + 1]; |
699 | 702 |
700 bool result = false; | 703 bool result = false; |
701 BROWSEINFO browse_info = {0}; | 704 BROWSEINFO browse_info = {0}; |
702 browse_info.hwndOwner = owner; | 705 browse_info.hwndOwner = owner; |
703 browse_info.lpszTitle = title.c_str(); | 706 browse_info.lpszTitle = title.c_str(); |
704 browse_info.pszDisplayName = dir_buffer; | 707 browse_info.pszDisplayName = dir_buffer; |
705 browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS; | 708 browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS; |
706 | 709 |
707 if (path->value().length()) { | 710 if (path->value().length()) { |
708 // Highlight the current value. | 711 // Highlight the current value. |
709 browse_info.lParam = (LPARAM)path->value().c_str(); | 712 browse_info.lParam = (LPARAM)path->value().c_str(); |
710 browse_info.lpfn = &BrowseCallbackProc; | 713 browse_info.lpfn = &BrowseCallbackProc; |
711 } | 714 } |
712 | 715 |
713 LPITEMIDLIST list = SHBrowseForFolder(&browse_info); | 716 LPITEMIDLIST list = SHBrowseForFolder(&browse_info); |
714 DisableOwner(owner); | 717 DisableOwner(owner); |
715 if (list) { | 718 if (list) { |
716 STRRET out_dir_buffer; | 719 STRRET out_dir_buffer; |
717 ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer)); | 720 ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer)); |
718 out_dir_buffer.uType = STRRET_WSTR; | 721 out_dir_buffer.uType = STRRET_WSTR; |
719 base::win::ScopedComPtr<IShellFolder> shell_folder; | 722 base::win::ScopedComPtr<IShellFolder> shell_folder; |
720 if (SHGetDesktopFolder(shell_folder.Receive()) == NOERROR) { | 723 if (SHGetDesktopFolder(shell_folder.Receive()) == NOERROR) { |
721 HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING, | 724 HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING, |
722 &out_dir_buffer); | 725 &out_dir_buffer); |
723 if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) { | 726 if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) { |
724 *path = FilePath(out_dir_buffer.pOleStr); | 727 *path = base::FilePath(out_dir_buffer.pOleStr); |
725 CoTaskMemFree(out_dir_buffer.pOleStr); | 728 CoTaskMemFree(out_dir_buffer.pOleStr); |
726 result = true; | 729 result = true; |
727 } else { | 730 } else { |
728 // Use old way if we don't get what we want. | 731 // Use old way if we don't get what we want. |
729 wchar_t old_out_dir_buffer[MAX_PATH + 1]; | 732 wchar_t old_out_dir_buffer[MAX_PATH + 1]; |
730 if (SHGetPathFromIDList(list, old_out_dir_buffer)) { | 733 if (SHGetPathFromIDList(list, old_out_dir_buffer)) { |
731 *path = FilePath(old_out_dir_buffer); | 734 *path = base::FilePath(old_out_dir_buffer); |
732 result = true; | 735 result = true; |
733 } | 736 } |
734 } | 737 } |
735 | 738 |
736 // According to MSDN, win2000 will not resolve shortcuts, so we do it | 739 // According to MSDN, win2000 will not resolve shortcuts, so we do it |
737 // ourself. | 740 // ourself. |
738 base::win::ResolveShortcut(*path, path, NULL); | 741 base::win::ResolveShortcut(*path, path, NULL); |
739 } | 742 } |
740 CoTaskMemFree(list); | 743 CoTaskMemFree(list); |
741 } | 744 } |
742 return result; | 745 return result; |
743 } | 746 } |
744 | 747 |
745 bool SelectFileDialogImpl::RunOpenFileDialog( | 748 bool SelectFileDialogImpl::RunOpenFileDialog( |
746 const std::wstring& title, | 749 const std::wstring& title, |
747 const std::wstring& filter, | 750 const std::wstring& filter, |
748 HWND owner, | 751 HWND owner, |
749 FilePath* path) { | 752 base::FilePath* path) { |
750 OPENFILENAME ofn; | 753 OPENFILENAME ofn; |
751 // We must do this otherwise the ofn's FlagsEx may be initialized to random | 754 // We must do this otherwise the ofn's FlagsEx may be initialized to random |
752 // junk in release builds which can cause the Places Bar not to show up! | 755 // junk in release builds which can cause the Places Bar not to show up! |
753 ZeroMemory(&ofn, sizeof(ofn)); | 756 ZeroMemory(&ofn, sizeof(ofn)); |
754 ofn.lStructSize = sizeof(ofn); | 757 ofn.lStructSize = sizeof(ofn); |
755 ofn.hwndOwner = owner; | 758 ofn.hwndOwner = owner; |
756 | 759 |
757 wchar_t filename[MAX_PATH]; | 760 wchar_t filename[MAX_PATH]; |
758 // According to http://support.microsoft.com/?scid=kb;en-us;222003&x=8&y=12, | 761 // According to http://support.microsoft.com/?scid=kb;en-us;222003&x=8&y=12, |
759 // The lpstrFile Buffer MUST be NULL Terminated. | 762 // The lpstrFile Buffer MUST be NULL Terminated. |
760 filename[0] = 0; | 763 filename[0] = 0; |
761 // Define the dir in here to keep the string buffer pointer pointed to | 764 // Define the dir in here to keep the string buffer pointer pointed to |
762 // ofn.lpstrInitialDir available during the period of running the | 765 // ofn.lpstrInitialDir available during the period of running the |
763 // GetOpenFileName. | 766 // GetOpenFileName. |
764 FilePath dir; | 767 base::FilePath dir; |
765 // Use lpstrInitialDir to specify the initial directory | 768 // Use lpstrInitialDir to specify the initial directory |
766 if (!path->empty()) { | 769 if (!path->empty()) { |
767 if (IsDirectory(*path)) { | 770 if (IsDirectory(*path)) { |
768 ofn.lpstrInitialDir = path->value().c_str(); | 771 ofn.lpstrInitialDir = path->value().c_str(); |
769 } else { | 772 } else { |
770 dir = path->DirName(); | 773 dir = path->DirName(); |
771 ofn.lpstrInitialDir = dir.value().c_str(); | 774 ofn.lpstrInitialDir = dir.value().c_str(); |
772 // Only pure filename can be put in lpstrFile field. | 775 // Only pure filename can be put in lpstrFile field. |
773 base::wcslcpy(filename, path->BaseName().value().c_str(), | 776 base::wcslcpy(filename, path->BaseName().value().c_str(), |
774 arraysize(filename)); | 777 arraysize(filename)); |
775 } | 778 } |
776 } | 779 } |
777 | 780 |
778 ofn.lpstrFile = filename; | 781 ofn.lpstrFile = filename; |
779 ofn.nMaxFile = MAX_PATH; | 782 ofn.nMaxFile = MAX_PATH; |
780 | 783 |
781 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory | 784 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory |
782 // without having to close Chrome first. | 785 // without having to close Chrome first. |
783 ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; | 786 ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; |
784 | 787 |
785 if (!filter.empty()) | 788 if (!filter.empty()) |
786 ofn.lpstrFilter = filter.c_str(); | 789 ofn.lpstrFilter = filter.c_str(); |
787 bool success = CallGetOpenFileName(&ofn); | 790 bool success = CallGetOpenFileName(&ofn); |
788 DisableOwner(owner); | 791 DisableOwner(owner); |
789 if (success) | 792 if (success) |
790 *path = FilePath(filename); | 793 *path = base::FilePath(filename); |
791 return success; | 794 return success; |
792 } | 795 } |
793 | 796 |
794 bool SelectFileDialogImpl::RunOpenMultiFileDialog( | 797 bool SelectFileDialogImpl::RunOpenMultiFileDialog( |
795 const std::wstring& title, | 798 const std::wstring& title, |
796 const std::wstring& filter, | 799 const std::wstring& filter, |
797 HWND owner, | 800 HWND owner, |
798 std::vector<FilePath>* paths) { | 801 std::vector<base::FilePath>* paths) { |
799 OPENFILENAME ofn; | 802 OPENFILENAME ofn; |
800 // We must do this otherwise the ofn's FlagsEx may be initialized to random | 803 // We must do this otherwise the ofn's FlagsEx may be initialized to random |
801 // junk in release builds which can cause the Places Bar not to show up! | 804 // junk in release builds which can cause the Places Bar not to show up! |
802 ZeroMemory(&ofn, sizeof(ofn)); | 805 ZeroMemory(&ofn, sizeof(ofn)); |
803 ofn.lStructSize = sizeof(ofn); | 806 ofn.lStructSize = sizeof(ofn); |
804 ofn.hwndOwner = owner; | 807 ofn.hwndOwner = owner; |
805 | 808 |
806 scoped_array<wchar_t> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]); | 809 scoped_array<wchar_t> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]); |
807 filename[0] = 0; | 810 filename[0] = 0; |
808 | 811 |
809 ofn.lpstrFile = filename.get(); | 812 ofn.lpstrFile = filename.get(); |
810 ofn.nMaxFile = UNICODE_STRING_MAX_CHARS; | 813 ofn.nMaxFile = UNICODE_STRING_MAX_CHARS; |
811 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory | 814 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory |
812 // without having to close Chrome first. | 815 // without having to close Chrome first. |
813 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | 816 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
814 | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT; | 817 | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT; |
815 | 818 |
816 if (!filter.empty()) { | 819 if (!filter.empty()) { |
817 ofn.lpstrFilter = filter.c_str(); | 820 ofn.lpstrFilter = filter.c_str(); |
818 } | 821 } |
819 | 822 |
820 bool success = CallGetOpenFileName(&ofn); | 823 bool success = CallGetOpenFileName(&ofn); |
821 DisableOwner(owner); | 824 DisableOwner(owner); |
822 if (success) { | 825 if (success) { |
823 std::vector<FilePath> files; | 826 std::vector<base::FilePath> files; |
824 const wchar_t* selection = ofn.lpstrFile; | 827 const wchar_t* selection = ofn.lpstrFile; |
825 while (*selection) { // Empty string indicates end of list. | 828 while (*selection) { // Empty string indicates end of list. |
826 files.push_back(FilePath(selection)); | 829 files.push_back(base::FilePath(selection)); |
827 // Skip over filename and null-terminator. | 830 // Skip over filename and null-terminator. |
828 selection += files.back().value().length() + 1; | 831 selection += files.back().value().length() + 1; |
829 } | 832 } |
830 if (files.empty()) { | 833 if (files.empty()) { |
831 success = false; | 834 success = false; |
832 } else if (files.size() == 1) { | 835 } else if (files.size() == 1) { |
833 // When there is one file, it contains the path and filename. | 836 // When there is one file, it contains the path and filename. |
834 paths->swap(files); | 837 paths->swap(files); |
835 } else { | 838 } else { |
836 // Otherwise, the first string is the path, and the remainder are | 839 // Otherwise, the first string is the path, and the remainder are |
837 // filenames. | 840 // filenames. |
838 std::vector<FilePath>::iterator path = files.begin(); | 841 std::vector<base::FilePath>::iterator path = files.begin(); |
839 for (std::vector<FilePath>::iterator file = path + 1; | 842 for (std::vector<base::FilePath>::iterator file = path + 1; |
840 file != files.end(); ++file) { | 843 file != files.end(); ++file) { |
841 paths->push_back(path->Append(*file)); | 844 paths->push_back(path->Append(*file)); |
842 } | 845 } |
843 } | 846 } |
844 } | 847 } |
845 return success; | 848 return success; |
846 } | 849 } |
847 | 850 |
848 string16 SelectFileDialogImpl::GetFilterForFileTypes( | 851 string16 SelectFileDialogImpl::GetFilterForFileTypes( |
849 const FileTypeInfo& file_types) { | 852 const FileTypeInfo& file_types) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 const std::wstring& suggested_ext) { | 888 const std::wstring& suggested_ext) { |
886 DCHECK(!filename.empty()); | 889 DCHECK(!filename.empty()); |
887 std::wstring return_value = filename; | 890 std::wstring return_value = filename; |
888 | 891 |
889 // If we wanted a specific extension, but the user's filename deleted it or | 892 // If we wanted a specific extension, but the user's filename deleted it or |
890 // changed it to something that the system doesn't understand, re-append. | 893 // changed it to something that the system doesn't understand, re-append. |
891 // Careful: Checking net::GetMimeTypeFromExtension() will only find | 894 // Careful: Checking net::GetMimeTypeFromExtension() will only find |
892 // extensions with a known MIME type, which many "known" extensions on Windows | 895 // extensions with a known MIME type, which many "known" extensions on Windows |
893 // don't have. So we check directly for the "known extension" registry key. | 896 // don't have. So we check directly for the "known extension" registry key. |
894 std::wstring file_extension( | 897 std::wstring file_extension( |
895 GetExtensionWithoutLeadingDot(FilePath(filename).Extension())); | 898 GetExtensionWithoutLeadingDot(base::FilePath(filename).Extension())); |
896 std::wstring key(L"." + file_extension); | 899 std::wstring key(L"." + file_extension); |
897 if (!(filter_selected.empty() || filter_selected == L"*.*") && | 900 if (!(filter_selected.empty() || filter_selected == L"*.*") && |
898 !base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).Valid() && | 901 !base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).Valid() && |
899 file_extension != suggested_ext) { | 902 file_extension != suggested_ext) { |
900 if (return_value[return_value.length() - 1] != L'.') | 903 if (return_value[return_value.length() - 1] != L'.') |
901 return_value.append(L"."); | 904 return_value.append(L"."); |
902 return_value.append(suggested_ext); | 905 return_value.append(suggested_ext); |
903 } | 906 } |
904 | 907 |
905 // Strip any trailing dots, which Windows doesn't allow. | 908 // Strip any trailing dots, which Windows doesn't allow. |
906 size_t index = return_value.find_last_not_of(L'.'); | 909 size_t index = return_value.find_last_not_of(L'.'); |
907 if (index < return_value.size() - 1) | 910 if (index < return_value.size() - 1) |
908 return_value.resize(index + 1); | 911 return_value.resize(index + 1); |
909 | 912 |
910 return return_value; | 913 return return_value; |
911 } | 914 } |
912 | 915 |
913 SelectFileDialog* CreateWinSelectFileDialog( | 916 SelectFileDialog* CreateWinSelectFileDialog( |
914 SelectFileDialog::Listener* listener, | 917 SelectFileDialog::Listener* listener, |
915 SelectFilePolicy* policy) { | 918 SelectFilePolicy* policy) { |
916 return new SelectFileDialogImpl(listener, policy); | 919 return new SelectFileDialogImpl(listener, policy); |
917 } | 920 } |
918 | 921 |
919 } // namespace ui | 922 } // namespace ui |
OLD | NEW |