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 15 class 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. 110 IN_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. 124 // Crashes on mac. http://crbug.com/75518 125 #if defined(OS_MACOSX) 126 #define MAYBE_LaunchTwice DISABLED_LaunchTwice 127 #else 128 #define MAYBE_LaunchTwice LaunchTwice 129 #endif 130 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_LaunchTwice) { 131 // Launch the service process the first time. 132 LaunchServiceProcessControl(); 133 134 // Make sure we are connected to the service process. 135 EXPECT_TRUE(process()->is_connected()); 136 SendRequestAndWait(); 137 138 // Launch the service process again. 139 LaunchServiceProcessControl(); 140 EXPECT_TRUE(process()->is_connected()); 141 SendRequestAndWait(); 142 143 // And then shutdown the service process. 144 EXPECT_TRUE(process()->Shutdown()); 145 } 146 147 static void DecrementUntilZero(int* count) { 148 (*count)--; 149 if (!(*count)) 150 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 151 } 152 153 // Invoke multiple Launch calls in succession and ensure that all the tasks 154 // get invoked. 155 // Crashes on mac. http://crbug.com/75518 156 #if defined(OS_MACOSX) 157 #define MAYBE_MultipleLaunchTasks DISABLED_MultipleLaunchTasks 158 #else 159 #define MAYBE_MultipleLaunchTasks MultipleLaunchTasks 160 #endif 161 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, 162 MAYBE_MultipleLaunchTasks) { 163 ServiceProcessControl* process = 164 ServiceProcessControlManager::GetInstance()->GetProcessControl( 165 browser()->profile()); 166 int launch_count = 5; 167 for (int i = 0; i < launch_count; i++) { 168 // Launch the process asynchronously. 169 process->Launch( 170 NewRunnableFunction(&DecrementUntilZero, &launch_count), 171 new MessageLoop::QuitTask()); 172 } 173 // Then run the message loop to keep things running. 174 ui_test_utils::RunMessageLoop(); 175 EXPECT_EQ(0, launch_count); 176 // And then shutdown the service process. 177 EXPECT_TRUE(process->Shutdown()); 178 } 179 180 // Make sure using the same task for success and failure tasks works. 181 // Crashes on mac. http://crbug.com/75518 182 #if defined(OS_MACOSX) 183 #define MAYBE_SameLaunchTask DISABLED_SameLaunchTask 184 #else 185 #define MAYBE_SameLaunchTask SameLaunchTask 186 #endif 187 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_SameLaunchTask) { 188 ServiceProcessControl* process = 189 ServiceProcessControlManager::GetInstance()->GetProcessControl( 190 browser()->profile()); 191 int launch_count = 5; 192 for (int i = 0; i < launch_count; i++) { 193 // Launch the process asynchronously. 194 Task * task = NewRunnableFunction(&DecrementUntilZero, &launch_count); 195 process->Launch(task, task); 196 } 197 // Then run the message loop to keep things running. 198 ui_test_utils::RunMessageLoop(); 199 EXPECT_EQ(0, launch_count); 200 // And then shutdown the service process. 201 EXPECT_TRUE(process->Shutdown()); 202 } 203 204 // Tests whether disconnecting from the service IPC causes the service process 205 // to die. 206 // Crashes on mac. http://crbug.com/75518 207 #if defined(OS_MACOSX) 208 #define MAYBE_DieOnDisconnect DISABLED_DieOnDisconnect 209 #else 210 #define MAYBE_DieOnDisconnect DieOnDisconnect 211 #endif 212 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, 213 MAYBE_DieOnDisconnect) { 214 // Launch the service process. 215 LaunchServiceProcessControl(); 216 // Make sure we are connected to the service process. 217 EXPECT_TRUE(process()->is_connected()); 218 Disconnect(); 219 WaitForShutdown(); 220 } 221 222 //http://code.google.com/p/chromium/issues/detail?id=70793 223 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, 224 DISABLED_ForceShutdown) { 225 // Launch the service process. 226 LaunchServiceProcessControl(); 227 // Make sure we are connected to the service process. 228 EXPECT_TRUE(process()->is_connected()); 229 base::ProcessId service_pid; 230 EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); 231 EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); 232 chrome::VersionInfo version_info; 233 ForceServiceProcessShutdown(version_info.Version(), service_pid); 234 WaitForShutdown(); 235 } 236 237 // Crashes on mac. http://crbug.com/75518 238 #if defined(OS_MACOSX) 239 #define MAYBE_CheckPid DISABLED_CheckPid 240 #else 241 #define MAYBE_CheckPid CheckPid 242 #endif 243 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, MAYBE_CheckPid) { 244 base::ProcessId service_pid; 245 EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid)); 246 // Launch the service process. 247 LaunchServiceProcessControl(); 248 EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); 249 EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); 250 } 251 252 DISABLE_RUNNABLE_METHOD_REFCOUNT(ServiceProcessControlBrowserTest); 253