blob: 9dc75500d1d4fbf7717c26530c2723d7369be129 [file] [log] [blame]
leon.hana0c5fa32017-06-13 08:14:111// Copyright 2017 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/macros.h"
7#include "base/run_loop.h"
Han Leon18ea6202017-06-19 03:34:498#include "base/strings/utf_string_conversions.h"
9#include "content/public/browser/browser_thread.h"
Han Leon43528ec2017-07-07 02:54:5710#include "content/public/browser/gpu_service_registry.h"
leon.hana0c5fa32017-06-13 08:14:1111#include "content/public/browser/render_frame_host.h"
12#include "content/public/browser/render_process_host.h"
Han Leon18ea6202017-06-19 03:34:4913#include "content/public/browser/utility_process_host.h"
14#include "content/public/browser/utility_process_host_client.h"
leon.hana0c5fa32017-06-13 08:14:1115#include "content/public/browser/web_contents.h"
16#include "content/public/common/service_names.mojom.h"
17#include "content/public/test/browser_test_utils.h"
18#include "content/public/test/content_browser_test.h"
19#include "content/public/test/content_browser_test_utils.h"
20#include "content/shell/browser/shell.h"
21#include "content/shell/common/power_monitor_test.mojom.h"
22#include "mojo/public/cpp/bindings/binding_set.h"
23#include "mojo/public/cpp/bindings/interface_ptr_set.h"
24#include "services/device/public/interfaces/constants.mojom.h"
25#include "services/device/public/interfaces/power_monitor.mojom.h"
26#include "services/service_manager/public/cpp/service_context.h"
27
28namespace content {
29
30namespace {
31
32void VerifyPowerStateInChildProcess(mojom::PowerMonitorTest* power_monitor_test,
33 bool expected_state) {
34 base::RunLoop run_loop;
tzike2aca992017-09-05 08:50:5435 power_monitor_test->QueryNextState(base::BindOnce(
leon.hana0c5fa32017-06-13 08:14:1136 [](const base::Closure& quit, bool expected_state,
37 bool on_battery_power) {
38 EXPECT_EQ(expected_state, on_battery_power);
39 quit.Run();
40 },
41 run_loop.QuitClosure(), expected_state));
42 run_loop.Run();
43}
44
Han Leon18ea6202017-06-19 03:34:4945void StartUtilityProcessOnIOThread(mojom::PowerMonitorTestRequest request) {
46 UtilityProcessHost* host = UtilityProcessHost::Create(nullptr, nullptr);
47 host->SetName(base::ASCIIToUTF16("TestProcess"));
48 EXPECT_TRUE(host->Start());
49
50 BindInterface(host, std::move(request));
51}
52
Han Leon43528ec2017-07-07 02:54:5753void BindInterfaceForGpuOnIOThread(mojom::PowerMonitorTestRequest request) {
54 BindInterfaceInGpuProcess(std::move(request));
55}
56
leon.hana0c5fa32017-06-13 08:14:1157class MockPowerMonitorMessageBroadcaster : public device::mojom::PowerMonitor {
58 public:
59 MockPowerMonitorMessageBroadcaster() = default;
60 ~MockPowerMonitorMessageBroadcaster() override = default;
61
62 void Bind(device::mojom::PowerMonitorRequest request) {
63 bindings_.AddBinding(this, std::move(request));
64 }
65
66 // device::mojom::PowerMonitor:
67 void AddClient(
68 device::mojom::PowerMonitorClientPtr power_monitor_client) override {
69 power_monitor_client->PowerStateChange(on_battery_power_);
70 clients_.AddPtr(std::move(power_monitor_client));
71 }
72
73 void OnPowerStateChange(bool on_battery_power) {
74 on_battery_power_ = on_battery_power;
75 clients_.ForAllPtrs(
76 [&on_battery_power](device::mojom::PowerMonitorClient* client) {
77 client->PowerStateChange(on_battery_power);
78 });
79 }
80
81 private:
82 bool on_battery_power_ = false;
83
84 mojo::BindingSet<device::mojom::PowerMonitor> bindings_;
85 mojo::InterfacePtrSet<device::mojom::PowerMonitorClient> clients_;
86
87 DISALLOW_COPY_AND_ASSIGN(MockPowerMonitorMessageBroadcaster);
88};
89
90class PowerMonitorTest : public ContentBrowserTest {
91 public:
92 PowerMonitorTest() = default;
93
Han Leon43528ec2017-07-07 02:54:5794 void SetUp() override {
leon.hana0c5fa32017-06-13 08:14:1195 // Because Device Service also runs in this process(browser process), we can
96 // set our binder to intercept requests for PowerMonitor interface to it.
97 service_manager::ServiceContext::SetGlobalBinderForTesting(
98 device::mojom::kServiceName, device::mojom::PowerMonitor::Name_,
99 base::Bind(&PowerMonitorTest::BindPowerMonitor,
100 base::Unretained(this)));
Han Leon43528ec2017-07-07 02:54:57101
102 ContentBrowserTest::SetUp();
leon.hana0c5fa32017-06-13 08:14:11103 }
104
Ben Goodger21ada1e2017-07-19 14:53:01105 void BindPowerMonitor(const std::string& interface_name,
106 mojo::ScopedMessagePipeHandle handle,
107 const service_manager::BindSourceInfo& source_info) {
Han Leon18ea6202017-06-19 03:34:49108 if (source_info.identity.name() == mojom::kRendererServiceName) {
leon.hana0c5fa32017-06-13 08:14:11109 ++request_count_from_renderer_;
110
Han Leon18ea6202017-06-19 03:34:49111 DCHECK(renderer_bound_closure_);
112 std::move(renderer_bound_closure_).Run();
113 } else if (source_info.identity.name() == mojom::kUtilityServiceName) {
114 ++request_count_from_utility_;
115
116 DCHECK(utility_bound_closure_);
117 std::move(utility_bound_closure_).Run();
Han Leon43528ec2017-07-07 02:54:57118 } else if (source_info.identity.name() == mojom::kGpuServiceName) {
119 ++request_count_from_gpu_;
120
121 // We ignore null gpu_bound_closure_ here for two possible scenarios:
122 // - TestRendererProcess and TestUtilityProcess also result in spinning
123 // up GPU processes as a side effect, but they do not set valid
124 // gpu_bound_closure_.
125 // - As GPU process is started during setup of browser test suite, so
126 // it's possible that TestGpuProcess execution may have not started
127 // yet when the PowerMonitor bind request comes here, in such case
128 // gpu_bound_closure_ will also be null.
129 if (gpu_bound_closure_)
130 std::move(gpu_bound_closure_).Run();
Han Leon18ea6202017-06-19 03:34:49131 }
132
leon.hana0c5fa32017-06-13 08:14:11133 power_monitor_message_broadcaster_.Bind(
134 device::mojom::PowerMonitorRequest(std::move(handle)));
135 }
136
137 protected:
Han Leon18ea6202017-06-19 03:34:49138 void StartUtilityProcess(mojom::PowerMonitorTestPtr* power_monitor_test,
139 base::Closure utility_bound_closure) {
140 utility_bound_closure_ = utility_bound_closure;
141 BrowserThread::PostTask(
142 BrowserThread::IO, FROM_HERE,
143 base::BindOnce(&StartUtilityProcessOnIOThread,
144 mojo::MakeRequest(power_monitor_test)));
145 }
146
147 void set_renderer_bound_closure(base::Closure closure) {
148 renderer_bound_closure_ = closure;
149 }
150
Han Leon43528ec2017-07-07 02:54:57151 void set_gpu_bound_closure(base::Closure closure) {
152 gpu_bound_closure_ = closure;
153 }
154
leon.hana0c5fa32017-06-13 08:14:11155 int request_count_from_renderer() { return request_count_from_renderer_; }
Han Leon18ea6202017-06-19 03:34:49156 int request_count_from_utility() { return request_count_from_utility_; }
Han Leon43528ec2017-07-07 02:54:57157 int request_count_from_gpu() { return request_count_from_gpu_; }
leon.hana0c5fa32017-06-13 08:14:11158
159 void SimulatePowerStateChange(bool on_battery_power) {
160 power_monitor_message_broadcaster_.OnPowerStateChange(on_battery_power);
161 }
162
163 private:
164 int request_count_from_renderer_ = 0;
Han Leon18ea6202017-06-19 03:34:49165 int request_count_from_utility_ = 0;
Han Leon43528ec2017-07-07 02:54:57166 int request_count_from_gpu_ = 0;
Han Leon18ea6202017-06-19 03:34:49167 base::OnceClosure renderer_bound_closure_;
Han Leon43528ec2017-07-07 02:54:57168 base::OnceClosure gpu_bound_closure_;
Han Leon18ea6202017-06-19 03:34:49169 base::OnceClosure utility_bound_closure_;
leon.hana0c5fa32017-06-13 08:14:11170
171 MockPowerMonitorMessageBroadcaster power_monitor_message_broadcaster_;
172
173 DISALLOW_COPY_AND_ASSIGN(PowerMonitorTest);
174};
175
Han Leon18ea6202017-06-19 03:34:49176IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestRendererProcess) {
leon.hana0c5fa32017-06-13 08:14:11177 ASSERT_EQ(0, request_count_from_renderer());
Han Leon18ea6202017-06-19 03:34:49178 base::RunLoop run_loop;
179 set_renderer_bound_closure(run_loop.QuitClosure());
leon.hana0c5fa32017-06-13 08:14:11180 ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "simple_page.html")));
Han Leon18ea6202017-06-19 03:34:49181 run_loop.Run();
leon.hana0c5fa32017-06-13 08:14:11182 EXPECT_EQ(1, request_count_from_renderer());
183
184 mojom::PowerMonitorTestPtr power_monitor_renderer;
185 RenderProcessHost* rph =
186 shell()->web_contents()->GetMainFrame()->GetProcess();
187 BindInterface(rph, &power_monitor_renderer);
188
189 SimulatePowerStateChange(true);
190 // Verify renderer process on_battery_power changed to true.
191 VerifyPowerStateInChildProcess(power_monitor_renderer.get(), true);
192
193 SimulatePowerStateChange(false);
194 // Verify renderer process on_battery_power changed to false.
195 VerifyPowerStateInChildProcess(power_monitor_renderer.get(), false);
196}
197
Han Leon18ea6202017-06-19 03:34:49198IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestUtilityProcess) {
199 mojom::PowerMonitorTestPtr power_monitor_utility;
200
201 ASSERT_EQ(0, request_count_from_utility());
202 base::RunLoop run_loop;
203 StartUtilityProcess(&power_monitor_utility, run_loop.QuitClosure());
204 run_loop.Run();
205 EXPECT_EQ(1, request_count_from_utility());
206
207 SimulatePowerStateChange(true);
208 // Verify utility process on_battery_power changed to true.
209 VerifyPowerStateInChildProcess(power_monitor_utility.get(), true);
210
211 SimulatePowerStateChange(false);
212 // Verify utility process on_battery_power changed to false.
213 VerifyPowerStateInChildProcess(power_monitor_utility.get(), false);
214}
215
Han Leon43528ec2017-07-07 02:54:57216IN_PROC_BROWSER_TEST_F(PowerMonitorTest, TestGpuProcess) {
217 // As gpu process is started automatically during the setup period of browser
218 // test suite, it may have already started and bound PowerMonitor interface to
219 // Device Service before execution of this TestGpuProcess test. So here we
220 // do not wait for the connection if we found it has already been established.
221 if (request_count_from_gpu() != 1) {
222 ASSERT_EQ(0, request_count_from_gpu());
223 base::RunLoop run_loop;
224 set_gpu_bound_closure(run_loop.QuitClosure());
225 // Wait for the connection from gpu process.
226 run_loop.Run();
227 }
228 EXPECT_EQ(1, request_count_from_gpu());
229
230 mojom::PowerMonitorTestPtr power_monitor_gpu;
231 BrowserThread::PostTask(
232 BrowserThread::IO, FROM_HERE,
233 base::BindOnce(&BindInterfaceForGpuOnIOThread,
234 mojo::MakeRequest(&power_monitor_gpu)));
235
236 SimulatePowerStateChange(true);
237 // Verify gpu process on_battery_power changed to true.
238 VerifyPowerStateInChildProcess(power_monitor_gpu.get(), true);
239
240 SimulatePowerStateChange(false);
241 // Verify gpu process on_battery_power changed to false.
242 VerifyPowerStateInChildProcess(power_monitor_gpu.get(), false);
243}
244
leon.hana0c5fa32017-06-13 08:14:11245} // namespace
246
247} // namespace content