Chromium Code Reviews| 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> | |
| 8 #include <commdlg.h> | |
| 9 #include <shlobj.h> | 7 #include <shlobj.h> |
| 10 | 8 |
| 11 #include <algorithm> | 9 #include <algorithm> |
| 12 #include <set> | 10 #include <set> |
| 13 | 11 |
| 14 #include "base/bind.h" | 12 #include "base/bind.h" |
| 15 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 16 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 17 #include "base/i18n/case_conversion.h" | 15 #include "base/i18n/case_conversion.h" |
| 18 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 31 #include "ui/aura/window_tree_host.h" | 29 #include "ui/aura/window_tree_host.h" |
| 32 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
| 33 #include "ui/base/win/open_file_name_win.h" | 31 #include "ui/base/win/open_file_name_win.h" |
| 34 #include "ui/gfx/native_widget_types.h" | 32 #include "ui/gfx/native_widget_types.h" |
| 35 #include "ui/shell_dialogs/base_shell_dialog_win.h" | 33 #include "ui/shell_dialogs/base_shell_dialog_win.h" |
| 36 #include "ui/shell_dialogs/shell_dialogs_delegate.h" | 34 #include "ui/shell_dialogs/shell_dialogs_delegate.h" |
| 37 #include "win8/viewer/metro_viewer_process_host.h" | 35 #include "win8/viewer/metro_viewer_process_host.h" |
| 38 | 36 |
| 39 namespace { | 37 namespace { |
| 40 | 38 |
| 39 bool CallBuiltinGetOpenFileName(OPENFILENAME* ofn) { | |
|
sky
2014/07/31 20:47:46
nit: don't indent this (same as 44 below).
erikwright (departed)
2014/08/01 13:53:15
Done.
| |
| 40 return GetOpenFileName(ofn) == TRUE; | |
| 41 } | |
| 42 | |
| 41 // Given |extension|, if it's not empty, then remove the leading dot. | 43 // Given |extension|, if it's not empty, then remove the leading dot. |
| 42 std::wstring GetExtensionWithoutLeadingDot(const std::wstring& extension) { | 44 std::wstring GetExtensionWithoutLeadingDot(const std::wstring& extension) { |
| 43 DCHECK(extension.empty() || extension[0] == L'.'); | 45 DCHECK(extension.empty() || extension[0] == L'.'); |
| 44 return extension.empty() ? extension : extension.substr(1); | 46 return extension.empty() ? extension : extension.substr(1); |
| 45 } | 47 } |
| 46 | 48 |
| 47 // Diverts to a metro-specific implementation as appropriate. | 49 // Diverts to a metro-specific implementation as appropriate. |
| 48 bool CallGetOpenFileName(OPENFILENAME* ofn) { | |
| 49 HMODULE metro_module = base::win::GetMetroModule(); | |
| 50 if (metro_module != NULL) { | |
| 51 typedef BOOL (*MetroGetOpenFileName)(OPENFILENAME*); | |
| 52 MetroGetOpenFileName metro_get_open_file_name = | |
| 53 reinterpret_cast<MetroGetOpenFileName>( | |
| 54 ::GetProcAddress(metro_module, "MetroGetOpenFileName")); | |
| 55 if (metro_get_open_file_name == NULL) { | |
| 56 NOTREACHED(); | |
| 57 return false; | |
| 58 } | |
| 59 | |
| 60 return metro_get_open_file_name(ofn) == TRUE; | |
| 61 } else { | |
| 62 return GetOpenFileName(ofn) == TRUE; | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 // Diverts to a metro-specific implementation as appropriate. | |
| 67 bool CallGetSaveFileName(OPENFILENAME* ofn) { | 50 bool CallGetSaveFileName(OPENFILENAME* ofn) { |
| 68 HMODULE metro_module = base::win::GetMetroModule(); | 51 HMODULE metro_module = base::win::GetMetroModule(); |
| 69 if (metro_module != NULL) { | 52 if (metro_module != NULL) { |
| 70 typedef BOOL (*MetroGetSaveFileName)(OPENFILENAME*); | 53 typedef BOOL (*MetroGetSaveFileName)(OPENFILENAME*); |
| 71 MetroGetSaveFileName metro_get_save_file_name = | 54 MetroGetSaveFileName metro_get_save_file_name = |
| 72 reinterpret_cast<MetroGetSaveFileName>( | 55 reinterpret_cast<MetroGetSaveFileName>( |
| 73 ::GetProcAddress(metro_module, "MetroGetSaveFileName")); | 56 ::GetProcAddress(metro_module, "MetroGetSaveFileName")); |
| 74 if (metro_get_save_file_name == NULL) { | 57 if (metro_get_save_file_name == NULL) { |
| 75 NOTREACHED(); | 58 NOTREACHED(); |
| 76 return false; | 59 return false; |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 false, | 386 false, |
| 404 &index, | 387 &index, |
| 405 final_name); | 388 final_name); |
| 406 } | 389 } |
| 407 | 390 |
| 408 // Implementation of SelectFileDialog that shows a Windows common dialog for | 391 // Implementation of SelectFileDialog that shows a Windows common dialog for |
| 409 // choosing a file or folder. | 392 // choosing a file or folder. |
| 410 class SelectFileDialogImpl : public ui::SelectFileDialog, | 393 class SelectFileDialogImpl : public ui::SelectFileDialog, |
| 411 public ui::BaseShellDialogImpl { | 394 public ui::BaseShellDialogImpl { |
| 412 public: | 395 public: |
| 413 explicit SelectFileDialogImpl(Listener* listener, | 396 SelectFileDialogImpl( |
| 414 ui::SelectFilePolicy* policy); | 397 Listener* listener, |
| 398 ui::SelectFilePolicy* policy, | |
| 399 const base::Callback<bool(OPENFILENAME*)>& get_open_file_name_impl); | |
| 415 | 400 |
| 416 // BaseShellDialog implementation: | 401 // BaseShellDialog implementation: |
| 417 virtual bool IsRunning(gfx::NativeWindow owning_window) const OVERRIDE; | 402 virtual bool IsRunning(gfx::NativeWindow owning_window) const OVERRIDE; |
| 418 virtual void ListenerDestroyed() OVERRIDE; | 403 virtual void ListenerDestroyed() OVERRIDE; |
| 419 | 404 |
| 420 protected: | 405 protected: |
| 421 // SelectFileDialog implementation: | 406 // SelectFileDialog implementation: |
| 422 virtual void SelectFileImpl( | 407 virtual void SelectFileImpl( |
| 423 Type type, | 408 Type type, |
| 424 const base::string16& title, | 409 const base::string16& title, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 LPARAM data); | 498 LPARAM data); |
| 514 | 499 |
| 515 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; | 500 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; |
| 516 | 501 |
| 517 // Returns the filter to be used while displaying the open/save file dialog. | 502 // Returns the filter to be used while displaying the open/save file dialog. |
| 518 // This is computed from the extensions for the file types being opened. | 503 // This is computed from the extensions for the file types being opened. |
| 519 // |file_types| can be NULL in which case the returned filter will be empty. | 504 // |file_types| can be NULL in which case the returned filter will be empty. |
| 520 base::string16 GetFilterForFileTypes(const FileTypeInfo* file_types); | 505 base::string16 GetFilterForFileTypes(const FileTypeInfo* file_types); |
| 521 | 506 |
| 522 bool has_multiple_file_type_choices_; | 507 bool has_multiple_file_type_choices_; |
| 508 base::Callback<bool(OPENFILENAME*)> get_open_file_name_impl_; | |
| 523 | 509 |
| 524 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); | 510 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); |
| 525 }; | 511 }; |
| 526 | 512 |
| 527 SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener, | 513 SelectFileDialogImpl::SelectFileDialogImpl( |
| 528 ui::SelectFilePolicy* policy) | 514 Listener* listener, |
| 515 ui::SelectFilePolicy* policy, | |
| 516 const base::Callback<bool(OPENFILENAME*)>& get_open_file_name_impl) | |
| 529 : SelectFileDialog(listener, policy), | 517 : SelectFileDialog(listener, policy), |
| 530 BaseShellDialogImpl(), | 518 BaseShellDialogImpl(), |
| 531 has_multiple_file_type_choices_(false) { | 519 has_multiple_file_type_choices_(false), |
| 520 get_open_file_name_impl_(get_open_file_name_impl) { | |
| 532 } | 521 } |
| 533 | 522 |
| 534 SelectFileDialogImpl::~SelectFileDialogImpl() { | 523 SelectFileDialogImpl::~SelectFileDialogImpl() { |
| 535 } | 524 } |
| 536 | 525 |
| 537 void SelectFileDialogImpl::SelectFileImpl( | 526 void SelectFileDialogImpl::SelectFileImpl( |
| 538 Type type, | 527 Type type, |
| 539 const base::string16& title, | 528 const base::string16& title, |
| 540 const base::FilePath& default_path, | 529 const base::FilePath& default_path, |
| 541 const FileTypeInfo* file_types, | 530 const FileTypeInfo* file_types, |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 ui::win::OpenFileName ofn(owner, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR); | 768 ui::win::OpenFileName ofn(owner, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR); |
| 780 if (!path->empty()) { | 769 if (!path->empty()) { |
| 781 if (IsDirectory(*path)) | 770 if (IsDirectory(*path)) |
| 782 ofn.SetInitialSelection(*path, base::FilePath()); | 771 ofn.SetInitialSelection(*path, base::FilePath()); |
| 783 else | 772 else |
| 784 ofn.SetInitialSelection(path->DirName(), path->BaseName()); | 773 ofn.SetInitialSelection(path->DirName(), path->BaseName()); |
| 785 } | 774 } |
| 786 | 775 |
| 787 if (!filter.empty()) | 776 if (!filter.empty()) |
| 788 ofn.Get()->lpstrFilter = filter.c_str(); | 777 ofn.Get()->lpstrFilter = filter.c_str(); |
| 789 bool success = CallGetOpenFileName(ofn.Get()); | 778 |
| 779 bool success = get_open_file_name_impl_.Run(ofn.Get()); | |
| 790 DisableOwner(owner); | 780 DisableOwner(owner); |
| 791 if (success) | 781 if (success) |
| 792 *path = ofn.GetSingleResult(); | 782 *path = ofn.GetSingleResult(); |
| 793 return success; | 783 return success; |
| 794 } | 784 } |
| 795 | 785 |
| 796 bool SelectFileDialogImpl::RunOpenMultiFileDialog( | 786 bool SelectFileDialogImpl::RunOpenMultiFileDialog( |
| 797 const std::wstring& title, | 787 const std::wstring& title, |
| 798 const std::wstring& filter, | 788 const std::wstring& filter, |
| 799 HWND owner, | 789 HWND owner, |
| 800 std::vector<base::FilePath>* paths) { | 790 std::vector<base::FilePath>* paths) { |
| 801 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory | 791 // We use OFN_NOCHANGEDIR so that the user can rename or delete the directory |
| 802 // without having to close Chrome first. | 792 // without having to close Chrome first. |
| 803 ui::win::OpenFileName ofn(owner, | 793 ui::win::OpenFileName ofn(owner, |
| 804 OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | | 794 OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | |
| 805 OFN_EXPLORER | OFN_HIDEREADONLY | | 795 OFN_EXPLORER | OFN_HIDEREADONLY | |
| 806 OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR); | 796 OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR); |
| 807 | 797 |
| 808 if (!filter.empty()) | 798 if (!filter.empty()) |
| 809 ofn.Get()->lpstrFilter = filter.c_str(); | 799 ofn.Get()->lpstrFilter = filter.c_str(); |
| 810 | 800 |
| 811 base::FilePath directory; | 801 base::FilePath directory; |
| 812 std::vector<base::FilePath> filenames; | 802 std::vector<base::FilePath> filenames; |
| 813 | 803 |
| 814 if (CallGetOpenFileName(ofn.Get())) | 804 if (get_open_file_name_impl_.Run(ofn.Get())) |
| 815 ofn.GetResult(&directory, &filenames); | 805 ofn.GetResult(&directory, &filenames); |
| 806 | |
| 816 DisableOwner(owner); | 807 DisableOwner(owner); |
| 817 | 808 |
| 818 for (std::vector<base::FilePath>::iterator it = filenames.begin(); | 809 for (std::vector<base::FilePath>::iterator it = filenames.begin(); |
| 819 it != filenames.end(); | 810 it != filenames.end(); |
| 820 ++it) { | 811 ++it) { |
| 821 paths->push_back(directory.Append(*it)); | 812 paths->push_back(directory.Append(*it)); |
| 822 } | 813 } |
| 823 | 814 |
| 824 return !paths->empty(); | 815 return !paths->empty(); |
| 825 } | 816 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 // Strip any trailing dots, which Windows doesn't allow. | 878 // Strip any trailing dots, which Windows doesn't allow. |
| 888 size_t index = return_value.find_last_not_of(L'.'); | 879 size_t index = return_value.find_last_not_of(L'.'); |
| 889 if (index < return_value.size() - 1) | 880 if (index < return_value.size() - 1) |
| 890 return_value.resize(index + 1); | 881 return_value.resize(index + 1); |
| 891 | 882 |
| 892 return return_value; | 883 return return_value; |
| 893 } | 884 } |
| 894 | 885 |
| 895 SelectFileDialog* CreateWinSelectFileDialog( | 886 SelectFileDialog* CreateWinSelectFileDialog( |
| 896 SelectFileDialog::Listener* listener, | 887 SelectFileDialog::Listener* listener, |
| 888 SelectFilePolicy* policy, | |
| 889 const base::Callback<bool(OPENFILENAME* ofn)>& get_open_file_name_impl) { | |
| 890 return new SelectFileDialogImpl(listener, policy, get_open_file_name_impl); | |
| 891 } | |
| 892 | |
| 893 SelectFileDialog* CreateDefaultWinSelectFileDialog( | |
| 894 SelectFileDialog::Listener* listener, | |
| 897 SelectFilePolicy* policy) { | 895 SelectFilePolicy* policy) { |
| 898 return new SelectFileDialogImpl(listener, policy); | 896 return CreateWinSelectFileDialog( |
| 897 listener, policy, base::Bind(&CallBuiltinGetOpenFileName)); | |
| 899 } | 898 } |
| 900 | 899 |
| 901 } // namespace ui | 900 } // namespace ui |
| OLD | NEW |