Chromium Code Reviews| 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..ce3a319ee3416523060549362c831d9d9646123f |
| --- /dev/null |
| +++ b/chrome/common/launchd_mac.mm |
| @@ -0,0 +1,189 @@ |
| +// 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 { |
| + |
| +std::string FileSystemPathFromCFURL(CFURLRef url) { |
| + base::mac::ScopedCFTypeRef<CFStringRef> path( |
| + CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle)); |
|
Mark Mentovai
2011/03/21 16:50:49
Might path be NULL? If url is bad in some way, lik
dmac
2011/03/21 22:59:19
Obsolete.
|
| + |
| + // TODO(dmaclach): Turn this into a more general utility |
|
Mark Mentovai
2011/03/21 16:50:49
This comment applies to the entire function, right
dmac
2011/03/21 22:59:19
Obsolete.
|
| + // http://crbug.com/76928 |
| + CFIndex max = CFStringGetMaximumSizeOfFileSystemRepresentation(path); |
|
Mark Mentovai
2011/03/21 16:50:49
I’d just use -[NSString fileSystemRepresentation]
dmac
2011/03/21 22:59:19
Obsolete.
|
| + std::vector<char> buffer(max); |
| + CHECK(CFStringGetFileSystemRepresentation(path, &buffer[0], max)); |
| + return std::string(&buffer[0]); |
| +} |
| + |
| +CFURLRef CopyPListURL(Launchd::Domain domain, |
|
Mark Mentovai
2011/03/21 16:50:49
CopyPlistURL, lowercase L, as you’ve done elsewher
dmac
2011/03/21 22:59:19
Done.
|
| + Launchd::Type type, |
| + CFStringRef name) { |
| + base::mac::ScopedNSAutoreleasePool pool; |
| + NSArray* library_paths = NSSearchPathForDirectoriesInDomains( |
| + NSLibraryDirectory, |
| + domain, |
|
Mark Mentovai
2011/03/21 16:50:49
Come up with a classier way to break these lines u
dmac
2011/03/21 22:59:19
Done.
|
| + true); |
| + 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]; |
|
Mark Mentovai
2011/03/21 16:50:49
4-space the continuation line.
dmac
2011/03/21 22:59:19
Done.
|
| + |
| + NSError* err; |
| + if (![[NSFileManager defaultManager] createDirectoryAtPath:launch_dir |
| + withIntermediateDirectories:YES |
| + attributes:nil |
| + error:&err]) { |
| + LOG(ERROR) << "CopyPListURL " << base::mac::NSToCFCast(err); |
| + return NULL; |
| + } |
| + |
| + NSString* plist_file_path |
|
Mark Mentovai
2011/03/21 16:50:49
= goes on this line, not the next.
dmac
2011/03/21 22:59:19
I hate that. Done.
|
| + = [launch_dir stringByAppendingPathComponent:base::mac::CFToNSCast(name)]; |
| + plist_file_path = [plist_file_path stringByAppendingPathExtension:@"plist"]; |
| + NSURL *url = [[NSURL alloc] initFileURLWithPath:plist_file_path |
|
Mark Mentovai
2011/03/21 16:50:49
You’ve been putting the *s on the type and not the
dmac
2011/03/21 22:59:19
Done.
|
| + isDirectory:NO]; |
| + return base::mac::NSToCFCast(url); |
| +} |
| + |
| +} |
|
Mark Mentovai
2011/03/21 16:50:49
} // namespace
dmac
2011/03/21 22:59:19
Done.
|
| + |
| +Launchd* Launchd::g_instance_ = NULL; |
| +bool Launchd::g_set_to_singleton_ = false; |
|
Mark Mentovai
2011/03/21 16:50:49
I don’t see why you need this.
dmac
2011/03/21 22:59:19
Done.
|
| + |
| +Launchd* Launchd::GetInstance() { |
| + if (!g_instance_) { |
| + g_instance_ = Singleton<Launchd>::get(); |
| + g_set_to_singleton_ = true; |
| + } |
| + return g_instance_; |
| +} |
| + |
| +void Launchd::SetInstance(Launchd* instance) { |
| + CHECK(!g_set_to_singleton_); |
| + g_instance_ = instance; |
| +} |
| + |
| +Launchd::~Launchd() { } |
| + |
| +CFDictionaryRef Launchd::CopyLaunchdExports() { |
| + return GTMCopyLaunchdExports(); |
|
Mark Mentovai
2011/03/21 16:50:49
I haven’t read this code or its API documentation,
dmac
2011/03/21 22:59:19
OK.. it's been working for a while now.
|
| +} |
| + |
| +CFDictionaryRef Launchd::CopyLaunchdJobDictionary(CFStringRef label) { |
| + return GTMSMJobCopyDictionary(label); |
| +} |
| + |
| +CFDictionaryRef Launchd::CopyLaunchdDictionaryByCheckingIn(CFErrorRef* error) { |
| + return GTMSMJobCheckIn(error); |
| +} |
| + |
| +bool Launchd::RemoveLaunchdJob(CFStringRef label, CFErrorRef* error) { |
| + return GTMSMJobRemove(label, error); |
| +} |
| + |
| +bool Launchd::ShutdownLaunchdJob(Domain domain, |
| + Type type, |
| + CFStringRef name, |
| + CFStringRef cf_session_type) { |
| + base::mac::ScopedCFTypeRef<CFURLRef> cf_url(CopyPListURL(domain, type, name)); |
| + std::string path(FileSystemPathFromCFURL(cf_url)); |
|
Mark Mentovai
2011/03/21 16:50:49
Isn’t it kind of obnoxious to use CopyPlistURL, wh
dmac
2011/03/21 22:59:19
Done. It made sense in the earlier CL because some
|
| + std::string session_type(base::SysCFStringRefToUTF8(cf_session_type)); |
| + std::vector<std::string> argv; |
| + argv.push_back("/bin/launchctl"); |
| + argv.push_back("unload"); |
| + argv.push_back("-S"); |
| + argv.push_back(session_type); |
| + argv.push_back(path); |
| + base::ProcessHandle handle; |
| + return base::LaunchAppInNewProcessGroup(argv, |
| + base::environment_vector(), |
| + base::file_handle_mapping_vector(), |
| + NO, |
| + &handle); |
| +} |
| + |
| +bool Launchd::RestartLaunchdJob(Domain domain, |
| + Type type, |
| + CFStringRef name, |
| + CFStringRef cf_session_type) { |
| + base::mac::ScopedCFTypeRef<CFURLRef> cf_url(CopyPListURL(domain, type, name)); |
| + std::string path(FileSystemPathFromCFURL(cf_url)); |
| + std::string session_type(base::SysCFStringRefToUTF8(cf_session_type)); |
| + 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\";", |
| + session_type.c_str(), path.c_str(), |
|
Mark Mentovai
2011/03/21 16:50:49
Didn’t I mention doing proper sanitization and esc
|
| + session_type.c_str(), path.c_str()); |
| + argv.push_back(command); |
| + base::ProcessHandle handle; |
| + return base::LaunchAppInNewProcessGroup(argv, |
| + base::environment_vector(), |
| + base::file_handle_mapping_vector(), |
| + NO, |
| + &handle); |
| +} |
| + |
| +CFMutableDictionaryRef Launchd::ReadLaunchdPlist(Domain domain, |
| + Type type, |
| + CFStringRef name) { |
| + base::mac::ScopedNSAutoreleasePool pool; |
| + base::mac::ScopedCFTypeRef<CFURLRef> cf_url(CopyPListURL(domain, type, name)); |
| + NSURL* ns_url = base::mac::CFToNSCast(cf_url); |
| + NSMutableDictionary* plist |
|
Mark Mentovai
2011/03/21 16:50:49
= goes on this line.
|
| + = [[NSMutableDictionary alloc] initWithContentsOfURL:ns_url]; |
|
Mark Mentovai
2011/03/21 16:50:49
Continuation line uses a 4-space indent.
Mark Mentovai
2011/03/21 16:50:49
OK, I see, the caller owns the returned dictionary
|
| + return base::mac::NSToCFCast(plist); |
| +} |
| + |
| +bool Launchd::WriteLaunchdPlist(Domain domain, |
| + Type type, |
| + CFStringRef name, |
| + CFDictionaryRef dict) { |
| + base::mac::ScopedNSAutoreleasePool pool; |
| + base::mac::ScopedCFTypeRef<CFURLRef> cf_url(CopyPListURL(domain, type, name)); |
| + base::mac::ScopedCFTypeRef<CFDataRef> cf_data( |
| + CFPropertyListCreateXMLData(kCFAllocatorDefault, |
| + dict)); |
|
Mark Mentovai
2011/03/21 16:50:49
dict fits on the previous line for sure.
|
| + Boolean good = false; |
|
Mark Mentovai
2011/03/21 16:50:49
Just bool, not Boolean.
|
| + if (cf_url.get() && cf_data.get()) { |
| + SInt32 error = 0; |
| + good = CFURLWriteDataAndPropertiesToResource(cf_url, cf_data, NULL, &error); |
| + if (!good) { |
| + LOG(ERROR) << "WriteLaunchdPlist " << error; |
| + } |
| + } |
| + return good; |
| +} |
| + |
| +bool Launchd::DeleteLaunchDPlist(Domain domain, Type type, CFStringRef name) { |
| + base::mac::ScopedCFTypeRef<CFURLRef> url(CopyPListURL(domain, type, name)); |
| + if (!url) { |
| + return false; |
| + } |
| + SInt32 error = 0; |
| + if (!CFURLDestroyResource(url, &error)) { |
| + LOG(ERROR) << "DeleteLaunchDPlist: " << error; |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
|
Mark Mentovai
2011/03/21 16:50:49
Dump the blank line at EOF.
|