Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(837)

Side by Side Diff: chrome/common/service_process_util_mac.mm

Issue 982883003: Use fixed socket name instead of SecureSocketWithKey (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mon Mar 16 00:37:12 PDT 2015 Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/common/service_process_util.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/mac/bundle_locations.h" 15 #include "base/mac/bundle_locations.h"
16 #include "base/mac/foundation_util.h" 16 #include "base/mac/foundation_util.h"
17 #include "base/mac/mac_util.h" 17 #include "base/mac/mac_util.h"
18 #include "base/mac/scoped_nsautorelease_pool.h" 18 #include "base/mac/scoped_nsautorelease_pool.h"
19 #include "base/mac/scoped_nsobject.h" 19 #include "base/mac/scoped_nsobject.h"
20 #include "base/metrics/histogram_macros.h"
20 #include "base/path_service.h" 21 #include "base/path_service.h"
21 #include "base/strings/string_util.h" 22 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 23 #include "base/strings/stringprintf.h"
23 #include "base/strings/sys_string_conversions.h" 24 #include "base/strings/sys_string_conversions.h"
24 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
25 #include "base/version.h" 26 #include "base/version.h"
26 #include "chrome/common/chrome_paths.h" 27 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h" 28 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h" 29 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/common/mac/launchd.h" 30 #include "chrome/common/mac/launchd.h"
31 #include "ipc/unix_domain_socket_util.h"
30 32
31 using ::base::FilePathWatcher; 33 using ::base::FilePathWatcher;
32 34
33 namespace { 35 namespace {
34 36
35 #define kServiceProcessSessionType "Aqua" 37 #define kServiceProcessSessionType "Aqua"
36 38
37 CFStringRef CopyServiceProcessLaunchDName() { 39 CFStringRef CopyServiceProcessLaunchDName() {
38 base::mac::ScopedNSAutoreleasePool pool; 40 base::mac::ScopedNSAutoreleasePool pool;
39 NSBundle* bundle = base::mac::FrameworkBundle(); 41 NSBundle* bundle = base::mac::FrameworkBundle();
40 return CFStringCreateCopy(kCFAllocatorDefault, 42 return CFStringCreateCopy(kCFAllocatorDefault,
41 base::mac::NSToCFCast([bundle bundleIdentifier])); 43 base::mac::NSToCFCast([bundle bundleIdentifier]));
42 } 44 }
43 45
44 NSString* GetServiceProcessLaunchDLabel() { 46 NSString* GetServiceProcessLaunchDLabel() {
45 base::scoped_nsobject<NSString> name( 47 base::scoped_nsobject<NSString> name(
46 base::mac::CFToNSCast(CopyServiceProcessLaunchDName())); 48 base::mac::CFToNSCast(CopyServiceProcessLaunchDName()));
47 NSString *label = [name stringByAppendingString:@".service_process"]; 49 NSString* label = [name stringByAppendingString:@".service_process"];
48 base::FilePath user_data_dir; 50 base::FilePath user_data_dir;
49 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 51 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
50 std::string user_data_dir_path = user_data_dir.value(); 52 std::string user_data_dir_path = user_data_dir.value();
51 NSString *ns_path = base::SysUTF8ToNSString(user_data_dir_path); 53 NSString* ns_path = base::SysUTF8ToNSString(user_data_dir_path);
52 ns_path = [ns_path stringByReplacingOccurrencesOfString:@" " 54 ns_path = [ns_path stringByReplacingOccurrencesOfString:@" "
53 withString:@"_"]; 55 withString:@"_"];
54 label = [label stringByAppendingString:ns_path]; 56 label = [label stringByAppendingString:ns_path];
55 return label; 57 return label;
56 } 58 }
57 59
58 NSString* GetServiceProcessLaunchDSocketKey() { 60 NSString* GetServiceProcessLaunchDSocketKey() {
59 return @"ServiceProcessSocket"; 61 return @"ServiceProcessSocket";
60 } 62 }
61 63
(...skipping 15 matching lines...) Expand all
77 ExecFilePathWatcherCallback() {} 79 ExecFilePathWatcherCallback() {}
78 ~ExecFilePathWatcherCallback() {} 80 ~ExecFilePathWatcherCallback() {}
79 81
80 bool Init(const base::FilePath& path); 82 bool Init(const base::FilePath& path);
81 void NotifyPathChanged(const base::FilePath& path, bool error); 83 void NotifyPathChanged(const base::FilePath& path, bool error);
82 84
83 private: 85 private:
84 FSRef executable_fsref_; 86 FSRef executable_fsref_;
85 }; 87 };
86 88
89 base::FilePath GetServiceProcessSocketName() {
90 base::FilePath socket_name;
91 PathService::Get(base::DIR_TEMP, &socket_name);
92 std::string pipe_name = GetServiceProcessScopedName("srv");
93 socket_name = socket_name.Append(pipe_name);
94 UMA_HISTOGRAM_CUSTOM_COUNTS("CloudPrint.ServiceProcessSocketLength",
95 socket_name.value().size(), 75, 124, 50);
96 if (socket_name.value().size() < IPC::kMaxSocketNameLength)
97 return socket_name;
98 // Fallback to /tmp if $TMPDIR is too long.
99 // TODO(vitalybuka): Investigate how often we get there.
100 // See http://crbug.com/466644
101 return base::FilePath("/tmp").Append(pipe_name);
102 }
103
87 } // namespace 104 } // namespace
88 105
89 NSString* GetServiceProcessLaunchDSocketEnvVar() {
90 NSString *label = GetServiceProcessLaunchDLabel();
91 NSString *env_var = [label stringByReplacingOccurrencesOfString:@"."
92 withString:@"_"];
93 env_var = [env_var stringByAppendingString:@"_SOCKET"];
94 env_var = [env_var uppercaseString];
95 return env_var;
96 }
97
98 // Gets the name of the service process IPC channel.
99 IPC::ChannelHandle GetServiceProcessChannel() { 106 IPC::ChannelHandle GetServiceProcessChannel() {
100 base::mac::ScopedNSAutoreleasePool pool; 107 base::FilePath socket_name = GetServiceProcessSocketName();
101 std::string socket_path; 108 VLOG(1) << "ServiceProcessChannel: " << socket_name.value();
102 base::scoped_nsobject<NSDictionary> dictionary( 109 return IPC::ChannelHandle(socket_name.value());
103 base::mac::CFToNSCast(Launchd::GetInstance()->CopyExports()));
104 NSString *ns_socket_path =
105 [dictionary objectForKey:GetServiceProcessLaunchDSocketEnvVar()];
106 if (ns_socket_path) {
107 socket_path = base::SysNSStringToUTF8(ns_socket_path);
108 }
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 DLOG(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 base::scoped_nsobject<NSDictionary> launchd_conf( 129 base::scoped_nsobject<NSDictionary> launchd_conf(
130 base::mac::CFToNSCast(Launchd::GetInstance()->CopyJobDictionary(label))); 130 base::mac::CFToNSCast(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 DLOG(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.
(...skipping 23 matching lines...) Expand all
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 DCHECK(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 DCHECK_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
(...skipping 24 matching lines...) Expand all
224 if (!ready) { 224 if (!ready) {
225 ForceServiceProcessShutdown(version, pid); 225 ForceServiceProcessShutdown(version, pid);
226 } 226 }
227 return ready; 227 return ready;
228 } 228 }
229 229
230 CFDictionaryRef CreateServiceProcessLaunchdPlist(base::CommandLine* cmd_line, 230 CFDictionaryRef CreateServiceProcessLaunchdPlist(base::CommandLine* cmd_line,
231 bool for_auto_launch) { 231 bool for_auto_launch) {
232 base::mac::ScopedNSAutoreleasePool pool; 232 base::mac::ScopedNSAutoreleasePool pool;
233 233
234 NSString *program = 234 NSString* program =
235 base::SysUTF8ToNSString(cmd_line->GetProgram().value()); 235 base::SysUTF8ToNSString(cmd_line->GetProgram().value());
236 236
237 std::vector<std::string> args = cmd_line->argv(); 237 std::vector<std::string> args = cmd_line->argv();
238 NSMutableArray *ns_args = [NSMutableArray arrayWithCapacity:args.size()]; 238 NSMutableArray* ns_args = [NSMutableArray arrayWithCapacity:args.size()];
239 239
240 for (std::vector<std::string>::iterator iter = args.begin(); 240 for (std::vector<std::string>::iterator iter = args.begin();
241 iter < args.end(); 241 iter < args.end();
242 ++iter) { 242 ++iter) {
243 [ns_args addObject:base::SysUTF8ToNSString(*iter)]; 243 [ns_args addObject:base::SysUTF8ToNSString(*iter)];
244 } 244 }
245 245
246 NSDictionary *socket = 246 NSString* socket_name =
247 [NSDictionary dictionaryWithObject:GetServiceProcessLaunchDSocketEnvVar() 247 base::SysUTF8ToNSString(GetServiceProcessSocketName().value());
248 forKey:@ LAUNCH_JOBSOCKETKEY_SECUREWITHKEY]; 248
249 NSDictionary *sockets = 249 NSDictionary* socket =
250 [NSDictionary dictionaryWithObject:socket_name
251 forKey:@LAUNCH_JOBSOCKETKEY_PATHNAME];
252 NSDictionary* sockets =
250 [NSDictionary dictionaryWithObject:socket 253 [NSDictionary dictionaryWithObject:socket
251 forKey:GetServiceProcessLaunchDSocketKey()]; 254 forKey:GetServiceProcessLaunchDSocketKey()];
252 255
253 // See the man page for launchd.plist. 256 // See the man page for launchd.plist.
254 NSMutableDictionary *launchd_plist = 257 NSMutableDictionary* launchd_plist =
255 [[NSMutableDictionary alloc] initWithObjectsAndKeys: 258 [[NSMutableDictionary alloc] initWithObjectsAndKeys:
256 GetServiceProcessLaunchDLabel(), @ LAUNCH_JOBKEY_LABEL, 259 GetServiceProcessLaunchDLabel(), @LAUNCH_JOBKEY_LABEL,
257 program, @ LAUNCH_JOBKEY_PROGRAM, 260 program, @LAUNCH_JOBKEY_PROGRAM,
258 ns_args, @ LAUNCH_JOBKEY_PROGRAMARGUMENTS, 261 ns_args, @LAUNCH_JOBKEY_PROGRAMARGUMENTS,
259 sockets, @ LAUNCH_JOBKEY_SOCKETS, 262 sockets, @LAUNCH_JOBKEY_SOCKETS,
260 nil]; 263 nil];
261 264
262 if (for_auto_launch) { 265 if (for_auto_launch) {
263 // We want the service process to be able to exit if there are no services 266 // We want the service process to be able to exit if there are no services
264 // enabled. With a value of NO in the SuccessfulExit key, launchd will 267 // enabled. With a value of NO in the SuccessfulExit key, launchd will
265 // relaunch the service automatically in any other case than exiting 268 // relaunch the service automatically in any other case than exiting
266 // cleanly with a 0 return code. 269 // cleanly with a 0 return code.
267 NSDictionary *keep_alive = 270 NSDictionary* keep_alive =
268 [NSDictionary 271 [NSDictionary
269 dictionaryWithObject:[NSNumber numberWithBool:NO] 272 dictionaryWithObject:[NSNumber numberWithBool:NO]
270 forKey:@ LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT]; 273 forKey:@LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT];
271 NSDictionary *auto_launchd_plist = 274 NSDictionary* auto_launchd_plist =
272 [[NSDictionary alloc] initWithObjectsAndKeys: 275 [[NSDictionary alloc] initWithObjectsAndKeys:
273 [NSNumber numberWithBool:YES], @ LAUNCH_JOBKEY_RUNATLOAD, 276 [NSNumber numberWithBool:YES], @LAUNCH_JOBKEY_RUNATLOAD,
274 keep_alive, @ LAUNCH_JOBKEY_KEEPALIVE, 277 keep_alive, @LAUNCH_JOBKEY_KEEPALIVE,
275 @ kServiceProcessSessionType, @ LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE, 278 @kServiceProcessSessionType, @LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE,
276 nil]; 279 nil];
277 [launchd_plist addEntriesFromDictionary:auto_launchd_plist]; 280 [launchd_plist addEntriesFromDictionary:auto_launchd_plist];
278 } 281 }
279 return reinterpret_cast<CFDictionaryRef>(launchd_plist); 282 return reinterpret_cast<CFDictionaryRef>(launchd_plist);
280 } 283 }
281 284
282 // Writes the launchd property list into the user's LaunchAgents directory, 285 // Writes the launchd property list into the user's LaunchAgents directory,
283 // creating that directory if needed. This will cause the service process to be 286 // creating that directory if needed. This will cause the service process to be
284 // auto launched on the next user login. 287 // auto launched on the next user login.
285 bool ServiceProcessState::AddToAutoRun() { 288 bool ServiceProcessState::AddToAutoRun() {
286 // We're creating directories and writing a file. 289 // We're creating directories and writing a file.
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 CFErrorRef err = NULL; 437 CFErrorRef err = NULL;
435 if (!Launchd::GetInstance()->RemoveJob(label, &err)) { 438 if (!Launchd::GetInstance()->RemoveJob(label, &err)) {
436 base::ScopedCFTypeRef<CFErrorRef> scoped_err(err); 439 base::ScopedCFTypeRef<CFErrorRef> scoped_err(err);
437 DLOG(ERROR) << "RemoveJob " << err; 440 DLOG(ERROR) << "RemoveJob " << err;
438 // Exiting with zero, so launchd doesn't restart the process. 441 // Exiting with zero, so launchd doesn't restart the process.
439 exit(0); 442 exit(0);
440 } 443 }
441 } 444 }
442 } 445 }
443 } 446 }
OLDNEW
« no previous file with comments | « chrome/common/service_process_util.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698