service_process_control_browsertest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 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/process_util.h"
6#include "base/test/test_timeouts.h"
7#include "chrome/browser/service/service_process_control.h"
8#include "chrome/browser/service/service_process_control_manager.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/common/chrome_version_info.h"
11#include "chrome/common/service_process_util.h"
12#include "chrome/test/in_process_browser_test.h"
13#include "chrome/test/ui_test_utils.h"
14
15class ServiceProcessControlBrowserTest
16    : public InProcessBrowserTest {
17 public:
18  ServiceProcessControlBrowserTest()
19      : service_process_handle_(base::kNullProcessHandle) {
20  }
21  ~ServiceProcessControlBrowserTest() {
22    base::CloseProcessHandle(service_process_handle_);
23    service_process_handle_ = base::kNullProcessHandle;
24    // Delete all instances of ServiceProcessControl.
25    ServiceProcessControlManager::GetInstance()->Shutdown();
26  }
27
28#if defined(OS_MACOSX)
29  virtual void TearDown() {
30    // ForceServiceProcessShutdown removes the process from launchd on Mac.
31    ForceServiceProcessShutdown("", 0);
32  }
33#endif  // OS_MACOSX
34
35 protected:
36  void LaunchServiceProcessControl() {
37    ServiceProcessControl* process =
38        ServiceProcessControlManager::GetInstance()->GetProcessControl(
39            browser()->profile());
40    process_ = process;
41
42    // Launch the process asynchronously.
43    process->Launch(
44        NewRunnableMethod(
45            this,
46            &ServiceProcessControlBrowserTest::ProcessControlLaunched),
47        NewRunnableMethod(
48            this,
49            &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed));
50
51    // Then run the message loop to keep things running.
52    ui_test_utils::RunMessageLoop();
53  }
54
55  // Send a remoting host status request and wait reply from the service.
56  void SendRequestAndWait() {
57    process()->GetCloudPrintProxyStatus(NewCallback(
58        this, &ServiceProcessControlBrowserTest::CloudPrintStatusCallback));
59    ui_test_utils::RunMessageLoop();
60  }
61
62  void CloudPrintStatusCallback(
63      bool enabled, std::string email) {
64    MessageLoop::current()->Quit();
65  }
66
67  void Disconnect() {
68    // This will delete all instances of ServiceProcessControl and close the IPC
69    // connections.
70    ServiceProcessControlManager::GetInstance()->Shutdown();
71    process_ = NULL;
72  }
73
74  void WaitForShutdown() {
75    EXPECT_TRUE(base::WaitForSingleProcess(
76        service_process_handle_,
77        TestTimeouts::wait_for_terminate_timeout_ms()));
78  }
79
80  void ProcessControlLaunched() {
81    base::ProcessId service_pid;
82    EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
83    EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
84    EXPECT_TRUE(base::OpenProcessHandleWithAccess(
85        service_pid,
86        base::kProcessAccessWaitForTermination,
87        &service_process_handle_));
88    // Quit the current message. Post a QuitTask instead of just calling Quit()
89    // because this can get invoked in the context of a Launch() call and we
90    // may not be in Run() yet.
91    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
92  }
93
94  void ProcessControlLaunchFailed() {
95    ADD_FAILURE();
96    // Quit the current message.
97    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
98  }
99
100  ServiceProcessControl* process() { return process_; }
101
102 private:
103  ServiceProcessControl* process_;
104  base::ProcessHandle service_process_handle_;
105};
106
107// They way that the IPC is implemented only works on windows. This has to
108// change when we implement a different scheme for IPC.
109// Times out flakily, http://crbug.com/70076.
110IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
111                       DISABLED_LaunchAndIPC) {
112  LaunchServiceProcessControl();
113
114  // Make sure we are connected to the service process.
115  EXPECT_TRUE(process()->is_connected());
116  SendRequestAndWait();
117
118  // And then shutdown the service process.
119  EXPECT_TRUE(process()->Shutdown());
120}
121
122// This tests the case when a service process is launched when browser
123// starts but we try to launch it again in the remoting setup dialog.
124IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchTwice) {
125  // Launch the service process the first time.
126  LaunchServiceProcessControl();
127
128  // Make sure we are connected to the service process.
129  EXPECT_TRUE(process()->is_connected());
130  SendRequestAndWait();
131
132  // Launch the service process again.
133  LaunchServiceProcessControl();
134  EXPECT_TRUE(process()->is_connected());
135  SendRequestAndWait();
136
137  // And then shutdown the service process.
138  EXPECT_TRUE(process()->Shutdown());
139}
140
141static void DecrementUntilZero(int* count) {
142  (*count)--;
143  if (!(*count))
144    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
145}
146
147// Invoke multiple Launch calls in succession and ensure that all the tasks
148// get invoked.
149IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MultipleLaunchTasks) {
150  ServiceProcessControl* process =
151      ServiceProcessControlManager::GetInstance()->GetProcessControl(
152          browser()->profile());
153  int launch_count = 5;
154  for (int i = 0; i < launch_count; i++) {
155    // Launch the process asynchronously.
156    process->Launch(
157        NewRunnableFunction(&DecrementUntilZero, &launch_count),
158        new MessageLoop::QuitTask());
159  }
160  // Then run the message loop to keep things running.
161  ui_test_utils::RunMessageLoop();
162  EXPECT_EQ(0, launch_count);
163  // And then shutdown the service process.
164  EXPECT_TRUE(process->Shutdown());
165}
166
167// Make sure using the same task for success and failure tasks works.
168IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, SameLaunchTask) {
169  ServiceProcessControl* process =
170      ServiceProcessControlManager::GetInstance()->GetProcessControl(
171          browser()->profile());
172  int launch_count = 5;
173  for (int i = 0; i < launch_count; i++) {
174    // Launch the process asynchronously.
175    Task * task = NewRunnableFunction(&DecrementUntilZero, &launch_count);
176    process->Launch(task, task);
177  }
178  // Then run the message loop to keep things running.
179  ui_test_utils::RunMessageLoop();
180  EXPECT_EQ(0, launch_count);
181  // And then shutdown the service process.
182  EXPECT_TRUE(process->Shutdown());
183}
184
185// Tests whether disconnecting from the service IPC causes the service process
186// to die.
187IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, DieOnDisconnect) {
188  // Launch the service process.
189  LaunchServiceProcessControl();
190  // Make sure we are connected to the service process.
191  EXPECT_TRUE(process()->is_connected());
192  Disconnect();
193  WaitForShutdown();
194}
195
196//http://code.google.com/p/chromium/issues/detail?id=70793
197IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
198                       DISABLED_ForceShutdown) {
199  // Launch the service process.
200  LaunchServiceProcessControl();
201  // Make sure we are connected to the service process.
202  EXPECT_TRUE(process()->is_connected());
203  base::ProcessId service_pid;
204  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
205  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
206  chrome::VersionInfo version_info;
207  ForceServiceProcessShutdown(version_info.Version(), service_pid);
208  WaitForShutdown();
209}
210
211IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, CheckPid) {
212  base::ProcessId service_pid;
213  EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid));
214  // Launch the service process.
215  LaunchServiceProcessControl();
216  EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
217  EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
218}
219
220DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest);
221