| 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..c67ff23abd6662b24302f4f49706fa4aa879c03b
|
| --- /dev/null
|
| +++ b/chrome/common/launchd_mac.mm
|
| @@ -0,0 +1,171 @@
|
| +// 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),
|
| + NSUserDomainMask_value_changed);
|
| +COMPILE_ASSERT(static_cast<int>(Launchd::Local) ==
|
| + static_cast<int>(NSLocalDomainMask),
|
| + NSLocalDomainMask_value_changed);
|
| +COMPILE_ASSERT(static_cast<int>(Launchd::Network) ==
|
| + static_cast<int>(NSNetworkDomainMask),
|
| + NSNetworkDomainMask_value_changed);
|
| +COMPILE_ASSERT(static_cast<int>(Launchd::System) ==
|
| + static_cast<int>(NSSystemDomainMask),
|
| + NSSystemDomainMask_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;
|
| +}
|
|
|