Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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. | |
| 4 | |
| 5 #import "AuthorizedInstall.h" | |
| 6 | |
| 7 @interface AuthorizedInstall () { | |
| 8 NSFileHandle* communicationFile_; | |
| 9 NSString* destinationAppBundlePath_; | |
| 10 } | |
| 11 @end | |
| 12 | |
| 13 @implementation AuthorizedInstall | |
| 14 // Does the setup needed to authorize a tool to run as admin. | |
| 15 - (OSStatus)setUpAuthorization:(AuthorizationRef*)authRef { | |
| 16 OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, | |
| 17 kAuthorizationFlagDefaults, authRef); | |
| 18 | |
| 19 AuthorizationItem items = {kAuthorizationRightExecute, 0, NULL, 0}; | |
| 20 AuthorizationRights rights = {1, &items}; | |
| 21 AuthorizationFlags flags = | |
| 22 kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | | |
| 23 kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; | |
| 24 | |
| 25 status = AuthorizationCopyRights(*authRef, &rights, NULL, flags, NULL); | |
| 26 return status; | |
| 27 } | |
| 28 | |
| 29 // Starts up the proccess with privileged permissions. | |
| 30 - (void)startPrivilegedTool:(const char*)toolPath | |
| 31 withArguments:(const char**)args | |
| 32 authorization:(AuthorizationRef)authRef | |
| 33 status:(OSStatus)status { | |
| 34 if (status != errAuthorizationSuccess) | |
| 35 return; | |
| 36 | |
| 37 FILE* file; | |
| 38 #pragma clang diagnostic push | |
| 39 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
| 40 status = AuthorizationExecuteWithPrivileges( | |
| 41 authRef, toolPath, kAuthorizationFlagDefaults, (char* const*)args, &file); | |
| 42 #pragma clang diagnostic pop | |
| 43 communicationFile_ = [[NSFileHandle alloc] initWithFileDescriptor:fileno(file) | |
| 44 closeOnDealloc:YES]; | |
| 45 } | |
| 46 | |
| 47 // Starts up same proccess as above without privileged permissions. | |
| 48 - (void)startUnprivilegedTool:(NSString*)toolPath withArguments:(NSArray*)args { | |
| 49 NSPipe* pipe = [NSPipe pipe]; | |
| 50 NSTask* task = [[NSTask alloc] init]; | |
| 51 [task setArguments:args]; | |
| 52 [task setLaunchPath:toolPath]; | |
| 53 [task setStandardInput:pipe]; | |
| 54 [task launch]; | |
| 55 communicationFile_ = [pipe fileHandleForWriting]; | |
| 56 } | |
| 57 | |
| 58 // Determines which "Applications" folder to use based on authorization. | |
| 59 // There are three possible scenarios and two possible return values. | |
| 60 // 1) /Applications is returned if: | |
| 61 // a) The user authenticates the app. | |
| 62 // b) The user doesn't authenticate but is an admin. | |
| 63 // 2) /Users/username/Applications is returned if: | |
| 64 // c) The user doesn't authenticate and is not an admin. | |
|
Elly Fong-Jones
2016/08/24 16:39:22
This comment is so good. You can refer to /Users/u
ivanhernandez
2016/08/24 18:23:17
Done.
| |
| 65 - (NSString*)getApplicationsFolder:(BOOL)isAuthorized { | |
| 66 NSFileManager* manager = [NSFileManager defaultManager]; | |
| 67 NSArray* applicationDirectories = NSSearchPathForDirectoriesInDomains( | |
| 68 NSApplicationDirectory, NSLocalDomainMask, YES); | |
| 69 if (isAuthorized || | |
| 70 [manager isWritableFileAtPath:applicationDirectories.firstObject]) { | |
| 71 return applicationDirectories.firstObject; | |
| 72 } else { | |
| 73 NSString* usersApplicationsDirectory = | |
| 74 [NSString pathWithComponents:@[ NSHomeDirectory(), @"Applications" ]]; | |
| 75 if (![manager fileExistsAtPath:usersApplicationsDirectory]) { | |
| 76 [manager createDirectoryAtPath:usersApplicationsDirectory | |
| 77 withIntermediateDirectories:NO | |
| 78 attributes:nil | |
| 79 error:nil]; | |
| 80 } | |
| 81 return usersApplicationsDirectory; | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 // Attempts to gain authorization to run installation tool with elevated | |
| 86 // permissions. | |
| 87 // Then starts the tool with the appropiate paths for the tools elevation | |
| 88 // status. | |
| 89 - (BOOL)loadInstallationTool { | |
| 90 AuthorizationRef authRef = NULL; | |
| 91 OSStatus status = [self setUpAuthorization:&authRef]; | |
| 92 BOOL isAuthorized = (status == errAuthorizationSuccess); | |
| 93 | |
| 94 NSString* toolPath = | |
| 95 [[NSBundle mainBundle] pathForResource:@"copy_to_disk" ofType:@"sh"]; | |
| 96 NSFileManager* manager = [NSFileManager defaultManager]; | |
| 97 if (![manager fileExistsAtPath:toolPath]) { | |
| 98 return false; | |
| 99 } | |
| 100 | |
| 101 NSString* applicationsDirectory = [self getApplicationsFolder:isAuthorized]; | |
| 102 destinationAppBundlePath_ = [NSString pathWithComponents: @[ | |
| 103 applicationsDirectory, @"Google Chrome.app"]]; | |
|
Elly Fong-Jones
2016/08/24 16:39:22
no more Chromo? :)
ivanhernandez
2016/08/24 18:23:17
This app is moving up in the world.
| |
| 104 | |
| 105 if (isAuthorized) { | |
| 106 const char* args[] = {[applicationsDirectory UTF8String], NULL}; | |
| 107 [self startPrivilegedTool:[toolPath UTF8String] | |
| 108 withArguments:args | |
| 109 authorization:authRef | |
| 110 status:status]; | |
| 111 } else { | |
| 112 NSArray* args = @[ applicationsDirectory ]; | |
| 113 [self startUnprivilegedTool:toolPath withArguments:args]; | |
| 114 } | |
| 115 | |
| 116 AuthorizationFree(authRef, kAuthorizationFlagDestroyRights); | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 - (NSString*)startInstall:(NSString*)appBundlePath { | |
| 121 [self sendMessageToTool:appBundlePath]; | |
| 122 [self sendMessageToTool:@"\n"]; | |
|
Elly Fong-Jones
2016/08/24 16:39:22
that's odd - why is the newline necessary? is the
ivanhernandez
2016/08/24 18:23:16
Good point, having sendMessageToTool append the ne
| |
| 123 return destinationAppBundlePath_; | |
| 124 } | |
| 125 | |
| 126 // Sends a message to the tool's stdin. | |
| 127 - (void)sendMessageToTool:(NSString*)message { | |
| 128 [communicationFile_ | |
| 129 writeData:[message dataUsingEncoding:NSUTF8StringEncoding]]; | |
| 130 } | |
| 131 | |
| 132 @end | |
| OLD | NEW |