15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/select_file_dialog_extension.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/selected_file_info.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const SelectFileDialogExtension::RoutingID kDefaultRoutingID = 141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SelectFileDialogExtension::RoutingID(); 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Must be a class so it can be a friend of SelectFileDialogExtension. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SelectFileDialogExtensionTest : public testing::Test { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SelectFileDialogExtensionTest() {} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~SelectFileDialogExtensionTest() {} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SelectFileDialogExtension* CreateDialog( 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::SelectFileDialog::Listener* listener) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFileDialogExtension* dialog = new SelectFileDialogExtension(listener, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simulate the dialog opening. 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(SelectFileDialogExtension::PendingExists(kDefaultRoutingID)); 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) dialog->AddPending(kDefaultRoutingID); 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(SelectFileDialogExtension::PendingExists(kDefaultRoutingID)); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dialog; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SelectFileDialogExtensionTest); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test listener for a SelectFileDialog. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestListener : public ui::SelectFileDialog::Listener { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestListener() : selected_(false), file_index_(-1) {} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TestListener() {} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool selected() const { return selected_; } 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int file_index() const { return file_index_; } 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ui::SelectFileDialog::Listener implementation 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void FileSelected(const base::FilePath& path, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index, 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void* params) OVERRIDE { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) selected_ = true; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_index_ = index; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool selected_; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int file_index_; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestListener); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Client of a SelectFileDialog that deletes itself whenever the dialog 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is closed. This is a common pattern in UI code. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SelfDeletingClient : public ui::SelectFileDialog::Listener { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SelfDeletingClient() { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog_ = SelectFileDialogExtensionTest::CreateDialog(this); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~SelfDeletingClient() { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dialog_.get()) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog_->ListenerDestroyed(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFileDialogExtension* dialog() const { return dialog_.get(); } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ui::SelectFileDialog::Listener implementation 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void FileSelected(const base::FilePath& path, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void* params) OVERRIDE { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SelectFileDialogExtensionTest, FileSelected) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kFileIndex = 5; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TestListener> listener(new TestListener); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog = 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDialog(listener.get()); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate selecting a file. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::SelectedFileInfo info; 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SelectFileDialogExtension::OnFileSelected(kDefaultRoutingID, info, 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kFileIndex); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate closing the dialog so the listener gets invoked. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog->ExtensionDialogClosing(NULL); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(listener->selected()); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(kFileIndex, listener->file_index()); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SelectFileDialogExtensionTest, FileSelectionCanceled) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TestListener> listener(new TestListener); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SelectFileDialogExtension> dialog = 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateDialog(listener.get()); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate cancelling the dialog. 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SelectFileDialogExtension::OnFileSelectionCanceled(kDefaultRoutingID); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Simulate closing the dialog so the listener gets invoked. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog->ExtensionDialogClosing(NULL); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(listener->selected()); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(-1, listener->file_index()); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SelectFileDialogExtensionTest, SelfDeleting) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SelfDeletingClient* client = new SelfDeletingClient(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure we don't crash or trip an Address Sanitizer warning about 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use-after-free. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::SelectedFileInfo file_info; 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SelectFileDialogExtension::OnFileSelected(kDefaultRoutingID, file_info, 0); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simulate closing the dialog so the listener gets invoked. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client->dialog()->ExtensionDialogClosing(NULL); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 125