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

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, 4 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
14 12
15 NSString* const kLaunchAgentsDir = @"/Library/LaunchAgents"; 13 void logOutput(FILE* pipe) {
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
24 // Keystone
25 const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/"
26 "GoogleSoftwareUpdate.bundle/Contents/MacOS/"
27 "ksadmin";
28 const char kKeystonePID[] = "com.google.chrome_remote_desktop";
29
30 - (void)dealloc {
31 [super dealloc];
32 }
33
34 - (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
35 }
36
37 - (void)logOutput:(FILE*) pipe {
38 char readBuffer[128]; 14 char readBuffer[128];
39 for (;;) { 15 for (;;) {
40 long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1); 16 long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1);
41 if (bytesRead < 1) 17 if (bytesRead < 1)
42 break; 18 break;
43 readBuffer[bytesRead] = '\0'; 19 readBuffer[bytesRead] = '\0';
44 NSLog(@"%s", readBuffer); 20 NSLog(@"%s", readBuffer);
45 } 21 }
46 } 22 }
47 23
48 - (void)messageBox:(const char*)message { 24 NSArray* convertToNSArray(const char** array) {
49 base::mac::ScopedCFTypeRef<CFStringRef> message_ref( 25 NSMutableArray* ns_array = [[[NSMutableArray alloc] init] autorelease];
50 CFStringCreateWithCString(NULL, message, (int)strlen(message))); 26 int i = 0;
51 CFOptionFlags result; 27 const char* element = array[i++];
52 CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, 28 while (element != NULL) {
53 NULL, NULL, NULL, 29 [ns_array addObject:[NSString stringWithUTF8String:element]];
54 CFSTR("Chrome Remote Desktop Uninstaller"), 30 element = array[i++];
55 message_ref, NULL, NULL, NULL, &result); 31 }
32 return ns_array;
56 } 33 }
57 34
58 -(void)runCommand:(NSString*)cmd 35 @implementation RemotingUninstaller
59 withArguments:(NSArray*)args { 36
37 // Keystone
38 const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/"
39 "GoogleSoftwareUpdate.bundle/Contents/MacOS/"
40 "ksadmin";
41 const char kKeystonePID[] = "com.google.chrome_remote_desktop";
42
43 - (void)runCommand:(const char*)cmd
44 withArguments:(const char**)args {
60 NSTask* task; 45 NSTask* task;
61 NSPipe* output = [NSPipe pipe]; 46 NSPipe* output = [NSPipe pipe];
62 NSString* result; 47 NSString* result;
63 48
64 NSLog(@"Executing: %@ %@", cmd, [args componentsJoinedByString:@" "]); 49 NSArray* arg_array = convertToNSArray(args);
50 NSLog(@"Executing: %s %@", cmd, [arg_array componentsJoinedByString:@" "]);
65 51
66 @try { 52 @try {
67 task = [[[NSTask alloc] init] autorelease]; 53 task = [[[NSTask alloc] init] autorelease];
68 [task setLaunchPath:cmd]; 54 [task setLaunchPath:[NSString stringWithUTF8String:cmd]];
69 [task setArguments:args]; 55 [task setArguments:arg_array];
70 [task setStandardInput:[NSPipe pipe]]; 56 [task setStandardInput:[NSPipe pipe]];
71 [task setStandardOutput:output]; 57 [task setStandardOutput:output];
72 [task launch]; 58 [task launch];
73 59
74 NSData* data = [[output fileHandleForReading] readDataToEndOfFile]; 60 NSData* data = [[output fileHandleForReading] readDataToEndOfFile];
75 61
76 [task waitUntilExit]; 62 [task waitUntilExit];
77 63
78 if ([task terminationStatus] != 0) { 64 if ([task terminationStatus] != 0) {
79 // TODO(garykac): When we switch to sdk_10.6, show the 65 // TODO(garykac): When we switch to sdk_10.6, show the
80 // [task terminationReason] as well. 66 // [task terminationReason] as well.
81 NSLog(@"Command terminated status=%d", [task terminationStatus]); 67 NSLog(@"Command terminated status=%d", [task terminationStatus]);
82 } 68 }
83 69
84 result = [[[NSString alloc] initWithData:data 70 result = [[[NSString alloc] initWithData:data
85 encoding:NSUTF8StringEncoding] 71 encoding:NSUTF8StringEncoding]
86 autorelease]; 72 autorelease];
87 if ([result length] != 0) { 73 if ([result length] != 0) {
88 NSLog(@"Result: %@", result); 74 NSLog(@"Result: %@", result);
89 } 75 }
90 } 76 }
91 @catch (NSException* exception) { 77 @catch (NSException* exception) {
92 NSLog(@"Exception %@ %@", [exception name], [exception reason]); 78 NSLog(@"Exception %@ %@", [exception name], [exception reason]);
93 } 79 }
94 } 80 }
95 81
96 - (void)sudoCommand:(const char*)cmd 82 - (void)sudoCommand:(const char*)cmd
97 withArguments:(const char**)args 83 withArguments:(const char**)args
98 usingAuth:(AuthorizationRef)authRef { 84 usingAuth:(AuthorizationRef)authRef {
99 85 NSArray* arg_array = convertToNSArray(args);
100 NSMutableArray* arg_array = [[[NSMutableArray alloc] init] autorelease];
101 int i = 0;
102 const char* arg = args[i++];
103 while (arg != NULL) {
104 [arg_array addObject:[NSString stringWithUTF8String:arg]];
105 arg = args[i++];
106 }
107 NSLog(@"Executing (as Admin): %s %@", cmd, 86 NSLog(@"Executing (as Admin): %s %@", cmd,
108 [arg_array componentsJoinedByString:@" "]); 87 [arg_array componentsJoinedByString:@" "]);
109 FILE* pipe = NULL; 88 FILE* pipe = NULL;
110 OSStatus status; 89 OSStatus status;
111 status = AuthorizationExecuteWithPrivileges(authRef, cmd, 90 status = AuthorizationExecuteWithPrivileges(authRef, cmd,
112 kAuthorizationFlagDefaults, 91 kAuthorizationFlagDefaults,
113 (char* const*)args, 92 (char* const*)args,
114 &pipe); 93 &pipe);
115 94
116 if (status == errAuthorizationToolExecuteFailure) { 95 if (status == errAuthorizationToolExecuteFailure) {
117 NSLog(@"Error errAuthorizationToolExecuteFailure"); 96 NSLog(@"Error errAuthorizationToolExecuteFailure");
118 } else if (status != errAuthorizationSuccess) { 97 } else if (status != errAuthorizationSuccess) {
119 NSLog(@"Error while executing %s. Status=%lx", cmd, status); 98 NSLog(@"Error while executing %s. Status=%lx", cmd, status);
120 } else { 99 } else {
121 [self logOutput:pipe]; 100 logOutput(pipe);
122 } 101 }
123 102
124 if (pipe != NULL) 103 if (pipe != NULL)
125 fclose(pipe); 104 fclose(pipe);
126 } 105 }
127 106
128 - (void)sudoDelete:(const char*)filename 107 - (void)sudoDelete:(const char*)filename
129 usingAuth:(AuthorizationRef)authRef { 108 usingAuth:(AuthorizationRef)authRef {
130 const char* args[] = { "-rf", filename, NULL }; 109 const char* args[] = { "-rf", filename, NULL };
131 [self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef]; 110 [self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef];
132 } 111 }
133 112
134 -(void)shutdownService { 113 - (void)shutdownService {
135 NSString* launchCtl = @"/bin/launchctl"; 114 const char* launchCtl = "/bin/launchctl";
136 NSArray* argsStop = [NSArray arrayWithObjects:@"stop", 115 const char* argsStop[] = { "stop", remoting::kServiceName, NULL };
137 @kServiceName, nil];
138 [self runCommand:launchCtl withArguments:argsStop]; 116 [self runCommand:launchCtl withArguments:argsStop];
139 117
140 NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", 118 if ([[NSFileManager defaultManager] fileExistsAtPath:
141 kLaunchAgentsDir, @kServiceName]; 119 [NSString stringWithUTF8String:remoting::kServicePlistPath]]) {
142 if ([[NSFileManager defaultManager] fileExistsAtPath:plist]) { 120 const char* argsUnload[] = { "unload", "-w", "-S", "Aqua",
143 NSArray* argsUnload = [NSArray arrayWithObjects:@"unload", 121 remoting::kServicePlistPath, NULL };
144 @"-w", @"-S", @"Aqua", plist, nil];
145 [self runCommand:launchCtl withArguments:argsUnload]; 122 [self runCommand:launchCtl withArguments:argsUnload];
146 } 123 }
147 } 124 }
148 125
149 -(void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef { 126 - (void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef {
150 const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL }; 127 const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL };
151 [self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef]; 128 [self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef];
152 } 129 }
153 130
154 -(void)remotingUninstallUsingAuth:(AuthorizationRef)authRef { 131 - (void)remotingUninstallUsingAuth:(AuthorizationRef)authRef {
155 NSString* host_enabled = [NSString stringWithFormat:@"%@/%@.me2me_enabled", 132 // Remove the enabled file before shutting down the service or else it might
156 kHelperToolsDir, @kServiceName]; 133 // restart itself.
157 [self sudoDelete:[host_enabled UTF8String] usingAuth:authRef]; 134 [self sudoDelete:remoting::kHostEnabledPath usingAuth:authRef];
158 135
159 [self shutdownService]; 136 [self shutdownService];
160 137
161 NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", 138 [self sudoDelete:remoting::kServicePlistPath usingAuth:authRef];
162 kLaunchAgentsDir, @kServiceName]; 139 [self sudoDelete:remoting::kHostBinaryPath usingAuth:authRef];
163 [self sudoDelete:[plist UTF8String] usingAuth:authRef]; 140 [self sudoDelete:remoting::kHostHelperScriptPath usingAuth:authRef];
164 141 [self sudoDelete:remoting::kHostConfigFilePath usingAuth:authRef];
165 NSString* host_binary = [NSString stringWithFormat:@"%@/%@.me2me_host.app", 142 [self sudoDelete:remoting::kPrefPaneFilePath usingAuth:authRef];
166 kHelperToolsDir, @kServiceName]; 143 [self sudoDelete:remoting::kBrandedUninstallerPath usingAuth:authRef];
167 [self sudoDelete:[host_binary UTF8String] usingAuth:authRef]; 144 [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 145
185 [self keystoneUnregisterUsingAuth:authRef]; 146 [self keystoneUnregisterUsingAuth:authRef];
186 } 147 }
187 148
188 - (IBAction)uninstall:(NSButton*)sender { 149 - (OSStatus)remotingUninstall {
189 base::mac::ScopedAuthorizationRef authRef; 150 base::mac::ScopedAuthorizationRef authRef;
190 151 OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
191 NSLog(@"Chrome Remote Desktop uninstall starting."); 152 kAuthorizationFlagDefaults, &authRef);
192 153 if (status != errAuthorizationSuccess) {
193 @try { 154 [NSException raise:@"AuthorizationCreate Failure"
194 OSStatus status; 155 format:@"Error during AuthorizationCreate status=%ld", 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 } 156 }
231 157
232 [NSApp terminate:self]; 158 AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0};
233 } 159 AuthorizationRights rights = {1, &right};
234 160 AuthorizationFlags flags = kAuthorizationFlagDefaults |
235 - (IBAction)cancel:(id)sender { 161 kAuthorizationFlagInteractionAllowed |
236 [NSApp terminate:self]; 162 kAuthorizationFlagPreAuthorize |
237 } 163 kAuthorizationFlagExtendRights;
238 164 status = AuthorizationCopyRights(authRef, &rights, NULL, flags, NULL);
239 - (IBAction)handleMenuClose:(NSMenuItem*)sender { 165 if (status == errAuthorizationSuccess) {
240 [NSApp terminate:self]; 166 RemotingUninstaller* uninstaller =
167 [[[RemotingUninstaller alloc] init] autorelease];
168 [uninstaller remotingUninstallUsingAuth:authRef];
169 }
170 return status;
241 } 171 }
242 172
243 @end 173 @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