| 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 12 matching lines...) Expand all Loading... |
| 23 #include "base/win/metro.h" | 23 #include "base/win/metro.h" |
| 24 #include "base/win/registry.h" | 24 #include "base/win/registry.h" |
| 25 #include "base/win/scoped_comptr.h" | 25 #include "base/win/scoped_comptr.h" |
| 26 #include "base/win/shortcut.h" | 26 #include "base/win/shortcut.h" |
| 27 #include "base/win/windows_version.h" | 27 #include "base/win/windows_version.h" |
| 28 #include "grit/ui_strings.h" | 28 #include "grit/ui_strings.h" |
| 29 #include "ui/aura/window.h" | 29 #include "ui/aura/window.h" |
| 30 #include "ui/aura/window_event_dispatcher.h" | 30 #include "ui/aura/window_event_dispatcher.h" |
| 31 #include "ui/aura/window_tree_host.h" | 31 #include "ui/aura/window_tree_host.h" |
| 32 #include "ui/base/l10n/l10n_util.h" | 32 #include "ui/base/l10n/l10n_util.h" |
| 33 #include "ui/base/win/open_file_name_win.h" |
| 33 #include "ui/gfx/native_widget_types.h" | 34 #include "ui/gfx/native_widget_types.h" |
| 34 #include "ui/shell_dialogs/base_shell_dialog_win.h" | 35 #include "ui/shell_dialogs/base_shell_dialog_win.h" |
| 35 #include "ui/shell_dialogs/shell_dialogs_delegate.h" | 36 #include "ui/shell_dialogs/shell_dialogs_delegate.h" |
| 36 #include "win8/viewer/metro_viewer_process_host.h" | 37 #include "win8/viewer/metro_viewer_process_host.h" |
| 37 | 38 |
| 38 namespace { | 39 namespace { |
| 39 | 40 |
| 40 // Given |extension|, if it's not empty, then remove the leading dot. | 41 // Given |extension|, if it's not empty, then remove the leading dot. |
| 41 std::wstring GetExtensionWithoutLeadingDot(const std::wstring& extension) { | 42 std::wstring GetExtensionWithoutLeadingDot(const std::wstring& extension) { |
| 42 DCHECK(extension.empty() || extension[0] == L'.'); | 43 DCHECK(extension.empty() || extension[0] == L'.'); |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 CoTaskMemFree(list); | 767 CoTaskMemFree(list); |
| 767 } | 768 } |
| 768 return result; | 769 return result; |
| 769 } | 770 } |
| 770 | 771 |
| 771 bool SelectFileDialogImpl::RunOpenFileDialog( | 772 bool SelectFileDialogImpl::RunOpenFileDialog( |
| 772 const std::wstring& title, | 773 const std::wstring& title, |
| 773 const std::wstring& filter, | 774 const std::wstring& filter, |
| 774 HWND owner, | 775 HWND owner, |
| 775 base::FilePath* path) { | 776 base::FilePath* path) { |
| 776 OPENFILENAME ofn; | 777 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory |
| 777 // We must do this otherwise the ofn's FlagsEx may be initialized to random | 778 // without having to close Chrome first. |
| 778 // junk in release builds which can cause the Places Bar not to show up! | 779 ui::win::OpenFileName ofn(owner, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR); |
| 779 ZeroMemory(&ofn, sizeof(ofn)); | |
| 780 ofn.lStructSize = sizeof(ofn); | |
| 781 ofn.hwndOwner = owner; | |
| 782 | |
| 783 wchar_t filename[MAX_PATH]; | |
| 784 // According to http://support.microsoft.com/?scid=kb;en-us;222003&x=8&y=12, | |
| 785 // The lpstrFile Buffer MUST be NULL Terminated. | |
| 786 filename[0] = 0; | |
| 787 // Define the dir in here to keep the string buffer pointer pointed to | |
| 788 // ofn.lpstrInitialDir available during the period of running the | |
| 789 // GetOpenFileName. | |
| 790 base::FilePath dir; | |
| 791 // Use lpstrInitialDir to specify the initial directory | |
| 792 if (!path->empty()) { | 780 if (!path->empty()) { |
| 793 if (IsDirectory(*path)) { | 781 if (IsDirectory(*path)) |
| 794 ofn.lpstrInitialDir = path->value().c_str(); | 782 ofn.SetInitialSelection(*path, base::FilePath()); |
| 795 } else { | 783 else |
| 796 dir = path->DirName(); | 784 ofn.SetInitialSelection(path->DirName(), path->BaseName()); |
| 797 ofn.lpstrInitialDir = dir.value().c_str(); | |
| 798 // Only pure filename can be put in lpstrFile field. | |
| 799 base::wcslcpy(filename, path->BaseName().value().c_str(), | |
| 800 arraysize(filename)); | |
| 801 } | |
| 802 } | 785 } |
| 803 | 786 |
| 804 ofn.lpstrFile = filename; | |
| 805 ofn.nMaxFile = MAX_PATH; | |
| 806 | |
| 807 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory | |
| 808 // without having to close Chrome first. | |
| 809 ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR; | |
| 810 | |
| 811 if (!filter.empty()) | 787 if (!filter.empty()) |
| 812 ofn.lpstrFilter = filter.c_str(); | 788 ofn.Get()->lpstrFilter = filter.c_str(); |
| 813 bool success = CallGetOpenFileName(&ofn); | 789 bool success = CallGetOpenFileName(ofn.Get()); |
| 814 DisableOwner(owner); | 790 DisableOwner(owner); |
| 815 if (success) | 791 if (success) |
| 816 *path = base::FilePath(filename); | 792 *path = ofn.GetSingleResult(); |
| 817 return success; | 793 return success; |
| 818 } | 794 } |
| 819 | 795 |
| 820 bool SelectFileDialogImpl::RunOpenMultiFileDialog( | 796 bool SelectFileDialogImpl::RunOpenMultiFileDialog( |
| 821 const std::wstring& title, | 797 const std::wstring& title, |
| 822 const std::wstring& filter, | 798 const std::wstring& filter, |
| 823 HWND owner, | 799 HWND owner, |
| 824 std::vector<base::FilePath>* paths) { | 800 std::vector<base::FilePath>* paths) { |
| 825 OPENFILENAME ofn; | |
| 826 // We must do this otherwise the ofn's FlagsEx may be initialized to random | |
| 827 // junk in release builds which can cause the Places Bar not to show up! | |
| 828 ZeroMemory(&ofn, sizeof(ofn)); | |
| 829 ofn.lStructSize = sizeof(ofn); | |
| 830 ofn.hwndOwner = owner; | |
| 831 | |
| 832 scoped_ptr<wchar_t[]> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]); | |
| 833 filename[0] = 0; | |
| 834 | |
| 835 ofn.lpstrFile = filename.get(); | |
| 836 ofn.nMaxFile = UNICODE_STRING_MAX_CHARS; | |
| 837 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory | 801 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory |
| 838 // without having to close Chrome first. | 802 // without having to close Chrome first. |
| 839 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | 803 ui::win::OpenFileName ofn(owner, |
| 840 | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR; | 804 OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | |
| 805 OFN_EXPLORER | OFN_HIDEREADONLY | |
| 806 OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR); |
| 841 | 807 |
| 842 if (!filter.empty()) { | 808 if (!filter.empty()) |
| 843 ofn.lpstrFilter = filter.c_str(); | 809 ofn.Get()->lpstrFilter = filter.c_str(); |
| 810 |
| 811 base::FilePath directory; |
| 812 std::vector<base::FilePath> filenames; |
| 813 |
| 814 if (CallGetOpenFileName(ofn.Get())) |
| 815 ofn.GetResult(&directory, &filenames); |
| 816 DisableOwner(owner); |
| 817 |
| 818 for (std::vector<base::FilePath>::iterator it = filenames.begin(); |
| 819 it != filenames.end(); |
| 820 ++it) { |
| 821 paths->push_back(directory.Append(*it)); |
| 844 } | 822 } |
| 845 | 823 |
| 846 bool success = CallGetOpenFileName(&ofn); | 824 return !paths->empty(); |
| 847 DisableOwner(owner); | |
| 848 if (success) { | |
| 849 std::vector<base::FilePath> files; | |
| 850 const wchar_t* selection = ofn.lpstrFile; | |
| 851 while (*selection) { // Empty string indicates end of list. | |
| 852 files.push_back(base::FilePath(selection)); | |
| 853 // Skip over filename and null-terminator. | |
| 854 selection += files.back().value().length() + 1; | |
| 855 } | |
| 856 if (files.empty()) { | |
| 857 success = false; | |
| 858 } else if (files.size() == 1) { | |
| 859 // When there is one file, it contains the path and filename. | |
| 860 paths->swap(files); | |
| 861 } else { | |
| 862 // Otherwise, the first string is the path, and the remainder are | |
| 863 // filenames. | |
| 864 std::vector<base::FilePath>::iterator path = files.begin(); | |
| 865 for (std::vector<base::FilePath>::iterator file = path + 1; | |
| 866 file != files.end(); ++file) { | |
| 867 paths->push_back(path->Append(*file)); | |
| 868 } | |
| 869 } | |
| 870 } | |
| 871 return success; | |
| 872 } | 825 } |
| 873 | 826 |
| 874 base::string16 SelectFileDialogImpl::GetFilterForFileTypes( | 827 base::string16 SelectFileDialogImpl::GetFilterForFileTypes( |
| 875 const FileTypeInfo* file_types) { | 828 const FileTypeInfo* file_types) { |
| 876 if (!file_types) | 829 if (!file_types) |
| 877 return base::string16(); | 830 return base::string16(); |
| 878 | 831 |
| 879 std::vector<base::string16> exts; | 832 std::vector<base::string16> exts; |
| 880 for (size_t i = 0; i < file_types->extensions.size(); ++i) { | 833 for (size_t i = 0; i < file_types->extensions.size(); ++i) { |
| 881 const std::vector<base::string16>& inner_exts = file_types->extensions[i]; | 834 const std::vector<base::string16>& inner_exts = file_types->extensions[i]; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 return return_value; | 892 return return_value; |
| 940 } | 893 } |
| 941 | 894 |
| 942 SelectFileDialog* CreateWinSelectFileDialog( | 895 SelectFileDialog* CreateWinSelectFileDialog( |
| 943 SelectFileDialog::Listener* listener, | 896 SelectFileDialog::Listener* listener, |
| 944 SelectFilePolicy* policy) { | 897 SelectFilePolicy* policy) { |
| 945 return new SelectFileDialogImpl(listener, policy); | 898 return new SelectFileDialogImpl(listener, policy); |
| 946 } | 899 } |
| 947 | 900 |
| 948 } // namespace ui | 901 } // namespace ui |
| OLD | NEW |