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/location.h"
11 #include "base/path_service.h"
12 #include "base/process/kill.h"
13 #include "base/process/process.h"
14 #include "base/process/process_iterator.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "chrome/common/service_process_util.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "components/version_info/version_info.h"
23 #include "content/public/common/content_paths.h"
24 #include "content/public/common/content_switches.h"
25 #include "content/public/test/test_utils.h"
26 #include "testing/gmock/include/gmock/gmock.h"
28 class ServiceProcessControlBrowserTest
29 : public InProcessBrowserTest
{
31 ServiceProcessControlBrowserTest() {
33 virtual ~ServiceProcessControlBrowserTest() {
36 void HistogramsCallback() {
37 MockHistogramsCallback();
41 MOCK_METHOD0(MockHistogramsCallback
, void());
44 void LaunchServiceProcessControl() {
45 // Launch the process asynchronously.
46 ServiceProcessControl::GetInstance()->Launch(
47 base::Bind(&ServiceProcessControlBrowserTest::ProcessControlLaunched
,
50 &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed
,
53 // Then run the message loop to keep things running.
54 content::RunMessageLoop();
57 static void QuitMessageLoop() {
58 base::MessageLoop::current()->Quit();
61 static void CloudPrintInfoCallback(
62 const cloud_print::CloudPrintProxyInfo
& proxy_info
) {
67 // This will close the IPC connection.
68 ServiceProcessControl::GetInstance()->Disconnect();
71 void SetUp() override
{
72 InProcessBrowserTest::SetUp();
74 // This should not be needed because TearDown() ends with a closed
75 // service_process_, but HistogramsTimeout and Histograms fail without this
77 service_process_
.Close();
80 void TearDown() override
{
81 if (ServiceProcessControl::GetInstance()->IsConnected())
82 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
83 #if defined(OS_MACOSX)
84 // ForceServiceProcessShutdown removes the process from launched on Mac.
85 ForceServiceProcessShutdown("", 0);
87 if (service_process_
.IsValid()) {
89 EXPECT_TRUE(service_process_
.WaitForExitWithTimeout(
90 TestTimeouts::action_max_timeout(), &exit_code
));
91 EXPECT_EQ(0, exit_code
);
92 service_process_
.Close();
95 InProcessBrowserTest::TearDown();
98 void ProcessControlLaunched() {
99 base::ProcessId service_pid
;
100 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
101 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
104 base::Process::OpenWithAccess(service_pid
,
105 SYNCHRONIZE
| PROCESS_QUERY_INFORMATION
);
107 service_process_
= base::Process::Open(service_pid
);
109 EXPECT_TRUE(service_process_
.IsValid());
110 // Quit the current message. Post a QuitTask instead of just calling Quit()
111 // because this can get invoked in the context of a Launch() call and we
112 // may not be in Run() yet.
113 base::ThreadTaskRunnerHandle::Get()->PostTask(
114 FROM_HERE
, base::MessageLoop::QuitClosure());
117 void ProcessControlLaunchFailed() {
119 // Quit the current message.
120 base::ThreadTaskRunnerHandle::Get()->PostTask(
121 FROM_HERE
, base::MessageLoop::QuitClosure());
125 base::Process service_process_
;
128 class RealServiceProcessControlBrowserTest
129 : public ServiceProcessControlBrowserTest
{
131 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
132 ServiceProcessControlBrowserTest::SetUpCommandLine(command_line
);
134 PathService::Get(base::DIR_EXE
, &exe
);
135 #if defined(OS_MACOSX)
136 exe
= exe
.DirName().DirName().DirName();
138 exe
= exe
.Append(chrome::kHelperProcessExecutablePath
);
139 // Run chrome instead of browser_tests.exe.
140 EXPECT_TRUE(base::PathExists(exe
));
141 command_line
->AppendSwitchPath(switches::kBrowserSubprocessPath
, exe
);
145 // TODO(vitalybuka): Fix crbug.com/340563
146 IN_PROC_BROWSER_TEST_F(RealServiceProcessControlBrowserTest
,
147 DISABLED_LaunchAndIPC
) {
148 LaunchServiceProcessControl();
150 // Make sure we are connected to the service process.
151 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
152 ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
153 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
));
154 content::RunMessageLoop();
156 // And then shutdown the service process.
157 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
160 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, LaunchAndIPC
) {
161 LaunchServiceProcessControl();
163 // Make sure we are connected to the service process.
164 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
165 ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
166 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
));
167 content::RunMessageLoop();
169 // And then shutdown the service process.
170 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
173 // This tests the case when a service process is launched when the browser
174 // starts but we try to launch it again while setting up Cloud Print.
175 // Flaky on Mac. http://crbug.com/517420
176 #if defined(OS_MACOSX)
177 #define MAYBE_LaunchTwice DISABLED_LaunchTwice
179 #define MAYBE_LaunchTwice LaunchTwice
181 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, MAYBE_LaunchTwice
) {
182 // Launch the service process the first time.
183 LaunchServiceProcessControl();
185 // Make sure we are connected to the service process.
186 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
187 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
188 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
)));
189 content::RunMessageLoop();
191 // Launch the service process again.
192 LaunchServiceProcessControl();
193 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
194 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
195 base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback
)));
196 content::RunMessageLoop();
199 static void DecrementUntilZero(int* count
) {
202 base::ThreadTaskRunnerHandle::Get()->PostTask(
203 FROM_HERE
, base::MessageLoop::QuitClosure());
206 // Flaky on Mac. http://crbug.com/517420
207 #if defined(OS_MACOSX)
208 #define MAYBE_MultipleLaunchTasks DISABLED_MultipleLaunchTasks
210 #define MAYBE_MultipleLaunchTasks MultipleLaunchTasks
212 // Invoke multiple Launch calls in succession and ensure that all the tasks
214 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
,
215 MAYBE_MultipleLaunchTasks
) {
216 ServiceProcessControl
* process
= ServiceProcessControl::GetInstance();
217 int launch_count
= 5;
218 for (int i
= 0; i
< launch_count
; i
++) {
219 // Launch the process asynchronously.
220 process
->Launch(base::Bind(&DecrementUntilZero
, &launch_count
),
221 base::MessageLoop::QuitClosure());
223 // Then run the message loop to keep things running.
224 content::RunMessageLoop();
225 EXPECT_EQ(0, launch_count
);
228 // Flaky on Mac. http://crbug.com/517420
229 #if defined(OS_MACOSX)
230 #define MAYBE_SameLaunchTask DISABLED_SameLaunchTask
232 #define MAYBE_SameLaunchTask SameLaunchTask
234 // Make sure using the same task for success and failure tasks works.
235 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, MAYBE_SameLaunchTask
) {
236 ServiceProcessControl
* process
= ServiceProcessControl::GetInstance();
237 int launch_count
= 5;
238 for (int i
= 0; i
< launch_count
; i
++) {
239 // Launch the process asynchronously.
240 base::Closure task
= base::Bind(&DecrementUntilZero
, &launch_count
);
241 process
->Launch(task
, task
);
243 // Then run the message loop to keep things running.
244 content::RunMessageLoop();
245 EXPECT_EQ(0, launch_count
);
248 // Tests whether disconnecting from the service IPC causes the service process
250 // Flaky on Mac. http://crbug.com/517420
251 #if defined(OS_MACOSX)
252 #define MAYBE_DieOnDisconnect DISABLED_DieOnDisconnect
254 #define MAYBE_DieOnDisconnect DieOnDisconnect
256 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
,
257 MAYBE_DieOnDisconnect
) {
258 // Launch the service process.
259 LaunchServiceProcessControl();
260 // Make sure we are connected to the service process.
261 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
265 // Flaky on Mac. http://crbug.com/517420
266 #if defined(OS_MACOSX)
267 #define MAYBE_ForceShutdown DISABLED_ForceShutdown
269 #define MAYBE_ForceShutdown ForceShutdown
271 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, MAYBE_ForceShutdown
) {
272 // Launch the service process.
273 LaunchServiceProcessControl();
274 // Make sure we are connected to the service process.
275 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
276 base::ProcessId service_pid
;
277 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
278 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
279 ForceServiceProcessShutdown(version_info::GetVersionNumber(), service_pid
);
282 // Flaky on Mac. http://crbug.com/517420
283 #if defined(OS_MACOSX)
284 #define MAYBE_CheckPid DISABLED_CheckPid
286 #define MAYBE_CheckPid CheckPid
288 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, MAYBE_CheckPid
) {
289 base::ProcessId service_pid
;
290 EXPECT_FALSE(GetServiceProcessData(NULL
, &service_pid
));
291 // Launch the service process.
292 LaunchServiceProcessControl();
293 EXPECT_TRUE(GetServiceProcessData(NULL
, &service_pid
));
294 EXPECT_NE(static_cast<base::ProcessId
>(0), service_pid
);
295 // Disconnect from service process.
299 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, HistogramsNoService
) {
300 ASSERT_FALSE(ServiceProcessControl::GetInstance()->IsConnected());
301 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
302 EXPECT_FALSE(ServiceProcessControl::GetInstance()->GetHistograms(
303 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
304 base::Unretained(this)),
308 // Histograms disabled on OSX http://crbug.com/406227
309 #if defined(OS_MACOSX)
310 #define MAYBE_HistogramsTimeout DISABLED_HistogramsTimeout
311 #define MAYBE_Histograms DISABLED_Histograms
313 #define MAYBE_HistogramsTimeout HistogramsTimeout
314 #define MAYBE_Histograms Histograms
316 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
,
317 MAYBE_HistogramsTimeout
) {
318 LaunchServiceProcessControl();
319 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
320 // Callback should not be called during GetHistograms call.
321 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
322 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
323 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
324 base::Unretained(this)),
325 base::TimeDelta::FromMilliseconds(100)));
326 EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
327 EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
328 content::RunMessageLoop();
331 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest
, MAYBE_Histograms
) {
332 LaunchServiceProcessControl();
333 ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
334 // Callback should not be called during GetHistograms call.
335 EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
336 // Wait for real callback by providing large timeout value.
337 EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
338 base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback
,
339 base::Unretained(this)),
340 base::TimeDelta::FromHours(1)));
341 EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
342 content::RunMessageLoop();