diff options
author | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-13 20:27:04 +0000 |
---|---|---|
committer | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-13 20:27:04 +0000 |
commit | 146354945e1fb1a915ecb009c6732e0e28db9adc (patch) | |
tree | 248ec50922622796c7df09720b30c3f4ad6d2fa6 /chrome/common/service_process_util_win.cc | |
parent | 6da080717a2ef41e6292090427386d9079e73a59 (diff) | |
download | chromium_src-146354945e1fb1a915ecb009c6732e0e28db9adc.zip chromium_src-146354945e1fb1a915ecb009c6732e0e28db9adc.tar.gz chromium_src-146354945e1fb1a915ecb009c6732e0e28db9adc.tar.bz2 |
Spilt code in service_process_utils.cc into separate files for Windows and Posix. Added unit-tests for this file. Also created a ServiceProcessState class that manages global state for the service process.
BUG=None
TEST=Unit-tests, cloud print proxy.
Review URL: http://codereview.chromium.org/3745001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62448 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/service_process_util_win.cc')
-rw-r--r-- | chrome/common/service_process_util_win.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/chrome/common/service_process_util_win.cc b/chrome/common/service_process_util_win.cc new file mode 100644 index 0000000..6d233e9 --- /dev/null +++ b/chrome/common/service_process_util_win.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/service_process_util.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/object_watcher.h" +#include "base/path_service.h" +#include "base/scoped_handle_win.h" +#include "base/string16.h" +#include "base/utf_string_conversions.h" +#include "base/win_util.h" +#include "chrome/common/chrome_switches.h" + +namespace { + +string16 GetServiceProcessReadyEventName() { + return UTF8ToWide( + GetServiceProcessScopedVersionedName("_service_ready")); +} + +string16 GetServiceProcessShutdownEventName() { + return UTF8ToWide( + GetServiceProcessScopedVersionedName("_service_shutdown_evt")); +} + +class ServiceProcessShutdownMonitor : public base::ObjectWatcher::Delegate { + public: + explicit ServiceProcessShutdownMonitor(Task* shutdown_task) + : shutdown_task_(shutdown_task) { + } + void Start() { + string16 event_name = GetServiceProcessShutdownEventName(); + CHECK(event_name.length() <= MAX_PATH); + shutdown_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); + watcher_.StartWatching(shutdown_event_.Get(), this); + } + + // base::ObjectWatcher::Delegate implementation. + virtual void OnObjectSignaled(HANDLE object) { + shutdown_task_->Run(); + shutdown_task_.reset(); + } + + private: + ScopedHandle shutdown_event_; + base::ObjectWatcher watcher_; + scoped_ptr<Task> shutdown_task_; +}; + +} // namespace + +bool ForceServiceProcessShutdown(const std::string& version) { + ScopedHandle shutdown_event; + std::string versioned_name = version; + versioned_name.append("_service_shutdown_evt"); + string16 event_name = + UTF8ToWide(GetServiceProcessScopedName(versioned_name)); + shutdown_event.Set(OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name.c_str())); + if (!shutdown_event.IsValid()) + return false; + SetEvent(shutdown_event.Get()); + return true; +} + +bool CheckServiceProcessReady() { + string16 event_name = GetServiceProcessReadyEventName(); + ScopedHandle event( + OpenEvent(SYNCHRONIZE | READ_CONTROL, false, event_name.c_str())); + if (!event.IsValid()) + return false; + // Check if the event is signaled. + return WaitForSingleObject(event, 0) == WAIT_OBJECT_0; +} + +struct ServiceProcessState::StateData { + // An event that is signaled when a service process is ready. + ScopedHandle ready_event; + scoped_ptr<ServiceProcessShutdownMonitor> shutdown_monitor; +}; + +bool ServiceProcessState::TakeSingletonLock() { + DCHECK(!state_); + string16 event_name = GetServiceProcessReadyEventName(); + CHECK(event_name.length() <= MAX_PATH); + ScopedHandle service_process_ready_event; + service_process_ready_event.Set( + CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); + DWORD error = GetLastError(); + if ((error == ERROR_ALREADY_EXISTS) || (error == ERROR_ACCESS_DENIED)) + return false; + DCHECK(service_process_ready_event.IsValid()); + state_ = new StateData; + state_->ready_event.Set(service_process_ready_event.Take()); + return true; +} + +void ServiceProcessState::SignalReady(Task* shutdown_task) { + DCHECK(state_); + DCHECK(state_->ready_event.IsValid()); + SetEvent(state_->ready_event.Get()); + if (shutdown_task) { + state_->shutdown_monitor.reset( + new ServiceProcessShutdownMonitor(shutdown_task)); + state_->shutdown_monitor->Start(); + } +} + +void ServiceProcessState::SignalStopped() { + TearDownState(); + shared_mem_service_data_.reset(); +} + +bool ServiceProcessState::AddToAutoRun() { + FilePath chrome_path; + if (PathService::Get(base::FILE_EXE, &chrome_path)) { + CommandLine cmd_line(chrome_path); + cmd_line.AppendSwitchASCII(switches::kProcessType, + switches::kServiceProcess); + // We need a unique name for the command per user-date-dir. Just use the + // channel name. + return win_util::AddCommandToAutoRun( + HKEY_CURRENT_USER, + UTF8ToWide(GetAutoRunKey()), + cmd_line.command_line_string()); + } + return false; +} + +bool ServiceProcessState::RemoveFromAutoRun() { + return win_util::RemoveCommandFromAutoRun( + HKEY_CURRENT_USER, UTF8ToWide(GetAutoRunKey())); +} + +void ServiceProcessState::TearDownState() { + delete state_; + state_ = NULL; +} + +bool ServiceProcessState::ShouldHandleOtherVersion() { + return true; +} |