Index: chrome/common/launchd_mac.mm |
diff --git a/chrome/common/launchd_mac.mm b/chrome/common/launchd_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0c930bb5c0a8ff9a266f8833a9fc477a1ff96496 |
--- /dev/null |
+++ b/chrome/common/launchd_mac.mm |
@@ -0,0 +1,167 @@ |
+// Copyright (c) 2011 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/launchd_mac.h" |
+ |
+#import <Foundation/Foundation.h> |
+#include <launch.h> |
+ |
+#include "base/mac/mac_util.h" |
+#include "base/mac/scoped_cftyperef.h" |
+#include "base/mac/scoped_nsautorelease_pool.h" |
+#include "base/process_util.h" |
+#include "base/stringprintf.h" |
+#include "base/sys_string_conversions.h" |
+#include "third_party/GTM/Foundation/GTMServiceManagement.h" |
+ |
+namespace { |
+ |
+NSString* SanitizeShellArgument(NSString* arg) { |
+ if (!arg) { |
+ return nil; |
+ } |
+ NSString *sanitize = [arg stringByReplacingOccurrencesOfString:@"'" |
+ withString:@"'\''"]; |
+ return [NSString stringWithFormat:@"'%@'", sanitize]; |
+} |
+ |
+NSURL* GetPlistURL(Launchd::Domain domain, |
+ Launchd::Type type, |
+ CFStringRef name) { |
+ NSArray* library_paths = |
+ NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, domain, YES); |
+ DCHECK_EQ([library_paths count], 1U); |
+ NSString* library_path = [library_paths objectAtIndex:0]; |
+ |
+ NSString *launch_dir_name = (type == Launchd::Daemon) ? @"LaunchDaemons" |
+ : @"LaunchAgents"; |
+ NSString* launch_dir = |
+ [library_path stringByAppendingPathComponent:launch_dir_name]; |
+ |
+ NSError* err; |
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:launch_dir |
+ withIntermediateDirectories:YES |
+ attributes:nil |
+ error:&err]) { |
+ LOG(ERROR) << "GetPlistURL " << base::mac::NSToCFCast(err); |
+ return nil; |
+ } |
+ |
+ NSString* plist_file_path = |
+ [launch_dir stringByAppendingPathComponent:base::mac::CFToNSCast(name)]; |
+ plist_file_path = [plist_file_path stringByAppendingPathExtension:@"plist"]; |
+ return [NSURL fileURLWithPath:plist_file_path isDirectory:NO]; |
+} |
+ |
+} // namespace |
+ |
+COMPILE_ASSERT(static_cast<int>(Launchd::User) == |
+ static_cast<int>(NSUserDomainMask), foundation_value_changed); |
Mark Mentovai
2011/03/22 00:48:24
You should use a different msg (second parameter)
dmac
2011/03/22 03:13:32
Done.
|
+COMPILE_ASSERT(static_cast<int>(Launchd::Local) == |
+ static_cast<int>(NSLocalDomainMask), foundation_value_changed); |
+COMPILE_ASSERT(static_cast<int>(Launchd::Network) == |
+ static_cast<int>(NSNetworkDomainMask), foundation_value_changed); |
+COMPILE_ASSERT(static_cast<int>(Launchd::System) == |
+ static_cast<int>(NSSystemDomainMask), foundation_value_changed); |
+ |
+Launchd* Launchd::g_instance_ = NULL; |
+ |
+Launchd* Launchd::GetInstance() { |
+ if (!g_instance_) { |
+ g_instance_ = Singleton<Launchd>::get(); |
+ } |
+ return g_instance_; |
+} |
+ |
+void Launchd::SetInstance(Launchd* instance) { |
+ if (instance) { |
+ CHECK(!g_instance_); |
+ } |
+ g_instance_ = instance; |
+} |
+ |
+Launchd::~Launchd() { } |
+ |
+CFDictionaryRef Launchd::CopyExports() { |
+ return GTMCopyLaunchdExports(); |
+} |
+ |
+CFDictionaryRef Launchd::CopyJobDictionary(CFStringRef label) { |
+ return GTMSMJobCopyDictionary(label); |
+} |
+ |
+CFDictionaryRef Launchd::CopyDictionaryByCheckingIn(CFErrorRef* error) { |
+ return GTMSMJobCheckIn(error); |
+} |
+ |
+bool Launchd::RemoveJob(CFStringRef label, CFErrorRef* error) { |
+ return GTMSMJobRemove(label, error); |
+} |
+ |
+bool Launchd::RestartJob(Domain domain, |
+ Type type, |
+ CFStringRef name, |
+ CFStringRef cf_session_type) { |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ NSURL* url = GetPlistURL(domain, type, name); |
+ NSString* ns_path = [url path]; |
+ ns_path = SanitizeShellArgument(ns_path); |
+ const char* file_path = [ns_path fileSystemRepresentation]; |
+ |
+ NSString* ns_session_type = |
+ SanitizeShellArgument(base::mac::CFToNSCast(cf_session_type)); |
+ if (!file_path || !ns_session_type) { |
+ return false; |
+ } |
+ |
+ std::vector<std::string> argv; |
+ argv.push_back("/bin/bash"); |
+ argv.push_back("--noprofile"); |
+ argv.push_back("-c"); |
+ std::string command = base::StringPrintf( |
+ "/bin/launchctl unload -S %s %s;" |
+ "/bin/launchctl load -S %s %s;", |
+ [ns_session_type UTF8String], file_path, |
+ [ns_session_type UTF8String], file_path); |
+ argv.push_back(command); |
+ base::ProcessHandle handle; |
+ return base::LaunchAppInNewProcessGroup(argv, |
+ base::environment_vector(), |
+ base::file_handle_mapping_vector(), |
+ NO, |
+ &handle); |
+} |
+ |
+CFMutableDictionaryRef Launchd::CreatePlistFromFile(Domain domain, |
+ Type type, |
+ CFStringRef name) { |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ NSURL* ns_url = GetPlistURL(domain, type, name); |
+ NSMutableDictionary* plist = |
+ [[NSMutableDictionary alloc] initWithContentsOfURL:ns_url]; |
+ return base::mac::NSToCFCast(plist); |
+} |
+ |
+bool Launchd::WritePlistToFile(Domain domain, |
+ Type type, |
+ CFStringRef name, |
+ CFDictionaryRef dict) { |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ NSURL* ns_url = GetPlistURL(domain, type, name); |
+ return [base::mac::CFToNSCast(dict) writeToURL:ns_url atomically:YES]; |
+} |
+ |
+bool Launchd::DeletePlist(Domain domain, Type type, CFStringRef name) { |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ NSURL* ns_url = GetPlistURL(domain, type, name); |
+ NSError* err = nil; |
+ if (![[NSFileManager defaultManager] removeItemAtPath:[ns_url path] |
+ error:&err]) { |
+ if ([err code] != NSFileNoSuchFileError) { |
+ LOG(ERROR) << "DeletePlist: " << base::mac::NSToCFCast(err); |
+ } |
+ return false; |
+ } |
+ return true; |
+} |