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