OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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/test/test_browser_dialog.h" |
| 6 |
| 7 #include "base/command_line.h" |
| 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/test/gtest_util.h" |
| 10 #include "chrome/browser/platform_util.h" |
| 11 #include "ui/base/material_design/material_design_controller.h" |
| 12 #include "ui/base/test/material_design_controller_test_api.h" |
| 13 #include "ui/base/test/user_interactive_test_case.h" |
| 14 #include "ui/base/ui_base_switches.h" |
| 15 #include "ui/views/widget/widget.h" |
| 16 #include "ui/views/widget/widget_observer.h" |
| 17 |
| 18 namespace { |
| 19 |
| 20 // An automatic action for WidgetCloser to post to the RunLoop. |
| 21 // TODO(tapted): Explore asynchronous Widget::Close() and DialogClientView:: |
| 22 // {Accept,Cancel}Window() approaches to test other dialog lifetimes. |
| 23 enum class DialogAction { |
| 24 INTERACTIVE, // Run interactively. |
| 25 CLOSE_NOW, // Call Widget::CloseNow(). |
| 26 }; |
| 27 |
| 28 // Helper to break out of the nested run loop that runs a test dialog. |
| 29 class WidgetCloser : public views::WidgetObserver { |
| 30 public: |
| 31 WidgetCloser(views::Widget* widget, DialogAction action) |
| 32 : widget_(widget), weak_ptr_factory_(this) { |
| 33 widget->AddObserver(this); |
| 34 if (action == DialogAction::INTERACTIVE) |
| 35 return; |
| 36 |
| 37 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 38 FROM_HERE, |
| 39 base::Bind(&WidgetCloser::CloseNow, weak_ptr_factory_.GetWeakPtr())); |
| 40 } |
| 41 |
| 42 // WidgetObserver: |
| 43 void OnWidgetDestroyed(views::Widget* widget) override { |
| 44 widget_->RemoveObserver(this); |
| 45 widget_ = nullptr; |
| 46 base::MessageLoop::current()->QuitNow(); |
| 47 } |
| 48 |
| 49 private: |
| 50 void CloseNow() { |
| 51 if (widget_) |
| 52 widget_->CloseNow(); |
| 53 } |
| 54 |
| 55 views::Widget* widget_; |
| 56 |
| 57 base::WeakPtrFactory<WidgetCloser> weak_ptr_factory_; |
| 58 |
| 59 DISALLOW_COPY_AND_ASSIGN(WidgetCloser); |
| 60 }; |
| 61 |
| 62 // Extracts the |name| argument for ShowDialog() from the current test case. |
| 63 // E.g. for InvokeDialog_name (or DISABLED_InvokeDialog_name) returns "name". |
| 64 std::string NameFromTestCase() { |
| 65 const std::string name = base::TestNameWithoutDisabledPrefix( |
| 66 testing::UnitTest::GetInstance()->current_test_info()->name()); |
| 67 std::string::size_type underscore = name.find('_'); |
| 68 return underscore == std::string::npos ? std::string() |
| 69 : name.substr(underscore + 1); |
| 70 } |
| 71 |
| 72 } // namespace |
| 73 |
| 74 TestBrowserDialog::TestBrowserDialog() {} |
| 75 |
| 76 void TestBrowserDialog::RunDialog() { |
| 77 #if defined(OS_MACOSX) |
| 78 // The rest of this method assumes the child dialog is toolkit-views. So, for |
| 79 // Mac, it will only work if --secondary-ui-md is passed. Without this, a |
| 80 // Cocoa dialog will be created, which TestBrowserDialog doesn't support. |
| 81 // Force SecondaryUiMaterial() on Mac to get coverage on the bots. Leave it |
| 82 // optional elsewhere so that the non-MD dialog can be invoked to compare. |
| 83 ui::test::MaterialDesignControllerTestAPI md_test_api( |
| 84 ui::MaterialDesignController::GetMode()); |
| 85 md_test_api.SetSecondaryUiMaterial(true); |
| 86 #endif |
| 87 |
| 88 gfx::NativeView parent = platform_util::GetViewForWindow(DialogParent()); |
| 89 views::Widget::Widgets widgets_before; |
| 90 views::Widget::GetAllChildWidgets(parent, &widgets_before); |
| 91 |
| 92 ShowDialog(NameFromTestCase()); |
| 93 views::Widget::Widgets widgets_after; |
| 94 views::Widget::GetAllChildWidgets(parent, &widgets_after); |
| 95 |
| 96 auto added = base::STLSetDifference<std::vector<views::Widget*>>( |
| 97 widgets_after, widgets_before); |
| 98 |
| 99 // This can fail if no dialog was shown, if the dialog shown wasn't a toolkit- |
| 100 // views dialog, or if more than one child dialog was shown. |
| 101 ASSERT_EQ(1u, added.size()); |
| 102 |
| 103 const DialogAction action = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 104 internal::kInteractiveSwitch) |
| 105 ? DialogAction::INTERACTIVE |
| 106 : DialogAction::CLOSE_NOW; |
| 107 |
| 108 WidgetCloser closer(added[0], action); |
| 109 ::test::RunTestInteractively(); |
| 110 } |
OLD | NEW |