diff options
-rw-r--r-- | base/process_util.h | 44 | ||||
-rw-r--r-- | base/process_util_posix.cc | 8 | ||||
-rw-r--r-- | base/process_util_win.cc | 12 | ||||
-rw-r--r-- | chrome/browser/service/service_process_control_browsertest.cc | 56 |
4 files changed, 86 insertions, 34 deletions
diff --git a/base/process_util.h b/base/process_util.h index 6876e88..38d96ec 100644 --- a/base/process_util.h +++ b/base/process_util.h @@ -50,7 +50,6 @@ class FilePath; namespace base { #if defined(OS_WIN) - struct ProcessEntry : public PROCESSENTRY32 { ProcessId pid() const { return th32ProcessID; } ProcessId parent_pid() const { return th32ParentProcessID; } @@ -60,6 +59,25 @@ struct ProcessEntry : public PROCESSENTRY32 { struct IoCounters : public IO_COUNTERS { }; +// Process access masks. These constants provide platform-independent +// definitions for the standard Windows access masks. +// See http://msdn.microsoft.com/en-us/library/ms684880(VS.85).aspx for +// the specific semantics of each mask value. +const uint32 kProcessAccessTerminate = PROCESS_TERMINATE; +const uint32 kProcessAccessCreateThread = PROCESS_CREATE_THREAD; +const uint32 kProcessAccessSetSessionId = PROCESS_SET_SESSIONID; +const uint32 kProcessAccessVMOperation = PROCESS_VM_OPERATION; +const uint32 kProcessAccessVMRead = PROCESS_VM_READ; +const uint32 kProcessAccessVMWrite = PROCESS_VM_WRITE; +const uint32 kProcessAccessDuplicateHandle = PROCESS_DUP_HANDLE; +const uint32 kProcessAccessCreateProcess = PROCESS_CREATE_PROCESS; +const uint32 kProcessAccessSetQuota = PROCESS_SET_QUOTA; +const uint32 kProcessAccessSetInformation = PROCESS_SET_INFORMATION; +const uint32 kProcessAccessQueryInformation = PROCESS_QUERY_INFORMATION; +const uint32 kProcessAccessSuspendResume = PROCESS_SUSPEND_RESUME; +const uint32 kProcessAccessQueryLimitedInfomation = + PROCESS_QUERY_LIMITED_INFORMATION; +const uint32 kProcessAccessWaitForTermination = SYNCHRONIZE; #elif defined(OS_POSIX) struct ProcessEntry { @@ -87,6 +105,22 @@ struct IoCounters { uint64_t OtherTransferCount; }; +// Process access masks. They are not used on Posix because access checking +// does not happen during handle creation. +const uint32 kProcessAccessTerminate = 0; +const uint32 kProcessAccessCreateThread = 0; +const uint32 kProcessAccessSetSessionId = 0; +const uint32 kProcessAccessVMOperation = 0; +const uint32 kProcessAccessVMRead = 0; +const uint32 kProcessAccessVMWrite = 0; +const uint32 kProcessAccessDuplicateHandle = 0; +const uint32 kProcessAccessCreateProcess = 0; +const uint32 kProcessAccessSetQuota = 0; +const uint32 kProcessAccessSetInformation = 0; +const uint32 kProcessAccessQueryInformation = 0; +const uint32 kProcessAccessSuspendResume = 0; +const uint32 kProcessAccessQueryLimitedInfomation = 0; +const uint32 kProcessAccessWaitForTermination = 0; #endif // defined(OS_POSIX) // A minimalistic but hopefully cross-platform set of exit codes. @@ -112,8 +146,16 @@ bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); // with more access rights and must only be used by trusted code. // You have to close returned handle using CloseProcessHandle. Returns true // on success. +// TODO(sanjeevr): Replace all calls to OpenPrivilegedProcessHandle with the +// more specific OpenProcessHandleWithAccess method and delete this. bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle); +// Converts a PID to a process handle using the desired access flags. Use a +// combination of the kProcessAccess* flags defined above for |access_flags|. +bool OpenProcessHandleWithAccess(ProcessId pid, + uint32 access_flags, + ProcessHandle* handle); + // Closes the process handle opened by OpenProcessHandle. void CloseProcessHandle(ProcessHandle process); diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc index 31a8e9d..d3b8818 100644 --- a/base/process_util_posix.cc +++ b/base/process_util_posix.cc @@ -139,6 +139,14 @@ bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) { return OpenProcessHandle(pid, handle); } +bool OpenProcessHandleWithAccess(ProcessId pid, + uint32 access_flags, + ProcessHandle* handle) { + // On POSIX permissions are checked for each operation on process, + // not when opening a "handle". + return OpenProcessHandle(pid, handle); +} + void CloseProcessHandle(ProcessHandle process) { // See OpenProcessHandle, nothing to do. return; diff --git a/base/process_util_win.cc b/base/process_util_win.cc index c5d7790..f3e0cac 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -119,6 +119,18 @@ bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) { return true; } +bool OpenProcessHandleWithAccess(ProcessId pid, + uint32 access_flags, + ProcessHandle* handle) { + ProcessHandle result = OpenProcess(access_flags, FALSE, pid); + + if (result == INVALID_HANDLE_VALUE) + return false; + + *handle = result; + return true; +} + void CloseProcessHandle(ProcessHandle process) { CloseHandle(process); } diff --git a/chrome/browser/service/service_process_control_browsertest.cc b/chrome/browser/service/service_process_control_browsertest.cc index c9038e6..9775e40 100644 --- a/chrome/browser/service/service_process_control_browsertest.cc +++ b/chrome/browser/service/service_process_control_browsertest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/process_util.h" #include "base/test/test_timeouts.h" #include "chrome/browser/browser.h" #include "chrome/browser/service/service_process_control.h" @@ -14,6 +15,15 @@ class ServiceProcessControlBrowserTest : public InProcessBrowserTest, public ServiceProcessControl::MessageHandler { + public: + ServiceProcessControlBrowserTest() + : service_process_handle_(base::kNullProcessHandle) { + } + ~ServiceProcessControlBrowserTest() { + base::CloseProcessHandle(service_process_handle_); + service_process_handle_ = base::kNullProcessHandle; + } + protected: void LaunchServiceProcessControl() { ServiceProcessControl* process = @@ -37,48 +47,26 @@ class ServiceProcessControlBrowserTest ui_test_utils::RunMessageLoop(); } - void DisconnectAndWaitForShutdown() { + void Disconnect() { // This will delete all instances of ServiceProcessControl and close the IPC // connections. ServiceProcessControlManager::instance()->Shutdown(); process_ = NULL; - WaitForShutdown(); } void WaitForShutdown() { - // We will keep trying every second till we hit the terminate timeout. - // TODO(sanjeevr): Use GetServiceProcessPid() to wait for termination. - // Will do this in a separate CL. - int retries_left = TestTimeouts::wait_for_terminate_timeout_ms()/1000; - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - NewRunnableMethod(this, - &ServiceProcessControlBrowserTest::DoDetectShutdown, - retries_left), - 1000); - ui_test_utils::RunMessageLoop(); - } - - void DoDetectShutdown(int retries_left) { - bool service_is_running = CheckServiceProcessReady(); - if (!retries_left) - EXPECT_FALSE(service_is_running); - if (retries_left && service_is_running) { - retries_left--; - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - NewRunnableMethod(this, - &ServiceProcessControlBrowserTest::DoDetectShutdown, - retries_left), - 1000); - } else { - // Quit the current message loop. - MessageLoop::current()->PostTask(FROM_HERE, - new MessageLoop::QuitTask()); - } + EXPECT_TRUE(base::WaitForSingleProcess( + service_process_handle_, + TestTimeouts::wait_for_terminate_timeout_ms())); } void ProcessControlLaunched() { + base::ProcessId service_pid = GetServiceProcessPid(); + EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); + EXPECT_TRUE(base::OpenProcessHandleWithAccess( + service_pid, + base::kProcessAccessWaitForTermination, + &service_process_handle_)); process()->SetMessageHandler(this); // Quit the current message. MessageLoop::current()->PostTask(FROM_HERE, @@ -95,6 +83,7 @@ class ServiceProcessControlBrowserTest private: ServiceProcessControl* process_; + base::ProcessHandle service_process_handle_; }; #if defined(OS_WIN) @@ -137,7 +126,8 @@ IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, DieOnDisconnect) { LaunchServiceProcessControl(); // Make sure we are connected to the service process. EXPECT_TRUE(process()->is_connected()); - DisconnectAndWaitForShutdown(); + Disconnect(); + WaitForShutdown(); } IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, ForceShutdown) { |