1 // Copyright 2019 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 "base/bind.h"
6 #include "base/run_loop.h"
7 #include "base/threading/platform_thread.h"
8 #include "build/build_config.h"
9 #if defined(OS_WIN)
10 #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h"
11 #endif  // defined(OS_WIN)
12 #include "chrome/browser/vr/test/browser_test_browser_renderer_browser_interface.h"
13 #include "chrome/browser/vr/test/ui_utils.h"
14 #include "chrome/browser/vr/test/xr_browser_test.h"
15 
16 namespace vr {
17 
UiUtils()18 UiUtils::UiUtils()
19     : ui_operation_results_(std::vector<UiTestOperationResult>(
20           static_cast<int>(UiTestOperationType::kNumUiTestOperationTypes))),
21       ui_operation_callbacks_(std::vector<base::OnceCallback<void()>>(
22           static_cast<int>(UiTestOperationType::kNumUiTestOperationTypes))),
23       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
24   auto* renderer = GetBrowserRenderer();
25   DCHECK(renderer) << "Failed to get a BrowserRenderer. Consider using "
26                    << "UiUtils::Create() instead.";
27 
28   interface_ =
29       std::make_unique<BrowserTestBrowserRendererBrowserInterface>(this);
30   renderer->SetBrowserRendererBrowserInterfaceForTesting(interface_.get());
31 }
32 
~UiUtils()33 UiUtils::~UiUtils() {
34   auto* renderer = GetBrowserRenderer();
35   if (renderer != nullptr) {
36     renderer->SetBrowserRendererBrowserInterfaceForTesting(nullptr);
37   }
38 }
39 
Create()40 std::unique_ptr<UiUtils> UiUtils::Create() {
41   base::RunLoop wait_loop(base::RunLoop::Type::kNestableTasksAllowed);
42   base::ThreadTaskRunnerHandle::Get()->PostTask(
43       FROM_HERE, base::BindOnce(&UiUtils::PollForBrowserRenderer, &wait_loop));
44   wait_loop.Run();
45 
46   return std::make_unique<UiUtils>();
47 }
48 
PollForBrowserRenderer(base::RunLoop * wait_loop)49 void UiUtils::PollForBrowserRenderer(base::RunLoop* wait_loop) {
50   if (GetBrowserRenderer() == nullptr) {
51     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
52         FROM_HERE, base::BindOnce(&UiUtils::PollForBrowserRenderer, wait_loop),
53         XrBrowserTestBase::kPollCheckIntervalShort);
54     return;
55   }
56   wait_loop->Quit();
57 }
58 
PerformActionAndWaitForVisibilityStatus(const UserFriendlyElementName & element_name,const bool & visible,base::OnceCallback<void ()> action)59 void UiUtils::PerformActionAndWaitForVisibilityStatus(
60     const UserFriendlyElementName& element_name,
61     const bool& visible,
62     base::OnceCallback<void()> action) {
63   ui_operation_results_[static_cast<int>(
64       UiTestOperationType::kElementVisibilityStatus)] =
65       UiTestOperationResult::kUnreported;
66   base::RunLoop wait_loop(base::RunLoop::Type::kNestableTasksAllowed);
67   ui_operation_callbacks_[static_cast<int>(
68       UiTestOperationType::kElementVisibilityStatus)] =
69       base::BindOnce([](base::RunLoop* loop) { loop->Quit(); }, &wait_loop);
70 
71   VisibilityChangeExpectation visibility_expectation;
72   visibility_expectation.element_name = element_name;
73   visibility_expectation.timeout_ms = kDefaultUiQuiescenceTimeout;
74   visibility_expectation.visibility = visible;
75 
76   main_thread_task_runner_->PostTask(
77       FROM_HERE,
78       base::BindOnce(&UiUtils::WatchElementForVisibilityStatusForTesting,
79                      base::Unretained(this), visibility_expectation));
80 
81   wait_loop.Run();
82 
83   auto result = ui_operation_results_[static_cast<int>(
84       UiTestOperationType::kElementVisibilityStatus)];
85   CHECK(result == UiTestOperationResult::kVisibilityMatch)
86       << "UI reported non-visibility-matched result '"
87       << UiTestOperationResultToString(result) << "'";
88 }
89 
WatchElementForVisibilityStatusForTesting(VisibilityChangeExpectation visibility_expectation)90 void UiUtils::WatchElementForVisibilityStatusForTesting(
91     VisibilityChangeExpectation visibility_expectation) {
92   BrowserRenderer* browser_renderer = UiUtils::GetBrowserRenderer();
93   if (browser_renderer) {
94     interface_ =
95         std::make_unique<BrowserTestBrowserRendererBrowserInterface>(this);
96     browser_renderer->SetBrowserRendererBrowserInterfaceForTesting(
97         interface_.get());
98     browser_renderer->WatchElementForVisibilityStatusForTesting(
99         visibility_expectation);
100   }
101 }
102 
ReportUiOperationResult(const UiTestOperationType & action_type,const UiTestOperationResult & result)103 void UiUtils::ReportUiOperationResult(const UiTestOperationType& action_type,
104                                       const UiTestOperationResult& result) {
105   ui_operation_results_[static_cast<int>(action_type)] = result;
106   std::move(ui_operation_callbacks_[static_cast<int>(action_type)]).Run();
107 }
108 
DisableFrameTimeoutForTesting()109 void UiUtils::DisableFrameTimeoutForTesting() {
110 #if defined(OS_WIN)
111   VRBrowserRendererThreadWin::DisableFrameTimeoutForTesting();
112 #else
113   NOTREACHED();
114 #endif  // defined(OS_WIN)
115 }
116 
UiTestOperationResultToString(UiTestOperationResult & result)117 std::string UiUtils::UiTestOperationResultToString(
118     UiTestOperationResult& result) {
119   switch (result) {
120     case UiTestOperationResult::kUnreported:
121       return "Unreported";
122     case UiTestOperationResult::kQuiescent:
123       return "Quiescent";
124     case UiTestOperationResult::kTimeoutNoStart:
125       return "Timeout (UI activity not started)";
126     case UiTestOperationResult::kTimeoutNoEnd:
127       return "Timeout (UI activity not stopped)";
128     case UiTestOperationResult::kVisibilityMatch:
129       return "Visibility match";
130     case UiTestOperationResult::kTimeoutNoVisibilityMatch:
131       return "Timeout (Element visibility did not match)";
132   }
133 }
134 
GetRendererThread()135 VRBrowserRendererThreadWin* UiUtils::GetRendererThread() {
136 #if defined(OS_WIN)
137   return VRBrowserRendererThreadWin::GetInstanceForTesting();
138 #else
139   NOTREACHED();
140 #endif  // defined(OS_WIN)
141 }
142 
GetBrowserRenderer()143 BrowserRenderer* UiUtils::GetBrowserRenderer() {
144 #if defined(OS_WIN)
145   auto* renderer_thread = GetRendererThread();
146   if (renderer_thread == nullptr)
147     return nullptr;
148   return static_cast<VRBrowserRendererThreadWin*>(renderer_thread)
149       ->GetBrowserRendererForTesting();
150 #else
151   NOTREACHED();
152 #endif  // defined(OS_WIN)
153 }
154 
155 }  // namespace vr
156