| 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 |