18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Copyright (c) 2011 The Chromium Authors. All rights reserved. 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Use of this source code is governed by a BSD-style license that can be 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// found in the LICENSE file. 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "chrome/common/service_process_util.h" 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/command_line.h" 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/file_util.h" 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/logging.h" 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/memory/scoped_ptr.h" 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/path_service.h" 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/string16.h" 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/task.h" 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/utf_string_conversions.h" 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/win/object_watcher.h" 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/win/scoped_handle.h" 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "base/win/win_util.h" 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "chrome/common/chrome_paths.h" 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "chrome/common/chrome_switches.h" 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace { 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstring16 GetServiceProcessReadyEventName() { 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return UTF8ToWide( 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GetServiceProcessScopedVersionedName("_service_ready")); 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstring16 GetServiceProcessShutdownEventName() { 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return UTF8ToWide( 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GetServiceProcessScopedVersionedName("_service_shutdown_evt")); 31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstd::string GetServiceProcessAutoRunKey() { 348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return GetServiceProcessScopedName("_service_run"); 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Returns the name of the autotun reg value that we used to use for older 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// versions of Chrome. 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstd::string GetObsoleteServiceProcessAutoRunKey() { 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FilePath user_data_dir; 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project std::string scoped_name = WideToUTF8(user_data_dir.value()); 43635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project std::replace(scoped_name.begin(), scoped_name.end(), '\\', '!'); 44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block std::replace(scoped_name.begin(), scoped_name.end(), '/', '!'); 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scoped_name.append("_service_run"); 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return scoped_name; 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass ServiceProcessShutdownMonitor 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : public base::win::ObjectWatcher::Delegate { 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project public: 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project explicit ServiceProcessShutdownMonitor(Task* shutdown_task) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project : shutdown_task_(shutdown_task) { 54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block void Start() { 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string16 event_name = GetServiceProcessShutdownEventName(); 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CHECK(event_name.length() <= MAX_PATH); 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project shutdown_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); 59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block watcher_.StartWatching(shutdown_event_.Get(), this); 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // base::ObjectWatcher::Delegate implementation. 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project virtual void OnObjectSignaled(HANDLE object) { 64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project shutdown_task_->Run(); 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project shutdown_task_.reset(); 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block private: 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ScopedHandle shutdown_event_; 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ObjectWatcher watcher_; 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scoped_ptr<Task> shutdown_task_; 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ForceServiceProcessShutdown(const std::string& version, 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::ProcessId process_id) { 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ScopedHandle shutdown_event; 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project std::string versioned_name = version; 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project versioned_name.append("_service_shutdown_evt"); 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string16 event_name = 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UTF8ToWide(GetServiceProcessScopedName(versioned_name)); 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project shutdown_event.Set(OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name.c_str())); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!shutdown_event.IsValid()) 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SetEvent(shutdown_event.Get()); 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool CheckServiceProcessReady() { 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string16 event_name = GetServiceProcessReadyEventName(); 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ScopedHandle event( 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project OpenEvent(SYNCHRONIZE | READ_CONTROL, false, event_name.c_str())); 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!event.IsValid()) 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check if the event is signaled. 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return WaitForSingleObject(event, 0) == WAIT_OBJECT_0; 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct ServiceProcessState::StateData { 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // An event that is signaled when a service process is ready. 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ScopedHandle ready_event; 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scoped_ptr<ServiceProcessShutdownMonitor> shutdown_monitor; 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ServiceProcessState::CreateState() { 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CHECK(!state_); 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project state_ = new StateData; 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ServiceProcessState::TakeSingletonLock() { 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DCHECK(state_); 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project string16 event_name = GetServiceProcessReadyEventName(); 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CHECK(event_name.length() <= MAX_PATH); 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::ScopedHandle service_process_ready_event; 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project service_process_ready_event.Set( 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project CreateEvent(NULL, TRUE, FALSE, event_name.c_str())); 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DWORD error = GetLastError(); 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((error == ERROR_ALREADY_EXISTS) || (error == ERROR_ACCESS_DENIED)) 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DCHECK(service_process_ready_event.IsValid()); 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block state_->ready_event.Set(service_process_ready_event.Take()); 123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return true; 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ServiceProcessState::SignalReady( 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::MessageLoopProxy* message_loop_proxy, Task* shutdown_task) { 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DCHECK(state_); 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DCHECK(state_->ready_event.IsValid()); 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project scoped_ptr<Task> scoped_shutdown_task(shutdown_task); 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!SetEvent(state_->ready_event.Get())) { 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (shutdown_task) { 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project state_->shutdown_monitor.reset( 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project new ServiceProcessShutdownMonitor(scoped_shutdown_task.release())); 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project state_->shutdown_monitor->Start(); 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 141643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ServiceProcessState::AddToAutoRun() { 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project DCHECK(autorun_command_line_.get()); 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove the old autorun value first because we changed the naming scheme 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // for the autorun value name. 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::RemoveCommandFromAutoRun( 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HKEY_CURRENT_USER, UTF8ToWide(GetObsoleteServiceProcessAutoRunKey())); 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return base::win::AddCommandToAutoRun( 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HKEY_CURRENT_USER, 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project UTF8ToWide(GetServiceProcessAutoRunKey()), 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project autorun_command_line_->command_line_string()); 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 154643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool ServiceProcessState::RemoveFromAutoRun() { 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Remove the old autorun value first because we changed the naming scheme 156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // for the autorun value name. 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project base::win::RemoveCommandFromAutoRun( 158643ca7872b450ea4efacab6188849e5aac2ba161Steve Block HKEY_CURRENT_USER, UTF8ToWide(GetObsoleteServiceProcessAutoRunKey())); 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return base::win::RemoveCommandFromAutoRun( 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HKEY_CURRENT_USER, UTF8ToWide(GetServiceProcessAutoRunKey())); 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ServiceProcessState::TearDownState() { 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete state_; 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project state_ = NULL; 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project