1 // Copyright (c) 2012 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.
5 #include "chrome/browser/service_process/service_process_control.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/path_service.h"
11 #include "base/process/kill.h"
12 #include "base/process/process.h"
13 #include "base/process/process_iterator.h"
14 #include "base/test/test_timeouts.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/common/service_process_util.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "content/public/common/content_paths.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/test_utils.h"
23 #include "testing/gmock/include/gmock/gmock.h"
25 class ServiceProcessControlBrowserTest
26 : public InProcessBrowserTest
{
28 ServiceProcessControlBrowserTest() {
30 virtual ~ServiceProcessControlBrowserTest() {
33 void HistogramsCallback() {
34 MockHistogramsCallback();
38 MOCK_METHOD0(MockHistogramsCallback
, void());
41 void LaunchServiceProcessControl() {
42 // Launch the process asynchronously.
43 ServiceProcessControl::GetInstance()->Launch(
44 base::Bind(&ServiceProcessControlBrowserTest::ProcessControlLaunched
,
47 &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed
,
50 // Then run the message loop to keep things running.
51 content::RunMessageLoop();
54 static void QuitMessageLoop() {
55 base::MessageLoop::current()->Quit();
58 static void CloudPrintInfoCallback(
59 const cloud_print::CloudPrintProxyInfo
& proxy_info
) {
64 // This will close the IPC connection.
65 ServiceProcessControl::GetInstance()->Disconnect();
68 void SetUp() override
{
69 // This should not be needed because TearDown() ends with a closed
70 // service_process_, but HistogramsTimeout and Histograms fail without this
72 service_process_
.Close();
75 void TearDown() override
{
76 if (ServiceProcessControl::GetInstance()->IsConnected())
77 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
78 #if defined(OS_MACOSX)
79 // ForceServiceProcessShutdown removes the process from launched on Mac.
80 ForceServiceProcessShutdown("", 0);
82 if (service_process_
.IsValid()) {
84 EXPECT_TRUE(service_process_
.WaitForExitWithTimeout(
85 TestTimeouts::action_max_timeout(), &exit_code
));
86 EXPECT_EQ(0, exit_code
);
87 service_process_
.Close();
91 void ProcessControlLaunched() {
92 base::ProcessId service_pid
;
93 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
94 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
97 base::Process::OpenWithAccess(service_pid
,
98 SYNCHRONIZE
| PROCESS_QUERY_INFORMATION
);
100 service_process_
= base::Process::Open(service_pid
);
102 EXPECT_TRUE(service_process_
.IsValid());
103 // Quit the current message. Post a QuitTask instead of just calling Quit()
104 // because this can get invoked in the context of a Launch() call and we
105 // may not be in Run() yet.
106 base::MessageLoop::current()->PostTask(FROM_HERE
,
107 base::MessageLoop::QuitClosure());
110 void ProcessControlLaunchFailed() {
112 // Quit the current message.
113 base::MessageLoop::current()->PostTask(FROM_HERE
,
114 base::MessageLoop::QuitClosure());
118 base::Process service_process_
;
121 class RealServiceProcessControlBrowserTest
122 : public ServiceProcessControlBrowserTest
{
124 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
125 ServiceProcessControlBrowserTest::SetUpCommandLine(command_line
);
127 PathService::Get(base::DIR_EXE
, &exe
);
128 #if defined(OS_MACOSX)
129 exe
= exe
.DirName().DirName().DirName();
131 exe
= exe
.Append(chrome::kHelperProcessExecutablePath
);
132 // Run chrome instead of browser_tests.exe.
133 EXPECT_TRUE(base::PathExists(exe
));
134 command_line
->AppendSwitchPath(switches::kBrowserSubprocessPath
, exe
);
138 // TODO(vitalybuka): Fix crbug.com/340563
139 IN_PROC_BROWSER_TEST_F(RealServiceProcessControlBrowserTest
,
140 DISABLED_LaunchAndIPC
) {
141 LaunchServiceProcessControl();
143 // Make sure we are connected to the service process.
144 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
145 ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
146 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
));
147 content::RunMessageLoop();
149 // And then shutdown the service process.
150 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
153 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, LaunchAndIPC
) {
154 LaunchServiceProcessControl();
156 // Make sure we are connected to the service process.
157 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
158 ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
159 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
));
160 content::RunMessageLoop();
162 // And then shutdown the service process.
163 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
166 // This tests the case when a service process is launched when the browser
167 // starts but we try to launch it again while setting up Cloud Print.
168 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, LaunchTwice
) {
169 // Launch the service process the first time.
170 LaunchServiceProcessControl();
172 // Make sure we are connected to the service process.
173 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
174 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
175 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
)));
176 content::RunMessageLoop();
178 // Launch the service process again.
179 LaunchServiceProcessControl();
180 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
181 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
182 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
)));
183 content::RunMessageLoop();
186 static void DecrementUntilZero(int* count
) {
189 base::MessageLoop::current()->PostTask(FROM_HERE
,
190 base::MessageLoop::QuitClosure());
193 // Invoke multiple Launch calls in succession and ensure that all the tasks
195 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
,
196 MultipleLaunchTasks
) {
197 ServiceProcessControl
* process
= ServiceProcessControl::GetInstance();
198 int launch_count
= 5;
199 for (int i
= 0; i
< launch_count
; i
++) {
200 // Launch the process asynchronously.
201 process
->Launch(base::Bind(&DecrementUntilZero
, &launch_count
),
202 base::MessageLoop::QuitClosure());
204 // Then run the message loop to keep things running.
205 content::RunMessageLoop();
206 EXPECT_EQ(0, launch_count
);
209 // Make sure using the same task for success and failure tasks works.
210 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, SameLaunchTask
) {
211 ServiceProcessControl
* process
= ServiceProcessControl::GetInstance();
212 int launch_count
= 5;
213 for (int i
= 0; i
< launch_count
; i
++) {
214 // Launch the process asynchronously.
215 base::Closure task
= base::Bind(&DecrementUntilZero
, &launch_count
);
216 process
->Launch(task
, task
);
218 // Then run the message loop to keep things running.
219 content::RunMessageLoop();
220 EXPECT_EQ(0, launch_count
);
223 // Tests whether disconnecting from the service IPC causes the service process
225 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, DieOnDisconnect
) {
226 // Launch the service process.
227 LaunchServiceProcessControl();
228 // Make sure we are connected to the service process.
229 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
233 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, ForceShutdown
) {
234 // Launch the service process.
235 LaunchServiceProcessControl();
236 // Make sure we are connected to the service process.
237 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
238 base::ProcessId service_pid
;
239 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
240 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
241 chrome::VersionInfo version_info
;
242 ForceServiceProcessShutdown(version_info
.Version(), service_pid
);
245 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, CheckPid
) {
246 base::ProcessId service_pid
;
247 EXPECT_FALSE(GetServiceProcessData(NULL
, &service_pid
));
248 // Launch the service process.
249 LaunchServiceProcessControl();
250 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
251 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
252 // Disconnect from service process.
256 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, HistogramsNoService
) {
257 ASSERT_FALSE(ServiceProcessControl::GetInstance()->IsConnected());
258 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
259 EXPECT_FALSE(ServiceProcessControl::GetInstance()->GetHistograms(
260 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
261 base::Unretained(this)),
265 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, HistogramsTimeout
) {
266 LaunchServiceProcessControl();
267 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
268 // Callback should not be called during GetHistograms call.
269 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
270 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
271 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
272 base::Unretained(this)),
273 base::TimeDelta::FromMilliseconds(100)));
274 EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
275 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
276 content::RunMessageLoop();
279 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, Histograms
) {
280 LaunchServiceProcessControl();
281 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
282 // Callback should not be called during GetHistograms call.
283 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
284 // Wait for real callback by providing large timeout value.
285 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
286 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
287 base::Unretained(this)),
288 base::TimeDelta::FromHours(1)));
289 EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
290 content::RunMessageLoop();