OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/service_process_util_posix.h" | 5 #include "chrome/common/service_process_util_posix.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
8 #include <launch.h> | 8 #include <launch.h> |
9 | 9 |
10 #include <vector> | 10 #include <vector> |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 return IPC::ChannelHandle(socket_path); | 109 return IPC::ChannelHandle(socket_path); |
110 } | 110 } |
111 | 111 |
112 bool ForceServiceProcessShutdown(const std::string& /* version */, | 112 bool ForceServiceProcessShutdown(const std::string& /* version */, |
113 base::ProcessId /* process_id */) { | 113 base::ProcessId /* process_id */) { |
114 base::mac::ScopedNSAutoreleasePool pool; | 114 base::mac::ScopedNSAutoreleasePool pool; |
115 CFStringRef label = base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); | 115 CFStringRef label = base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); |
116 CFErrorRef err = NULL; | 116 CFErrorRef err = NULL; |
117 bool ret = Launchd::GetInstance()->RemoveJob(label, &err); | 117 bool ret = Launchd::GetInstance()->RemoveJob(label, &err); |
118 if (!ret) { | 118 if (!ret) { |
119 LOG(ERROR) << "ForceServiceProcessShutdown: " << err << " " | 119 DLOG(ERROR) << "ForceServiceProcessShutdown: " << err << " " |
120 << base::SysCFStringRefToUTF8(label); | 120 << base::SysCFStringRefToUTF8(label); |
121 CFRelease(err); | 121 CFRelease(err); |
122 } | 122 } |
123 return ret; | 123 return ret; |
124 } | 124 } |
125 | 125 |
126 bool GetServiceProcessData(std::string* version, base::ProcessId* pid) { | 126 bool GetServiceProcessData(std::string* version, base::ProcessId* pid) { |
127 base::mac::ScopedNSAutoreleasePool pool; | 127 base::mac::ScopedNSAutoreleasePool pool; |
128 CFStringRef label = base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); | 128 CFStringRef label = base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); |
129 scoped_nsobject<NSDictionary> launchd_conf(base::mac::CFToNSCast( | 129 scoped_nsobject<NSDictionary> launchd_conf(base::mac::CFToNSCast( |
130 Launchd::GetInstance()->CopyJobDictionary(label))); | 130 Launchd::GetInstance()->CopyJobDictionary(label))); |
131 if (!launchd_conf.get()) { | 131 if (!launchd_conf.get()) { |
132 return false; | 132 return false; |
133 } | 133 } |
134 // Anything past here will return true in that there does appear | 134 // Anything past here will return true in that there does appear |
135 // to be a service process of some sort registered with launchd. | 135 // to be a service process of some sort registered with launchd. |
136 if (version) { | 136 if (version) { |
137 *version = "0"; | 137 *version = "0"; |
138 NSString *exe_path = [launchd_conf objectForKey:@ LAUNCH_JOBKEY_PROGRAM]; | 138 NSString *exe_path = [launchd_conf objectForKey:@ LAUNCH_JOBKEY_PROGRAM]; |
139 if (exe_path) { | 139 if (exe_path) { |
140 NSString *bundle_path = [[[exe_path stringByDeletingLastPathComponent] | 140 NSString *bundle_path = [[[exe_path stringByDeletingLastPathComponent] |
141 stringByDeletingLastPathComponent] | 141 stringByDeletingLastPathComponent] |
142 stringByDeletingLastPathComponent]; | 142 stringByDeletingLastPathComponent]; |
143 NSBundle *bundle = [NSBundle bundleWithPath:bundle_path]; | 143 NSBundle *bundle = [NSBundle bundleWithPath:bundle_path]; |
144 if (bundle) { | 144 if (bundle) { |
145 NSString *ns_version = | 145 NSString *ns_version = |
146 [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; | 146 [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; |
147 if (ns_version) { | 147 if (ns_version) { |
148 *version = base::SysNSStringToUTF8(ns_version); | 148 *version = base::SysNSStringToUTF8(ns_version); |
149 } else { | 149 } else { |
150 LOG(ERROR) << "Unable to get version at: " | 150 DLOG(ERROR) << "Unable to get version at: " |
151 << reinterpret_cast<CFStringRef>(bundle_path); | 151 << reinterpret_cast<CFStringRef>(bundle_path); |
152 } | 152 } |
153 } else { | 153 } else { |
154 // The bundle has been deleted out from underneath the registered | 154 // The bundle has been deleted out from underneath the registered |
155 // job. | 155 // job. |
156 LOG(ERROR) << "Unable to get bundle at: " | 156 DLOG(ERROR) << "Unable to get bundle at: " |
157 << reinterpret_cast<CFStringRef>(bundle_path); | 157 << reinterpret_cast<CFStringRef>(bundle_path); |
158 } | 158 } |
159 } else { | 159 } else { |
160 LOG(ERROR) << "Unable to get executable path for service process"; | 160 DLOG(ERROR) << "Unable to get executable path for service process"; |
161 } | 161 } |
162 } | 162 } |
163 if (pid) { | 163 if (pid) { |
164 *pid = -1; | 164 *pid = -1; |
165 NSNumber* ns_pid = [launchd_conf objectForKey:@ LAUNCH_JOBKEY_PID]; | 165 NSNumber* ns_pid = [launchd_conf objectForKey:@ LAUNCH_JOBKEY_PID]; |
166 if (ns_pid) { | 166 if (ns_pid) { |
167 *pid = [ns_pid intValue]; | 167 *pid = [ns_pid intValue]; |
168 } | 168 } |
169 } | 169 } |
170 return true; | 170 return true; |
171 } | 171 } |
172 | 172 |
173 bool ServiceProcessState::Initialize() { | 173 bool ServiceProcessState::Initialize() { |
174 CFErrorRef err = NULL; | 174 CFErrorRef err = NULL; |
175 CFDictionaryRef dict = | 175 CFDictionaryRef dict = |
176 Launchd::GetInstance()->CopyDictionaryByCheckingIn(&err); | 176 Launchd::GetInstance()->CopyDictionaryByCheckingIn(&err); |
177 if (!dict) { | 177 if (!dict) { |
178 LOG(ERROR) << "ServiceProcess must be launched by launchd. " | 178 DLOG(ERROR) << "ServiceProcess must be launched by launchd. " |
179 << "CopyLaunchdDictionaryByCheckingIn: " << err; | 179 << "CopyLaunchdDictionaryByCheckingIn: " << err; |
180 CFRelease(err); | 180 CFRelease(err); |
181 return false; | 181 return false; |
182 } | 182 } |
183 state_->launchd_conf_.reset(dict); | 183 state_->launchd_conf_.reset(dict); |
184 return true; | 184 return true; |
185 } | 185 } |
186 | 186 |
187 IPC::ChannelHandle ServiceProcessState::GetServiceProcessChannel() { | 187 IPC::ChannelHandle ServiceProcessState::GetServiceProcessChannel() { |
188 CHECK(state_); | 188 DCHECK(state_); |
189 NSDictionary *ns_launchd_conf = base::mac::CFToNSCast(state_->launchd_conf_); | 189 NSDictionary *ns_launchd_conf = base::mac::CFToNSCast(state_->launchd_conf_); |
190 NSDictionary* socket_dict = | 190 NSDictionary* socket_dict = |
191 [ns_launchd_conf objectForKey:@ LAUNCH_JOBKEY_SOCKETS]; | 191 [ns_launchd_conf objectForKey:@ LAUNCH_JOBKEY_SOCKETS]; |
192 NSArray* sockets = | 192 NSArray* sockets = |
193 [socket_dict objectForKey:GetServiceProcessLaunchDSocketKey()]; | 193 [socket_dict objectForKey:GetServiceProcessLaunchDSocketKey()]; |
194 CHECK_EQ([sockets count], 1U); | 194 DCHECK_EQ([sockets count], 1U); |
195 int socket = [[sockets objectAtIndex:0] intValue]; | 195 int socket = [[sockets objectAtIndex:0] intValue]; |
196 base::FileDescriptor fd(socket, false); | 196 base::FileDescriptor fd(socket, false); |
197 return IPC::ChannelHandle(std::string(), fd); | 197 return IPC::ChannelHandle(std::string(), fd); |
198 } | 198 } |
199 | 199 |
200 bool CheckServiceProcessReady() { | 200 bool CheckServiceProcessReady() { |
201 std::string version; | 201 std::string version; |
202 pid_t pid; | 202 pid_t pid; |
203 if (!GetServiceProcessData(&version, &pid)) { | 203 if (!GetServiceProcessData(&version, &pid)) { |
204 return false; | 204 return false; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 | 306 |
307 bool ServiceProcessState::RemoveFromAutoRun() { | 307 bool ServiceProcessState::RemoveFromAutoRun() { |
308 return RemoveFromLaunchd(); | 308 return RemoveFromLaunchd(); |
309 } | 309 } |
310 | 310 |
311 bool ServiceProcessState::StateData::WatchExecutable() { | 311 bool ServiceProcessState::StateData::WatchExecutable() { |
312 base::mac::ScopedNSAutoreleasePool pool; | 312 base::mac::ScopedNSAutoreleasePool pool; |
313 NSDictionary* ns_launchd_conf = base::mac::CFToNSCast(launchd_conf_); | 313 NSDictionary* ns_launchd_conf = base::mac::CFToNSCast(launchd_conf_); |
314 NSString* exe_path = [ns_launchd_conf objectForKey:@ LAUNCH_JOBKEY_PROGRAM]; | 314 NSString* exe_path = [ns_launchd_conf objectForKey:@ LAUNCH_JOBKEY_PROGRAM]; |
315 if (!exe_path) { | 315 if (!exe_path) { |
316 LOG(ERROR) << "No " LAUNCH_JOBKEY_PROGRAM; | 316 DLOG(ERROR) << "No " LAUNCH_JOBKEY_PROGRAM; |
317 return false; | 317 return false; |
318 } | 318 } |
319 | 319 |
320 FilePath executable_path = FilePath([exe_path fileSystemRepresentation]); | 320 FilePath executable_path = FilePath([exe_path fileSystemRepresentation]); |
321 scoped_ptr<ExecFilePathWatcherDelegate> delegate( | 321 scoped_ptr<ExecFilePathWatcherDelegate> delegate( |
322 new ExecFilePathWatcherDelegate); | 322 new ExecFilePathWatcherDelegate); |
323 if (!delegate->Init(executable_path)) { | 323 if (!delegate->Init(executable_path)) { |
324 LOG(ERROR) << "executable_watcher_.Init " << executable_path.value(); | 324 DLOG(ERROR) << "executable_watcher_.Init " << executable_path.value(); |
325 return false; | 325 return false; |
326 } | 326 } |
327 if (!executable_watcher_.Watch(executable_path, delegate.release())) { | 327 if (!executable_watcher_.Watch(executable_path, delegate.release())) { |
328 LOG(ERROR) << "executable_watcher_.watch " << executable_path.value(); | 328 DLOG(ERROR) << "executable_watcher_.watch " << executable_path.value(); |
329 return false; | 329 return false; |
330 } | 330 } |
331 return true; | 331 return true; |
332 } | 332 } |
333 | 333 |
334 bool ExecFilePathWatcherDelegate::Init(const FilePath& path) { | 334 bool ExecFilePathWatcherDelegate::Init(const FilePath& path) { |
335 return base::mac::FSRefFromPath(path.value(), &executable_fsref_); | 335 return base::mac::FSRefFromPath(path.value(), &executable_fsref_); |
336 } | 336 } |
337 | 337 |
338 void ExecFilePathWatcherDelegate::OnFilePathChanged(const FilePath& path) { | 338 void ExecFilePathWatcherDelegate::OnFilePathChanged(const FilePath& path) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 [ns_plist setObject:ns_new_path forKey:@ LAUNCH_JOBKEY_PROGRAM]; | 397 [ns_plist setObject:ns_new_path forKey:@ LAUNCH_JOBKEY_PROGRAM]; |
398 scoped_nsobject<NSMutableArray> args( | 398 scoped_nsobject<NSMutableArray> args( |
399 [[ns_plist objectForKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS] | 399 [[ns_plist objectForKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS] |
400 mutableCopy]); | 400 mutableCopy]); |
401 [args replaceObjectAtIndex:0 withObject:ns_new_path]; | 401 [args replaceObjectAtIndex:0 withObject:ns_new_path]; |
402 [ns_plist setObject:args forKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS]; | 402 [ns_plist setObject:args forKey:@ LAUNCH_JOBKEY_PROGRAMARGUMENTS]; |
403 if (!Launchd::GetInstance()->WritePlistToFile(Launchd::User, | 403 if (!Launchd::GetInstance()->WritePlistToFile(Launchd::User, |
404 Launchd::Agent, | 404 Launchd::Agent, |
405 name, | 405 name, |
406 plist)) { | 406 plist)) { |
407 LOG(ERROR) << "Unable to rewrite plist."; | 407 DLOG(ERROR) << "Unable to rewrite plist."; |
408 needs_shutdown = true; | 408 needs_shutdown = true; |
409 } | 409 } |
410 } else { | 410 } else { |
411 LOG(ERROR) << "Unable to read plist."; | 411 DLOG(ERROR) << "Unable to read plist."; |
412 needs_shutdown = true; | 412 needs_shutdown = true; |
413 } | 413 } |
414 } | 414 } |
415 if (needs_shutdown) { | 415 if (needs_shutdown) { |
416 if (!RemoveFromLaunchd()) { | 416 if (!RemoveFromLaunchd()) { |
417 LOG(ERROR) << "Unable to RemoveFromLaunchd."; | 417 DLOG(ERROR) << "Unable to RemoveFromLaunchd."; |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 // Then deal with the process. | 421 // Then deal with the process. |
422 CFStringRef session_type = CFSTR(kServiceProcessSessionType); | 422 CFStringRef session_type = CFSTR(kServiceProcessSessionType); |
423 if (needs_restart) { | 423 if (needs_restart) { |
424 if (!Launchd::GetInstance()->RestartJob(Launchd::User, | 424 if (!Launchd::GetInstance()->RestartJob(Launchd::User, |
425 Launchd::Agent, | 425 Launchd::Agent, |
426 name, | 426 name, |
427 session_type)) { | 427 session_type)) { |
428 LOG(ERROR) << "RestartLaunchdJob"; | 428 DLOG(ERROR) << "RestartLaunchdJob"; |
429 needs_shutdown = true; | 429 needs_shutdown = true; |
430 } | 430 } |
431 } | 431 } |
432 if (needs_shutdown) { | 432 if (needs_shutdown) { |
433 CFStringRef label = | 433 CFStringRef label = |
434 base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); | 434 base::mac::NSToCFCast(GetServiceProcessLaunchDLabel()); |
435 CFErrorRef err = NULL; | 435 CFErrorRef err = NULL; |
436 if (!Launchd::GetInstance()->RemoveJob(label, &err)) { | 436 if (!Launchd::GetInstance()->RemoveJob(label, &err)) { |
437 base::mac::ScopedCFTypeRef<CFErrorRef> scoped_err(err); | 437 base::mac::ScopedCFTypeRef<CFErrorRef> scoped_err(err); |
438 LOG(ERROR) << "RemoveJob " << err; | 438 DLOG(ERROR) << "RemoveJob " << err; |
439 // Exiting with zero, so launchd doesn't restart the process. | 439 // Exiting with zero, so launchd doesn't restart the process. |
440 exit(0); | 440 exit(0); |
441 } | 441 } |
442 } | 442 } |
443 } | 443 } |
444 } | 444 } |
OLD | NEW |