OLD | NEW |
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 #import "chrome/browser/mac/dock.h" | 5 #import "chrome/browser/mac/dock.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 #include <CoreFoundation/CoreFoundation.h> | 9 #include <CoreFoundation/CoreFoundation.h> |
10 #include <signal.h> | 10 #include <signal.h> |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 return nil; | 113 return nil; |
114 } | 114 } |
115 | 115 |
116 NSString* path = [url path]; | 116 NSString* path = [url path]; |
117 [app_paths addObject:path]; | 117 [app_paths addObject:path]; |
118 } | 118 } |
119 | 119 |
120 return app_paths; | 120 return app_paths; |
121 } | 121 } |
122 | 122 |
123 // Returns the process ID for a process whose bundle identifier is bundle_id. | |
124 // The process is looked up using the Process Manager. Returns -1 on error, | |
125 // including when no process matches the bundle identifier. | |
126 pid_t PIDForProcessBundleID(const std::string& bundle_id) { | |
127 // This technique is racy: what happens if |psn| becomes invalid before a | |
128 // subsequent call to GetNextProcess, or if the Process Manager's internal | |
129 // order of processes changes? Tolerate the race by allowing failure. Since | |
130 // this function is only used on Leopard to find the Dock process so that it | |
131 // can be restarted, the worst that can happen here is that the Dock won't | |
132 // be restarted. | |
133 ProcessSerialNumber psn = {0, kNoProcess}; | |
134 OSStatus status; | |
135 while ((status = GetNextProcess(&psn)) == noErr) { | |
136 pid_t process_pid; | |
137 if ((status = GetProcessPID(&psn, &process_pid)) != noErr) { | |
138 OSSTATUS_LOG(ERROR, status) << "GetProcessPID"; | |
139 continue; | |
140 } | |
141 | |
142 base::mac::ScopedCFTypeRef<CFDictionaryRef> process_dictionary( | |
143 ProcessInformationCopyDictionary(&psn, | |
144 kProcessDictionaryIncludeAllInformationMask)); | |
145 if (!process_dictionary.get()) { | |
146 LOG(ERROR) << "ProcessInformationCopyDictionary"; | |
147 continue; | |
148 } | |
149 | |
150 CFStringRef process_bundle_id_cf = base::mac::CFCast<CFStringRef>( | |
151 CFDictionaryGetValue(process_dictionary, kCFBundleIdentifierKey)); | |
152 if (!process_bundle_id_cf) { | |
153 // Not all processes have a bundle ID. | |
154 continue; | |
155 } | |
156 | |
157 std::string process_bundle_id = | |
158 base::SysCFStringRefToUTF8(process_bundle_id_cf); | |
159 if (process_bundle_id == bundle_id) { | |
160 // Found it! | |
161 return process_pid; | |
162 } | |
163 } | |
164 | |
165 // status will be procNotFound (-600) if the process wasn't found. | |
166 OSSTATUS_LOG(ERROR, status) << "GetNextProcess"; | |
167 | |
168 return -1; | |
169 } | |
170 | |
171 // Restart the Dock process by sending it a SIGHUP. | 123 // Restart the Dock process by sending it a SIGHUP. |
172 void Restart() { | 124 void Restart() { |
173 pid_t pid; | 125 // Doing this via launchd using the proper job label is the safest way to |
174 | 126 // handle the restart. Unlike "killall Dock", looking this up via launchd |
175 if (base::mac::IsOSSnowLeopardOrLater()) { | 127 // guarantees that only the right process will be targeted. |
176 // Doing this via launchd using the proper job label is the safest way to | 128 pid_t pid = base::mac::PIDForJob("com.apple.Dock.agent"); |
177 // handle the restart. Unlike "killall Dock", looking this up via launchd | |
178 // guarantees that only the right process will be targeted. | |
179 pid = base::mac::PIDForJob("com.apple.Dock.agent"); | |
180 } else { | |
181 // On Leopard, the Dock doesn't have a known fixed job label name as it | |
182 // does on Snow Leopard and Lion because it's not launched as a launch | |
183 // agent. Look the PID up by finding a process with the expected bundle | |
184 // identifier using the Process Manager. | |
185 pid = PIDForProcessBundleID("com.apple.dock"); | |
186 } | |
187 | |
188 if (pid <= 0) { | 129 if (pid <= 0) { |
189 return; | 130 return; |
190 } | 131 } |
191 | 132 |
192 // Sending a SIGHUP to the Dock seems to be a more reliable way to get the | 133 // Sending a SIGHUP to the Dock seems to be a more reliable way to get the |
193 // replacement Dock process to read the newly written plist than using the | 134 // replacement Dock process to read the newly written plist than using the |
194 // equivalent of "launchctl stop" (even if followed by "launchctl start.") | 135 // equivalent of "launchctl stop" (even if followed by "launchctl start.") |
195 // Note that this is a potential race in that pid may no longer be valid or | 136 // Note that this is a potential race in that pid may no longer be valid or |
196 // may even have been reused. | 137 // may even have been reused. |
197 kill(pid, SIGHUP); | 138 kill(pid, SIGHUP); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 } | 326 } |
386 | 327 |
387 // Rewrite the plist. | 328 // Rewrite the plist. |
388 [dock_plist setObject:persistent_apps forKey:kDockPersistentAppsKey]; | 329 [dock_plist setObject:persistent_apps forKey:kDockPersistentAppsKey]; |
389 [user_defaults setPersistentDomain:dock_plist forName:kDockDomain]; | 330 [user_defaults setPersistentDomain:dock_plist forName:kDockDomain]; |
390 | 331 |
391 Restart(); | 332 Restart(); |
392 } | 333 } |
393 | 334 |
394 } // namespace dock | 335 } // namespace dock |
OLD | NEW |