Revert 248827 "android: Migrate old content readback to use asyn..."
[chromium-blink-merge.git] / chrome / common / mac / launchd.mm
blob848a2c7d8569798f4c03dfa344afae35f4495dfa
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/mac/launchd.h"
7 #import <Foundation/Foundation.h>
8 #include <launch.h>
10 #include "base/mac/mac_util.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/mac/scoped_nsautorelease_pool.h"
13 #include "base/process/launch.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "third_party/google_toolbox_for_mac/src/Foundation/GTMServiceManagement.h"
18 namespace {
20 NSString* SanitizeShellArgument(NSString* arg) {
21   if (!arg) {
22     return nil;
23   }
24   NSString *sanitize = [arg stringByReplacingOccurrencesOfString:@"'"
25                                                       withString:@"'\''"];
26   return [NSString stringWithFormat:@"'%@'", sanitize];
29 NSURL* GetPlistURL(Launchd::Domain domain,
30                    Launchd::Type type,
31                    CFStringRef name) {
32   NSArray* library_paths =
33       NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, domain, YES);
34   DCHECK_EQ([library_paths count], 1U);
35   NSString* library_path = [library_paths objectAtIndex:0];
37   NSString *launch_dir_name = (type == Launchd::Daemon) ? @"LaunchDaemons"
38                                                         : @"LaunchAgents";
39   NSString* launch_dir =
40       [library_path stringByAppendingPathComponent:launch_dir_name];
42   NSError* err;
43   if (![[NSFileManager defaultManager] createDirectoryAtPath:launch_dir
44                                  withIntermediateDirectories:YES
45                                                   attributes:nil
46                                                        error:&err]) {
47     DLOG(ERROR) << "GetPlistURL " << base::mac::NSToCFCast(err);
48     return nil;
49   }
51   NSString* plist_file_path =
52       [launch_dir stringByAppendingPathComponent:base::mac::CFToNSCast(name)];
53   plist_file_path = [plist_file_path stringByAppendingPathExtension:@"plist"];
54   return [NSURL fileURLWithPath:plist_file_path isDirectory:NO];
57 }  // namespace
59 COMPILE_ASSERT(static_cast<int>(Launchd::User) ==
60                static_cast<int>(NSUserDomainMask),
61                NSUserDomainMask_value_changed);
62 COMPILE_ASSERT(static_cast<int>(Launchd::Local) ==
63                static_cast<int>(NSLocalDomainMask),
64                NSLocalDomainMask_value_changed);
65 COMPILE_ASSERT(static_cast<int>(Launchd::Network) ==
66                static_cast<int>(NSNetworkDomainMask),
67                NSNetworkDomainMask_value_changed);
68 COMPILE_ASSERT(static_cast<int>(Launchd::System) ==
69                static_cast<int>(NSSystemDomainMask),
70                NSSystemDomainMask_value_changed);
72 Launchd* Launchd::g_instance_ = NULL;
74 Launchd* Launchd::GetInstance() {
75   if (!g_instance_) {
76     g_instance_ = Singleton<Launchd>::get();
77   }
78   return g_instance_;
81 void Launchd::SetInstance(Launchd* instance) {
82   if (instance) {
83     CHECK(!g_instance_);
84   }
85   g_instance_ = instance;
88 Launchd::~Launchd() { }
90 CFDictionaryRef Launchd::CopyExports() {
91   return GTMCopyLaunchdExports();
94 CFDictionaryRef Launchd::CopyJobDictionary(CFStringRef label) {
95   return GTMSMJobCopyDictionary(label);
98 CFDictionaryRef Launchd::CopyDictionaryByCheckingIn(CFErrorRef* error) {
99   return GTMSMCopyJobCheckInDictionary(error);
102 bool Launchd::RemoveJob(CFStringRef label, CFErrorRef* error) {
103   return GTMSMJobRemove(label, error);
106 bool Launchd::RestartJob(Domain domain,
107                          Type type,
108                          CFStringRef name,
109                          CFStringRef cf_session_type) {
110   base::mac::ScopedNSAutoreleasePool pool;
111   NSURL* url = GetPlistURL(domain, type, name);
112   NSString* ns_path = [url path];
113   ns_path = SanitizeShellArgument(ns_path);
114   const char* file_path = [ns_path fileSystemRepresentation];
116   NSString* ns_session_type =
117       SanitizeShellArgument(base::mac::CFToNSCast(cf_session_type));
118   if (!file_path || !ns_session_type) {
119     return false;
120   }
122   std::vector<std::string> argv;
123   argv.push_back("/bin/bash");
124   argv.push_back("--noprofile");
125   argv.push_back("-c");
126   std::string command = base::StringPrintf(
127       "/bin/launchctl unload -S %s %s;"
128       "/bin/launchctl load -S %s %s;",
129       [ns_session_type UTF8String], file_path,
130       [ns_session_type UTF8String], file_path);
131   argv.push_back(command);
133   base::LaunchOptions options;
134   options.new_process_group = true;
135   return base::LaunchProcess(argv, options, NULL);
138 CFMutableDictionaryRef Launchd::CreatePlistFromFile(Domain domain,
139                                                     Type type,
140                                                     CFStringRef name) {
141   base::mac::ScopedNSAutoreleasePool pool;
142   NSURL* ns_url = GetPlistURL(domain, type, name);
143   NSMutableDictionary* plist =
144       [[NSMutableDictionary alloc] initWithContentsOfURL:ns_url];
145   return base::mac::NSToCFCast(plist);
148 bool Launchd::WritePlistToFile(Domain domain,
149                                Type type,
150                                CFStringRef name,
151                                CFDictionaryRef dict) {
152   base::mac::ScopedNSAutoreleasePool pool;
153   NSURL* ns_url = GetPlistURL(domain, type, name);
154   return [base::mac::CFToNSCast(dict) writeToURL:ns_url atomically:YES];
157 bool Launchd::DeletePlist(Domain domain, Type type, CFStringRef name) {
158   base::mac::ScopedNSAutoreleasePool pool;
159   NSURL* ns_url = GetPlistURL(domain, type, name);
160   NSError* err = nil;
161   if (![[NSFileManager defaultManager] removeItemAtPath:[ns_url path]
162                                                   error:&err]) {
163     if ([err code] != NSFileNoSuchFileError) {
164       DLOG(ERROR) << "DeletePlist: " << base::mac::NSToCFCast(err);
165     }
166     return false;
167   }
168   return true;