service_process_util_win.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 "chrome/common/service_process_util.h" 6 7#include "base/command_line.h" 8#include "base/file_util.h" 9#include "base/logging.h" 10#include "base/object_watcher.h" 11#include "base/path_service.h" 12#include "base/scoped_handle_win.h" 13#include "base/string16.h" 14#include "base/utf_string_conversions.h" 15#include "base/win_util.h" 16#include "chrome/common/chrome_switches.h" 17 18namespace { 19 20string16 GetServiceProcessReadyEventName() { 21 return UTF8ToWide( 22 GetServiceProcessScopedVersionedName("_service_ready")); 23} 24 25string16 GetServiceProcessShutdownEventName() { 26 return UTF8ToWide( 27 GetServiceProcessScopedVersionedName("_service_shutdown_evt")); 28} 29 30class ServiceProcessShutdownMonitor : public base::ObjectWatcher::Delegate { 31 public: 32 explicit ServiceProcessShutdownMonitor(Task* shutdown_task) 33 : shutdown_task_(shutdown_task) { 34 } 35 void Start() { 36 string16 event_name = GetServiceProcessShutdownEventName(); 37 CHECK(event_name.length() <= MAX_PATH); 38 shutdown_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); 39 watcher_.StartWatching(shutdown_event_.Get(), this); 40 } 41 42 // base::ObjectWatcher::Delegate implementation. 43 virtual void OnObjectSignaled(HANDLE object) { 44 shutdown_task_->Run(); 45 shutdown_task_.reset(); 46 } 47 48 private: 49 ScopedHandle shutdown_event_; 50 base::ObjectWatcher watcher_; 51 scoped_ptr<Task> shutdown_task_; 52}; 53 54} // namespace 55 56bool ForceServiceProcessShutdown(const std::string& version) { 57 ScopedHandle shutdown_event; 58 std::string versioned_name = version; 59 versioned_name.append("_service_shutdown_evt"); 60 string16 event_name = 61 UTF8ToWide(GetServiceProcessScopedName(versioned_name)); 62 shutdown_event.Set(OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name.c_str())); 63 if (!shutdown_event.IsValid()) 64 return false; 65 SetEvent(shutdown_event.Get()); 66 return true; 67} 68 69bool CheckServiceProcessReady() { 70 string16 event_name = GetServiceProcessReadyEventName(); 71 ScopedHandle event( 72 OpenEvent(SYNCHRONIZE | READ_CONTROL, false, event_name.c_str())); 73 if (!event.IsValid()) 74 return false; 75 // Check if the event is signaled. 76 return WaitForSingleObject(event, 0) == WAIT_OBJECT_0; 77} 78 79struct ServiceProcessState::StateData { 80 // An event that is signaled when a service process is ready. 81 ScopedHandle ready_event; 82 scoped_ptr<ServiceProcessShutdownMonitor> shutdown_monitor; 83}; 84 85bool ServiceProcessState::TakeSingletonLock() { 86 DCHECK(!state_); 87 string16 event_name = GetServiceProcessReadyEventName(); 88 CHECK(event_name.length() <= MAX_PATH); 89 ScopedHandle service_process_ready_event; 90 service_process_ready_event.Set( 91 CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); 92 DWORD error = GetLastError(); 93 if ((error == ERROR_ALREADY_EXISTS) || (error == ERROR_ACCESS_DENIED)) 94 return false; 95 DCHECK(service_process_ready_event.IsValid()); 96 state_ = new StateData; 97 state_->ready_event.Set(service_process_ready_event.Take()); 98 return true; 99} 100 101void ServiceProcessState::SignalReady(Task* shutdown_task) { 102 DCHECK(state_); 103 DCHECK(state_->ready_event.IsValid()); 104 SetEvent(state_->ready_event.Get()); 105 if (shutdown_task) { 106 state_->shutdown_monitor.reset( 107 new ServiceProcessShutdownMonitor(shutdown_task)); 108 state_->shutdown_monitor->Start(); 109 } 110} 111 112void ServiceProcessState::SignalStopped() { 113 TearDownState(); 114 shared_mem_service_data_.reset(); 115} 116 117bool ServiceProcessState::AddToAutoRun() { 118 FilePath chrome_path; 119 if (PathService::Get(base::FILE_EXE, &chrome_path)) { 120 CommandLine cmd_line(chrome_path); 121 cmd_line.AppendSwitchASCII(switches::kProcessType, 122 switches::kServiceProcess); 123 // We need a unique name for the command per user-date-dir. Just use the 124 // channel name. 125 return win_util::AddCommandToAutoRun( 126 HKEY_CURRENT_USER, 127 UTF8ToWide(GetAutoRunKey()), 128 cmd_line.command_line_string()); 129 } 130 return false; 131} 132 133bool ServiceProcessState::RemoveFromAutoRun() { 134 return win_util::RemoveCommandFromAutoRun( 135 HKEY_CURRENT_USER, UTF8ToWide(GetAutoRunKey())); 136} 137 138void ServiceProcessState::TearDownState() { 139 delete state_; 140 state_ = NULL; 141} 142 143bool ServiceProcessState::ShouldHandleOtherVersion() { 144 return true; 145} 146