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

Side by Side Diff: remoting/host/installer/mac/uninstaller/remoting_uninstaller.mm

Issue 10807061: [Chromoting] Update uninstaller to facilitate testing automation. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
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 "remoting/host/installer/mac/uninstaller/remoting_uninstaller.h" 5 #include "remoting/host/installer/mac/uninstaller/remoting_uninstaller.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include "base/mac/scoped_authorizationref.h" 9 #include "base/mac/scoped_authorizationref.h"
10 #include "base/mac/scoped_cftyperef.h"
11 #include "remoting/host/constants_mac.h" 10 #include "remoting/host/constants_mac.h"
12 11
13 @implementation RemotingUninstallerAppDelegate 12 @implementation RemotingUninstaller
14
15 NSString* const kLaunchAgentsDir = @"/Library/LaunchAgents";
16 NSString* const kPrefPaneDir = @"/Library/PreferencePanes";
17 NSString* const kHelperToolsDir = @"/Library/PrivilegedHelperTools";
18 NSString* const kApplicationDir = @"/Applications";
19
20 NSString* const kPrefPaneName = @kServiceName ".prefPane";
21 NSString* const kUninstallerName =
22 @"Chrome Remote Desktop Host Uninstaller.app";
23 13
24 // Keystone 14 // Keystone
25 const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/" 15 const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/"
26 "GoogleSoftwareUpdate.bundle/Contents/MacOS/" 16 "GoogleSoftwareUpdate.bundle/Contents/MacOS/"
27 "ksadmin"; 17 "ksadmin";
28 const char kKeystonePID[] = "com.google.chrome_remote_desktop"; 18 const char kKeystonePID[] = "com.google.chrome_remote_desktop";
29 19
30 - (void)dealloc {
31 [super dealloc];
32 }
33
34 - (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
35 }
36
37 - (void)logOutput:(FILE*) pipe { 20 - (void)logOutput:(FILE*) pipe {
38 char readBuffer[128]; 21 char readBuffer[128];
39 for (;;) { 22 for (;;) {
40 long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1); 23 long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1);
41 if (bytesRead < 1) 24 if (bytesRead < 1)
42 break; 25 break;
43 readBuffer[bytesRead] = '\0'; 26 readBuffer[bytesRead] = '\0';
44 NSLog(@"%s", readBuffer); 27 NSLog(@"%s", readBuffer);
45 } 28 }
46 } 29 }
47 30
48 - (void)messageBox:(const char*)message { 31 - (NSArray*)convertToNSArray:(const char**)array {
Lambros 2012/07/23 22:06:47 Is it normal ObjC++ style to add these kinds of pr
garykac 2012/07/23 22:41:09 Not sure about style. I moved it out as a plain fu
49 base::mac::ScopedCFTypeRef<CFStringRef> message_ref( 32 NSMutableArray* ns_array = [[[NSMutableArray alloc] init] autorelease];
50 CFStringCreateWithCString(NULL, message, (int)strlen(message))); 33 int i = 0;
51 CFOptionFlags result; 34 const char* element = array[i++];
52 CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, 35 while (element != NULL) {
53 NULL, NULL, NULL, 36 [ns_array addObject:[NSString stringWithUTF8String:element]];
54 CFSTR("Chrome Remote Desktop Uninstaller"), 37 element = array[i++];
55 message_ref, NULL, NULL, NULL, &result); 38 }
39 return ns_array;
56 } 40 }
57 41
58 -(void)runCommand:(NSString*)cmd 42 - (void)runCommand:(const char*)cmd
59 withArguments:(NSArray*)args { 43 withArguments:(const char**)args {
60 NSTask* task; 44 NSTask* task;
61 NSPipe* output = [NSPipe pipe]; 45 NSPipe* output = [NSPipe pipe];
62 NSString* result; 46 NSString* result;
63 47
64 NSLog(@"Executing: %@ %@", cmd, [args componentsJoinedByString:@" "]); 48 NSArray* arg_array = [self convertToNSArray:args];
49 NSLog(@"Executing: %s %@", cmd, [arg_array componentsJoinedByString:@" "]);
65 50
66 @try { 51 @try {
67 task = [[[NSTask alloc] init] autorelease]; 52 task = [[[NSTask alloc] init] autorelease];
68 [task setLaunchPath:cmd]; 53 [task setLaunchPath:[NSString stringWithUTF8String:cmd]];
69 [task setArguments:args]; 54 [task setArguments:arg_array];
70 [task setStandardInput:[NSPipe pipe]]; 55 [task setStandardInput:[NSPipe pipe]];
71 [task setStandardOutput:output]; 56 [task setStandardOutput:output];
72 [task launch]; 57 [task launch];
73 58
74 NSData* data = [[output fileHandleForReading] readDataToEndOfFile]; 59 NSData* data = [[output fileHandleForReading] readDataToEndOfFile];
75 60
76 [task waitUntilExit]; 61 [task waitUntilExit];
77 62
78 if ([task terminationStatus] != 0) { 63 if ([task terminationStatus] != 0) {
79 // TODO(garykac): When we switch to sdk_10.6, show the 64 // TODO(garykac): When we switch to sdk_10.6, show the
(...skipping 10 matching lines...) Expand all
90 } 75 }
91 @catch (NSException* exception) { 76 @catch (NSException* exception) {
92 NSLog(@"Exception %@ %@", [exception name], [exception reason]); 77 NSLog(@"Exception %@ %@", [exception name], [exception reason]);
93 } 78 }
94 } 79 }
95 80
96 - (void)sudoCommand:(const char*)cmd 81 - (void)sudoCommand:(const char*)cmd
97 withArguments:(const char**)args 82 withArguments:(const char**)args
98 usingAuth:(AuthorizationRef)authRef { 83 usingAuth:(AuthorizationRef)authRef {
99 84
100 NSMutableArray* arg_array = [[[NSMutableArray alloc] init] autorelease]; 85 if (authRef == nil) {
101 int i = 0; 86 // We're running as root, so just run the command directly.
Lambros 2012/07/23 20:42:35 This feels wrong to me - are you absolutely sure y
garykac 2012/07/23 22:41:09 Hmm.. Previous tests made me think this was requir
102 const char* arg = args[i++]; 87 [self runCommand:cmd withArguments:args];
103 while (arg != NULL) { 88 return;
104 [arg_array addObject:[NSString stringWithUTF8String:arg]];
105 arg = args[i++];
106 } 89 }
90
91 NSArray* arg_array = [self convertToNSArray:args];
107 NSLog(@"Executing (as Admin): %s %@", cmd, 92 NSLog(@"Executing (as Admin): %s %@", cmd,
108 [arg_array componentsJoinedByString:@" "]); 93 [arg_array componentsJoinedByString:@" "]);
109 FILE* pipe = NULL; 94 FILE* pipe = NULL;
110 OSStatus status; 95 OSStatus status;
111 status = AuthorizationExecuteWithPrivileges(authRef, cmd, 96 status = AuthorizationExecuteWithPrivileges(authRef, cmd,
112 kAuthorizationFlagDefaults, 97 kAuthorizationFlagDefaults,
113 (char* const*)args, 98 (char* const*)args,
114 &pipe); 99 &pipe);
115 100
116 if (status == errAuthorizationToolExecuteFailure) { 101 if (status == errAuthorizationToolExecuteFailure) {
117 NSLog(@"Error errAuthorizationToolExecuteFailure"); 102 NSLog(@"Error errAuthorizationToolExecuteFailure");
118 } else if (status != errAuthorizationSuccess) { 103 } else if (status != errAuthorizationSuccess) {
119 NSLog(@"Error while executing %s. Status=%lx", cmd, status); 104 NSLog(@"Error while executing %s. Status=%lx", cmd, status);
120 } else { 105 } else {
121 [self logOutput:pipe]; 106 [self logOutput:pipe];
122 } 107 }
123 108
124 if (pipe != NULL) 109 if (pipe != NULL)
125 fclose(pipe); 110 fclose(pipe);
126 } 111 }
127 112
128 - (void)sudoDelete:(const char*)filename 113 - (void)sudoDelete:(const char*)filename
129 usingAuth:(AuthorizationRef)authRef { 114 usingAuth:(AuthorizationRef)authRef {
130 const char* args[] = { "-rf", filename, NULL }; 115 const char* args[] = { "-rf", filename, NULL };
131 [self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef]; 116 [self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef];
132 } 117 }
133 118
134 -(void)shutdownService { 119 - (void)shutdownService {
135 NSString* launchCtl = @"/bin/launchctl"; 120 const char* launchCtl = "/bin/launchctl";
136 NSArray* argsStop = [NSArray arrayWithObjects:@"stop", 121 const char* argsStop[] = { "stop", remoting::kServiceName, NULL };
137 @kServiceName, nil];
138 [self runCommand:launchCtl withArguments:argsStop]; 122 [self runCommand:launchCtl withArguments:argsStop];
139 123
140 NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", 124 if ([[NSFileManager defaultManager] fileExistsAtPath:
141 kLaunchAgentsDir, @kServiceName]; 125 [NSString stringWithUTF8String:remoting::kServicePlistPath]]) {
142 if ([[NSFileManager defaultManager] fileExistsAtPath:plist]) { 126 const char* argsUnload[] = { "unload", "-w", "-S", "Aqua",
143 NSArray* argsUnload = [NSArray arrayWithObjects:@"unload", 127 remoting::kServicePlistPath, NULL };
144 @"-w", @"-S", @"Aqua", plist, nil];
145 [self runCommand:launchCtl withArguments:argsUnload]; 128 [self runCommand:launchCtl withArguments:argsUnload];
146 } 129 }
147 } 130 }
148 131
149 -(void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef { 132 - (void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef {
150 const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL }; 133 const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL };
151 [self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef]; 134 [self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef];
152 } 135 }
153 136
154 -(void)remotingUninstallUsingAuth:(AuthorizationRef)authRef { 137 - (void)remotingUninstallUsingAuth:(AuthorizationRef)authRef {
155 NSString* host_enabled = [NSString stringWithFormat:@"%@/%@.me2me_enabled", 138 // Remove the enabled file before shutting down the service or else it might
156 kHelperToolsDir, @kServiceName]; 139 // restart itself.
157 [self sudoDelete:[host_enabled UTF8String] usingAuth:authRef]; 140 [self sudoDelete:remoting::kHostEnabledPath usingAuth:authRef];
158 141
159 [self shutdownService]; 142 [self shutdownService];
160 143
161 NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", 144 [self sudoDelete:remoting::kServicePlistPath usingAuth:authRef];
162 kLaunchAgentsDir, @kServiceName]; 145 [self sudoDelete:remoting::kHostBinaryPath usingAuth:authRef];
163 [self sudoDelete:[plist UTF8String] usingAuth:authRef]; 146 [self sudoDelete:remoting::kHostHelperScriptPath usingAuth:authRef];
164 147 [self sudoDelete:remoting::kHostConfigFilePath usingAuth:authRef];
165 NSString* host_binary = [NSString stringWithFormat:@"%@/%@.me2me_host.app", 148 [self sudoDelete:remoting::kPrefPaneFilePath usingAuth:authRef];
166 kHelperToolsDir, @kServiceName]; 149 [self sudoDelete:remoting::kBrandedUninstallerPath usingAuth:authRef];
167 [self sudoDelete:[host_binary UTF8String] usingAuth:authRef]; 150 [self sudoDelete:remoting::kUnbrandedUninstallerPath usingAuth:authRef];
168
169 NSString* host_script = [NSString stringWithFormat:@"%@/%@.me2me.sh",
170 kHelperToolsDir, @kServiceName];
171 [self sudoDelete:[host_script UTF8String] usingAuth:authRef];
172
173 NSString* auth = [NSString stringWithFormat:@"%@/%@.json",
174 kHelperToolsDir, @kServiceName];
175 [self sudoDelete:[auth UTF8String] usingAuth:authRef];
176
177 NSString* prefpane = [NSString stringWithFormat:@"%@/%@",
178 kPrefPaneDir, kPrefPaneName];
179 [self sudoDelete:[prefpane UTF8String] usingAuth:authRef];
180
181 NSString* uninstaller = [NSString stringWithFormat:@"%@/%@",
182 kApplicationDir, kUninstallerName];
183 [self sudoDelete:[uninstaller UTF8String] usingAuth:authRef];
184 151
185 [self keystoneUnregisterUsingAuth:authRef]; 152 [self keystoneUnregisterUsingAuth:authRef];
186 } 153 }
187 154
188 - (IBAction)uninstall:(NSButton*)sender {
189 base::mac::ScopedAuthorizationRef authRef;
190
191 NSLog(@"Chrome Remote Desktop uninstall starting.");
192
193 @try {
194 OSStatus status;
195 status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
196 kAuthorizationFlagDefaults, &authRef);
197 if (status != errAuthorizationSuccess) {
198 [NSException raise:@"AuthorizationCreate Failure"
199 format:@"Error during AuthorizationCreate status=%ld", status];
200 }
201
202 AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
203 AuthorizationRights rights = {1, &right};
204 AuthorizationFlags flags = kAuthorizationFlagDefaults |
205 kAuthorizationFlagInteractionAllowed |
206 kAuthorizationFlagPreAuthorize |
207 kAuthorizationFlagExtendRights;
208 status = AuthorizationCopyRights(authRef, &rights, NULL, flags, NULL);
209 if (status == errAuthorizationCanceled) {
210 NSLog(@"Chrome Remote Desktop Host uninstall canceled.");
211 const char* message = "Chrome Remote Desktop Host uninstall canceled.";
212 [self messageBox:message];
213 } else if (status == errAuthorizationSuccess) {
214 [self remotingUninstallUsingAuth:authRef];
215
216 NSLog(@"Chrome Remote Desktop Host uninstall complete.");
217 const char* message =
218 "Chrome Remote Desktop Host was successfully uninstalled.";
219 [self messageBox:message];
220 } else {
221 [NSException raise:@"AuthorizationCopyRights Failure"
222 format:@"Error during AuthorizationCopyRights status=%ld", status];
223 }
224 }
225 @catch (NSException* exception) {
226 NSLog(@"Exception %@ %@", [exception name], [exception reason]);
227 const char* message =
228 "Error! Unable to uninstall Chrome Remote Desktop Host.";
229 [self messageBox:message];
230 }
231
232 [NSApp terminate:self];
233 }
234
235 - (IBAction)cancel:(id)sender {
236 [NSApp terminate:self];
237 }
238
239 - (IBAction)handleMenuClose:(NSMenuItem*)sender {
240 [NSApp terminate:self];
241 }
242
243 @end 155 @end
244
245 int main(int argc, char* argv[])
246 {
247 return NSApplicationMain(argc, (const char**)argv);
248 }
249
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698