Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / common / service_process_util_win.cc
blobdf7c039d5de33b6a7f41c1bcf0b35c9c3085e9bd
1 // Copyright (c) 2011 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.
5 #include "chrome/common/service_process_util.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/win/object_watcher.h"
16 #include "base/win/scoped_handle.h"
17 #include "base/win/win_util.h"
18 #include "chrome/common/chrome_paths.h"
19 #include "chrome/common/chrome_switches.h"
21 namespace {
23 const char kTerminateEventSuffix[] = "_service_terminate_evt";
25 base::string16 GetServiceProcessReadyEventName() {
26 return base::UTF8ToWide(
27 GetServiceProcessScopedVersionedName("_service_ready"));
30 base::string16 GetServiceProcessTerminateEventName() {
31 return base::UTF8ToWide(
32 GetServiceProcessScopedVersionedName(kTerminateEventSuffix));
35 std::string GetServiceProcessAutoRunKey() {
36 return GetServiceProcessScopedName("_service_run");
39 // Returns the name of the autotun reg value that we used to use for older
40 // versions of Chrome.
41 std::string GetObsoleteServiceProcessAutoRunKey() {
42 base::FilePath user_data_dir;
43 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
44 std::string scoped_name = base::WideToUTF8(user_data_dir.value());
45 std::replace(scoped_name.begin(), scoped_name.end(), '\\', '!');
46 std::replace(scoped_name.begin(), scoped_name.end(), '/', '!');
47 scoped_name.append("_service_run");
48 return scoped_name;
51 class ServiceProcessTerminateMonitor
52 : public base::win::ObjectWatcher::Delegate {
53 public:
54 explicit ServiceProcessTerminateMonitor(const base::Closure& terminate_task)
55 : terminate_task_(terminate_task) {
57 void Start() {
58 base::string16 event_name = GetServiceProcessTerminateEventName();
59 DCHECK(event_name.length() <= MAX_PATH);
60 terminate_event_.Set(CreateEvent(NULL, TRUE, FALSE, event_name.c_str()));
61 watcher_.StartWatching(terminate_event_.Get(), this);
64 // base::ObjectWatcher::Delegate implementation.
65 void OnObjectSignaled(HANDLE object) override {
66 if (!terminate_task_.is_null()) {
67 terminate_task_.Run();
68 terminate_task_.Reset();
72 private:
73 base::win::ScopedHandle terminate_event_;
74 base::win::ObjectWatcher watcher_;
75 base::Closure terminate_task_;
78 } // namespace
80 // Gets the name of the service process IPC channel.
81 IPC::ChannelHandle GetServiceProcessChannel() {
82 return GetServiceProcessScopedVersionedName("_service_ipc");
85 bool ForceServiceProcessShutdown(const std::string& version,
86 base::ProcessId process_id) {
87 base::win::ScopedHandle terminate_event;
88 std::string versioned_name = version;
89 versioned_name.append(kTerminateEventSuffix);
90 base::string16 event_name =
91 base::UTF8ToWide(GetServiceProcessScopedName(versioned_name));
92 terminate_event.Set(OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name.c_str()));
93 if (!terminate_event.IsValid())
94 return false;
95 SetEvent(terminate_event.Get());
96 return true;
99 bool CheckServiceProcessReady() {
100 base::string16 event_name = GetServiceProcessReadyEventName();
101 base::win::ScopedHandle event(
102 OpenEvent(SYNCHRONIZE | READ_CONTROL, false, event_name.c_str()));
103 if (!event.IsValid())
104 return false;
105 // Check if the event is signaled.
106 return WaitForSingleObject(event.Get(), 0) == WAIT_OBJECT_0;
109 struct ServiceProcessState::StateData {
110 // An event that is signaled when a service process is ready.
111 base::win::ScopedHandle ready_event;
112 scoped_ptr<ServiceProcessTerminateMonitor> terminate_monitor;
115 void ServiceProcessState::CreateState() {
116 DCHECK(!state_);
117 state_ = new StateData;
120 bool ServiceProcessState::TakeSingletonLock() {
121 DCHECK(state_);
122 base::string16 event_name = GetServiceProcessReadyEventName();
123 DCHECK(event_name.length() <= MAX_PATH);
124 base::win::ScopedHandle service_process_ready_event;
125 service_process_ready_event.Set(
126 CreateEvent(NULL, TRUE, FALSE, event_name.c_str()));
127 DWORD error = GetLastError();
128 if ((error == ERROR_ALREADY_EXISTS) || (error == ERROR_ACCESS_DENIED))
129 return false;
130 DCHECK(service_process_ready_event.IsValid());
131 state_->ready_event.Set(service_process_ready_event.Take());
132 return true;
135 bool ServiceProcessState::SignalReady(base::SingleThreadTaskRunner* task_runner,
136 const base::Closure& terminate_task) {
137 DCHECK(state_);
138 DCHECK(state_->ready_event.IsValid());
139 if (!SetEvent(state_->ready_event.Get())) {
140 return false;
142 if (!terminate_task.is_null()) {
143 state_->terminate_monitor.reset(
144 new ServiceProcessTerminateMonitor(terminate_task));
145 state_->terminate_monitor->Start();
147 return true;
150 bool ServiceProcessState::AddToAutoRun() {
151 DCHECK(autorun_command_line_.get());
152 // Remove the old autorun value first because we changed the naming scheme
153 // for the autorun value name.
154 base::win::RemoveCommandFromAutoRun(
155 HKEY_CURRENT_USER,
156 base::UTF8ToWide(GetObsoleteServiceProcessAutoRunKey()));
157 return base::win::AddCommandToAutoRun(
158 HKEY_CURRENT_USER,
159 base::UTF8ToWide(GetServiceProcessAutoRunKey()),
160 autorun_command_line_->GetCommandLineString());
163 bool ServiceProcessState::RemoveFromAutoRun() {
164 // Remove the old autorun value first because we changed the naming scheme
165 // for the autorun value name.
166 base::win::RemoveCommandFromAutoRun(
167 HKEY_CURRENT_USER,
168 base::UTF8ToWide(GetObsoleteServiceProcessAutoRunKey()));
169 return base::win::RemoveCommandFromAutoRun(
170 HKEY_CURRENT_USER, base::UTF8ToWide(GetServiceProcessAutoRunKey()));
173 void ServiceProcessState::TearDownState() {
174 delete state_;
175 state_ = NULL;