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/optional.h"
6 #include "base/run_loop.h"
7 #include "base/test/bind_test_util.h"
8 #include "base/time/time.h"
9 #include "base/timer/elapsed_timer.h"
10 #include "content/public/browser/service_process_host.h"
11 #include "content/public/test/content_browser_test.h"
12 #include "services/test/echo/public/mojom/echo.mojom.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace content {
16
17 using ServiceProcessHostBrowserTest = ContentBrowserTest;
18
19 class EchoServiceProcessObserver : public ServiceProcessHost::Observer {
20 public:
EchoServiceProcessObserver()21 EchoServiceProcessObserver() { ServiceProcessHost::AddObserver(this); }
22
~EchoServiceProcessObserver()23 ~EchoServiceProcessObserver() override {
24 ServiceProcessHost::RemoveObserver(this);
25 }
26
WaitForLaunch()27 void WaitForLaunch() { launch_loop_.Run(); }
WaitForDeath()28 void WaitForDeath() { death_loop_.Run(); }
WaitForCrash()29 void WaitForCrash() { crash_loop_.Run(); }
30
31 private:
32 // ServiceProcessHost::Observer:
OnServiceProcessLaunched(const ServiceProcessInfo & info)33 void OnServiceProcessLaunched(const ServiceProcessInfo& info) override {
34 if (info.IsService<echo::mojom::EchoService>())
35 launch_loop_.Quit();
36 }
37
OnServiceProcessTerminatedNormally(const ServiceProcessInfo & info)38 void OnServiceProcessTerminatedNormally(
39 const ServiceProcessInfo& info) override {
40 if (info.IsService<echo::mojom::EchoService>())
41 death_loop_.Quit();
42 }
43
OnServiceProcessCrashed(const ServiceProcessInfo & info)44 void OnServiceProcessCrashed(const ServiceProcessInfo& info) override {
45 if (info.IsService<echo::mojom::EchoService>())
46 crash_loop_.Quit();
47 }
48
49 base::RunLoop launch_loop_;
50 base::RunLoop death_loop_;
51 base::RunLoop crash_loop_;
52
53 DISALLOW_COPY_AND_ASSIGN(EchoServiceProcessObserver);
54 };
55
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest,Launch)56 IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, Launch) {
57 EchoServiceProcessObserver observer;
58 auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
59 observer.WaitForLaunch();
60
61 const std::string kTestString =
62 "Aurora borealis! At this time of year? At this time of day? "
63 "In this part of the country? Localized entirely within your kitchen?";
64 base::RunLoop loop;
65 echo_service->EchoString(
66 kTestString,
67 base::BindLambdaForTesting([&](const std::string& echoed_input) {
68 EXPECT_EQ(kTestString, echoed_input);
69 loop.Quit();
70 }));
71 loop.Run();
72 }
73
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest,LocalDisconnectQuits)74 IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, LocalDisconnectQuits) {
75 EchoServiceProcessObserver observer;
76 auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
77 observer.WaitForLaunch();
78 echo_service.reset();
79 observer.WaitForDeath();
80 }
81
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest,RemoteDisconnectQuits)82 IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, RemoteDisconnectQuits) {
83 EchoServiceProcessObserver observer;
84 auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
85 observer.WaitForLaunch();
86 echo_service->Quit();
87 observer.WaitForDeath();
88 }
89
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest,ObserveCrash)90 IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, ObserveCrash) {
91 EchoServiceProcessObserver observer;
92 auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
93 observer.WaitForLaunch();
94 echo_service->Crash();
95 observer.WaitForCrash();
96 }
97
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest,IdleTimeout)98 IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, IdleTimeout) {
99 EchoServiceProcessObserver observer;
100 auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
101
102 base::RunLoop wait_for_idle_loop;
103 constexpr auto kTimeout = base::TimeDelta::FromSeconds(1);
104 echo_service.set_idle_handler(kTimeout, base::BindLambdaForTesting([&] {
105 wait_for_idle_loop.Quit();
106 echo_service.reset();
107 }));
108
109 // Send a message and wait for the reply. Once the message is sent we should
110 // observe at least |kTimeout| time elapsing before the RunLoop quits, because
111 // the service process must wait at least that long to report itself as idle.
112 base::ElapsedTimer timer;
113 const std::string kTestString =
114 "Yes, and you call them steamed hams despite the fact that they are "
115 "obviously grilled.";
116 echo_service->EchoString(
117 kTestString,
118 base::BindLambdaForTesting([&](const std::string& echoed_input) {
119 EXPECT_EQ(kTestString, echoed_input);
120 }));
121 wait_for_idle_loop.Run();
122 EXPECT_GE(timer.Elapsed(), kTimeout);
123
124 // And since the idle handler resets |echo_service|, we should imminently see
125 // normal service process termination.
126 observer.WaitForDeath();
127 }
128
129 } // namespace content
130