1 // Copyright 2020 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 "ui/views/examples/examples_main_proc.h" 6 7 #include <memory> 8 #include <string> 9 10 #include "base/base_switches.h" 11 #include "base/bind.h" 12 #include "base/command_line.h" 13 #include "base/feature_list.h" 14 #include "base/files/file_path.h" 15 #include "base/i18n/icu_util.h" 16 #include "base/lazy_instance.h" 17 #include "base/memory/ptr_util.h" 18 #include "base/path_service.h" 19 #include "base/power_monitor/power_monitor.h" 20 #include "base/power_monitor/power_monitor_device_source.h" 21 #include "base/run_loop.h" 22 #include "base/test/scoped_run_loop_timeout.h" 23 #include "base/test/task_environment.h" 24 #include "base/test/test_discardable_memory_allocator.h" 25 #include "base/test/test_timeouts.h" 26 #include "build/build_config.h" 27 #include "components/viz/common/features.h" 28 #include "components/viz/host/host_frame_sink_manager.h" 29 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" 30 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" 31 #include "mojo/core/embedder/embedder.h" 32 #include "ui/base/ime/init/input_method_initializer.h" 33 #include "ui/base/resource/resource_bundle.h" 34 #include "ui/base/ui_base_paths.h" 35 #include "ui/compositor/compositor_switches.h" 36 #include "ui/compositor/test/in_process_context_factory.h" 37 #include "ui/compositor/test/test_context_factories.h" 38 #include "ui/display/screen.h" 39 #include "ui/gfx/font_util.h" 40 #include "ui/gfx/image/image.h" 41 #include "ui/gl/gl_switches.h" 42 #include "ui/gl/init/gl_factory.h" 43 #include "ui/views/buildflags.h" 44 #include "ui/views/examples/example_base.h" 45 #include "ui/views/examples/examples_window.h" 46 #include "ui/views/test/desktop_test_views_delegate.h" 47 #include "ui/views/widget/any_widget_observer.h" 48 #include "ui/views/widget/widget.h" 49 50 #if defined(USE_AURA) 51 #include "ui/aura/env.h" 52 #include "ui/wm/core/wm_state.h" 53 #endif 54 55 #if defined(OS_CHROMEOS) 56 #include "ui/views/examples/examples_views_delegate_chromeos.h" 57 #endif 58 59 #if BUILDFLAG(ENABLE_DESKTOP_AURA) 60 #include "ui/views/widget/desktop_aura/desktop_screen.h" 61 #endif 62 63 #if defined(OS_WIN) 64 #include "ui/base/win/scoped_ole_initializer.h" 65 #include "ui/views/examples/examples_skia_gold_pixel_diff.h" 66 #endif 67 68 #if defined(USE_OZONE) 69 #include "ui/base/ui_base_features.h" 70 #include "ui/ozone/public/ozone_platform.h" 71 #endif 72 73 namespace views { 74 namespace examples { 75 76 base::LazyInstance<base::TestDiscardableMemoryAllocator>::DestructorAtExit 77 g_discardable_memory_allocator = LAZY_INSTANCE_INITIALIZER; 78 ExamplesMainProc(bool under_test)79ExamplesExitCode ExamplesMainProc(bool under_test) { 80 #if defined(OS_WIN) 81 ui::ScopedOleInitializer ole_initializer; 82 #endif 83 84 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 85 86 // Disabling Direct Composition works around the limitation that 87 // InProcessContextFactory doesn't work with Direct Composition, causing the 88 // window to not render. See http://crbug.com/936249. 89 command_line->AppendSwitch(switches::kDisableDirectComposition); 90 91 // Disable skia renderer to use GL instead. 92 std::string disabled = 93 command_line->GetSwitchValueASCII(switches::kDisableFeatures); 94 if (!disabled.empty()) 95 disabled += ","; 96 disabled += features::kUseSkiaRenderer.name; 97 command_line->AppendSwitchASCII(switches::kDisableFeatures, disabled); 98 99 base::FeatureList::InitializeInstance( 100 command_line->GetSwitchValueASCII(switches::kEnableFeatures), 101 command_line->GetSwitchValueASCII(switches::kDisableFeatures)); 102 103 if (under_test) 104 command_line->AppendSwitch(switches::kEnablePixelOutputInTests); 105 106 mojo::core::Init(); 107 108 #if defined(USE_OZONE) 109 if (features::IsUsingOzonePlatform()) { 110 ui::OzonePlatform::InitParams params; 111 params.single_process = true; 112 ui::OzonePlatform::InitializeForGPU(params); 113 } 114 #endif 115 116 gl::init::InitializeGLOneOff(); 117 118 // Viz depends on the task environment to correctly tear down. 119 base::test::TaskEnvironment task_environment( 120 base::test::TaskEnvironment::MainThreadType::UI); 121 122 // The ContextFactory must exist before any Compositors are created. 123 auto context_factories = 124 std::make_unique<ui::TestContextFactories>(under_test); 125 context_factories->SetUseTestSurface(false); 126 127 base::i18n::InitializeICU(); 128 129 ui::RegisterPathProvider(); 130 131 base::FilePath ui_test_pak_path; 132 CHECK(base::PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path)); 133 ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path); 134 135 base::FilePath views_examples_resources_pak_path; 136 CHECK(base::PathService::Get(base::DIR_MODULE, 137 &views_examples_resources_pak_path)); 138 ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( 139 views_examples_resources_pak_path.AppendASCII( 140 "views_examples_resources.pak"), 141 ui::SCALE_FACTOR_100P); 142 143 base::DiscardableMemoryAllocator::SetInstance( 144 g_discardable_memory_allocator.Pointer()); 145 146 base::PowerMonitor::Initialize( 147 std::make_unique<base::PowerMonitorDeviceSource>()); 148 149 gfx::InitializeFonts(); 150 151 #if defined(USE_AURA) 152 std::unique_ptr<aura::Env> env = aura::Env::CreateInstance(); 153 aura::Env::GetInstance()->set_context_factory( 154 context_factories->GetContextFactory()); 155 #endif 156 ui::InitializeInputMethodForTesting(); 157 158 ExamplesExitCode compare_result = ExamplesExitCode::kSucceeded; 159 160 { 161 #if defined(OS_CHROMEOS) 162 ExamplesViewsDelegateChromeOS views_delegate; 163 #else 164 views::DesktopTestViewsDelegate views_delegate; 165 #if defined(USE_AURA) 166 wm::WMState wm_state; 167 #endif 168 #endif 169 #if BUILDFLAG(ENABLE_DESKTOP_AURA) 170 std::unique_ptr<display::Screen> desktop_screen = 171 base::WrapUnique(views::CreateDesktopScreen()); 172 #endif 173 174 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); 175 176 #if defined(OS_WIN) 177 ExamplesSkiaGoldPixelDiff pixel_diff; 178 views::AnyWidgetObserver widget_observer{ 179 views::test::AnyWidgetTestPasskey()}; 180 181 // If this app isn't a test, it shouldn't timeout. 182 auto disable_timeout = 183 std::make_unique<base::test::ScopedDisableRunLoopTimeout>(); 184 185 if (under_test) { 186 pixel_diff.Init("ViewsExamples"); 187 widget_observer.set_shown_callback( 188 base::BindRepeating(&ExamplesSkiaGoldPixelDiff::OnExamplesWindowShown, 189 base::Unretained(&pixel_diff))); 190 // Enable the timeout since we're not running in a test. 191 disable_timeout.reset(); 192 } 193 #else 194 base::test::ScopedDisableRunLoopTimeout disable_timeout; 195 #endif 196 197 views::examples::ShowExamplesWindow(run_loop.QuitClosure()); 198 199 run_loop.Run(); 200 201 #if defined(OS_WIN) 202 compare_result = pixel_diff.get_result(); 203 #endif 204 205 ui::ResourceBundle::CleanupSharedInstance(); 206 } 207 208 ui::ShutdownInputMethod(); 209 210 #if defined(USE_AURA) 211 env.reset(); 212 #endif 213 214 return compare_result; 215 } 216 217 } // namespace examples 218 } // namespace views 219