blob: 3fd66fff3ea2b1a13ab5cd06ab017ffa0a0b6117 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
using BrowserSelectFileDialogTest = InProcessBrowserTest;
// Spins a run loop until a Widget's activation reaches the desired state.
class WidgetActivationWaiter : public views::WidgetObserver {
public:
WidgetActivationWaiter(views::Widget* widget, bool active)
: observed_(false), active_(active) {
widget->AddObserver(this);
EXPECT_NE(active, widget->IsActive());
}
void Wait() {
if (!observed_)
run_loop_.Run();
}
private:
// views::WidgetObserver:
void OnWidgetActivationChanged(views::Widget* widget, bool active) override {
if (active_ != active)
return;
observed_ = true;
widget->RemoveObserver(this);
if (run_loop_.running())
run_loop_.Quit();
}
base::RunLoop run_loop_;
bool observed_;
bool active_;
DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiter);
};
namespace libgtk2ui {
// FilePicker opens a GtkFileChooser.
class FilePicker : public ui::SelectFileDialog::Listener {
public:
explicit FilePicker(BrowserWindow* window) {
select_file_dialog_ = ui::SelectFileDialog::Create(
this, new ChromeSelectFilePolicy(nullptr));
gfx::NativeWindow parent_window = window->GetNativeWindow();
ui::SelectFileDialog::FileTypeInfo file_types;
file_types.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
const base::FilePath file_path;
select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
base::string16(),
file_path,
&file_types,
0,
base::FilePath::StringType(),
parent_window,
nullptr);
}
~FilePicker() override {
select_file_dialog_->ListenerDestroyed();
}
void Close() {
SelectFileDialogImplGTK* file_dialog =
static_cast<SelectFileDialogImplGTK*>(select_file_dialog_.get());
while (!file_dialog->dialogs_.empty())
gtk_widget_destroy(*(file_dialog->dialogs_.begin()));
}
// SelectFileDialog::Listener implementation.
void FileSelected(const base::FilePath& path,
int index,
void* params) override {}
private:
// Dialog box used for opening and saving files.
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
DISALLOW_COPY_AND_ASSIGN(FilePicker);
};
} // namespace libgtk2ui
// Test that the file-picker is modal.
IN_PROC_BROWSER_TEST_F(BrowserSelectFileDialogTest, ModalTest) {
// Bring the native window to the foreground. Returns true on success.
ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
ASSERT_TRUE(browser()->window()->IsActive());
// Leaks in GtkFileChooserDialog. http://crbug.com/537468
ANNOTATE_SCOPED_MEMORY_LEAK;
libgtk2ui::FilePicker file_picker(browser()->window());
gfx::NativeWindow window = browser()->window()->GetNativeWindow();
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
ASSERT_NE(nullptr, widget);
// Run a nested loop until the browser window becomes inactive
// so that the file-picker can be active.
WidgetActivationWaiter waiter_inactive(widget, false);
waiter_inactive.Wait();
EXPECT_FALSE(browser()->window()->IsActive());
ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
// The window should not get focus due to modal dialog.
EXPECT_FALSE(browser()->window()->IsActive());
ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
EXPECT_FALSE(browser()->window()->IsActive());
ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
EXPECT_FALSE(browser()->window()->IsActive());
ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
browser(), ui::VKEY_TAB, false, false, true, false));
EXPECT_FALSE(browser()->window()->IsActive());
file_picker.Close();
// Run a nested loop until the browser window becomes active.
WidgetActivationWaiter wait_active(widget, true);
wait_active.Wait();
ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
EXPECT_TRUE(browser()->window()->IsActive());
}