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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/select_file_dialog_extension.h" 6 7 #include "base/files/file_path.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 #include "ui/shell_dialogs/selected_file_info.h" 10 11 namespace { 12 13 const int32 kDefaultTabId = 0; 14 15 } // namespace 16 17 // Must be a class so it can be a friend of SelectFileDialogExtension. 18 class SelectFileDialogExtensionTest : public testing::Test { 19 public: 20 SelectFileDialogExtensionTest() {} 21 virtual ~SelectFileDialogExtensionTest() {} 22 23 static SelectFileDialogExtension* CreateDialog( 24 ui::SelectFileDialog::Listener* listener) { 25 SelectFileDialogExtension* dialog = new SelectFileDialogExtension(listener, 26 NULL); 27 // Simulate the dialog opening. 28 EXPECT_FALSE(SelectFileDialogExtension::PendingExists(kDefaultTabId)); 29 dialog->AddPending(kDefaultTabId); 30 EXPECT_TRUE(SelectFileDialogExtension::PendingExists(kDefaultTabId)); 31 return dialog; 32 } 33 34 private: 35 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogExtensionTest); 36 }; 37 38 // Test listener for a SelectFileDialog. 39 class TestListener : public ui::SelectFileDialog::Listener { 40 public: 41 TestListener() : selected_(false), file_index_(-1) {} 42 virtual ~TestListener() {} 43 44 bool selected() const { return selected_; } 45 int file_index() const { return file_index_; } 46 47 // ui::SelectFileDialog::Listener implementation 48 virtual void FileSelected(const base::FilePath& path, 49 int index, 50 void* params) OVERRIDE { 51 selected_ = true; 52 file_index_ = index; 53 } 54 55 private: 56 bool selected_; 57 int file_index_; 58 59 DISALLOW_COPY_AND_ASSIGN(TestListener); 60 }; 61 62 // Client of a SelectFileDialog that deletes itself whenever the dialog 63 // is closed. This is a common pattern in UI code. 64 class SelfDeletingClient : public ui::SelectFileDialog::Listener { 65 public: 66 SelfDeletingClient() { 67 dialog_ = SelectFileDialogExtensionTest::CreateDialog(this); 68 } 69 70 virtual ~SelfDeletingClient() { 71 if (dialog_.get()) 72 dialog_->ListenerDestroyed(); 73 } 74 75 SelectFileDialogExtension* dialog() const { return dialog_.get(); } 76 77 // ui::SelectFileDialog::Listener implementation 78 virtual void FileSelected(const base::FilePath& path, 79 int index, 80 void* params) OVERRIDE { 81 delete this; 82 } 83 84 private: 85 scoped_refptr<SelectFileDialogExtension> dialog_; 86 }; 87 88 TEST_F(SelectFileDialogExtensionTest, FileSelected) { 89 const int kFileIndex = 5; 90 scoped_ptr<TestListener> listener(new TestListener); 91 scoped_refptr<SelectFileDialogExtension> dialog = 92 CreateDialog(listener.get()); 93 // Simulate selecting a file. 94 ui::SelectedFileInfo info; 95 SelectFileDialogExtension::OnFileSelected(kDefaultTabId, info, kFileIndex); 96 // Simulate closing the dialog so the listener gets invoked. 97 dialog->ExtensionDialogClosing(NULL); 98 EXPECT_TRUE(listener->selected()); 99 EXPECT_EQ(kFileIndex, listener->file_index()); 100 } 101 102 TEST_F(SelectFileDialogExtensionTest, FileSelectionCanceled) { 103 scoped_ptr<TestListener> listener(new TestListener); 104 scoped_refptr<SelectFileDialogExtension> dialog = 105 CreateDialog(listener.get()); 106 // Simulate cancelling the dialog. 107 SelectFileDialogExtension::OnFileSelectionCanceled(kDefaultTabId); 108 // Simulate closing the dialog so the listener gets invoked. 109 dialog->ExtensionDialogClosing(NULL); 110 EXPECT_FALSE(listener->selected()); 111 EXPECT_EQ(-1, listener->file_index()); 112 } 113 114 TEST_F(SelectFileDialogExtensionTest, SelfDeleting) { 115 SelfDeletingClient* client = new SelfDeletingClient(); 116 // Ensure we don't crash or trip an Address Sanitizer warning about 117 // use-after-free. 118 ui::SelectedFileInfo file_info; 119 SelectFileDialogExtension::OnFileSelected(kDefaultTabId, file_info, 0); 120 // Simulate closing the dialog so the listener gets invoked. 121 client->dialog()->ExtensionDialogClosing(NULL); 122 } 123