Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 "AppDelegate.h" | 5 #import "AppDelegate.h" |
| 6 | 6 |
| 7 #include <Security/Security.h> | 7 #include <Security/Security.h> |
| 8 | 8 |
| 9 #include "chrome/common/chrome_switches.h" | 9 #include "chrome/common/chrome_switches.h" |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 } | 32 } |
| 33 @property(strong) NSWindow* window; | 33 @property(strong) NSWindow* window; |
| 34 - (void)exit; | 34 - (void)exit; |
| 35 @end | 35 @end |
| 36 | 36 |
| 37 @implementation AppDelegate | 37 @implementation AppDelegate |
| 38 @synthesize window = window_; | 38 @synthesize window = window_; |
| 39 | 39 |
| 40 // Sets up the main window and begins the downloading process. | 40 // Sets up the main window and begins the downloading process. |
| 41 - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { | 41 - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { |
| 42 // TODO: fix UI not loading until after asking for authorization. | 42 // TODO: Despite what the code implies -- when the installer is run, the main |
| 43 // window of the application is not visible until the user has taken action on | |
| 44 // the Authorization modal. | |
| 43 window_.delegate = self; | 45 window_.delegate = self; |
| 44 installerWindowController_ = | 46 installerWindowController_ = |
| 45 [[InstallerWindowController alloc] initWithWindow:window_]; | 47 [[InstallerWindowController alloc] initWithWindow:window_]; |
| 46 authorizedInstall_ = [[AuthorizedInstall alloc] init]; | 48 authorizedInstall_ = [[AuthorizedInstall alloc] init]; |
| 47 if ([authorizedInstall_ loadInstallationTool]) { | 49 if ([authorizedInstall_ loadInstallationTool]) { |
| 48 [self startDownload]; | 50 [self startDownload]; |
| 49 } else { | 51 } else { |
| 50 [self onLoadInstallationToolFailure]; | 52 [self onLoadInstallationToolFailure]; |
| 51 } | 53 } |
| 52 } | 54 } |
| 53 | 55 |
| 54 - (void)applicationWillTerminate:(NSNotification*)aNotification { | 56 - (void)applicationWillTerminate:(NSNotification*)aNotification { |
| 55 } | 57 } |
| 56 | 58 |
| 57 - (NSApplicationTerminateReply)applicationShouldTerminate: | 59 - (NSApplicationTerminateReply)applicationShouldTerminate: |
| 58 (NSApplication*)sender { | 60 (NSApplication*)sender { |
| 59 return preventTermination_ ? NSTerminateCancel : NSTerminateNow; | 61 return preventTermination_ ? NSTerminateCancel : NSTerminateNow; |
| 60 } | 62 } |
| 61 | 63 |
| 62 // This function effectively takes the place of | 64 // This function effectively takes the place of |
| 63 // applicationShouldTerminateAfterLastWindowClosed: to make sure that the | 65 // applicationShouldTerminateAfterLastWindowClosed: to make sure that the |
| 64 // application does correctly terminate after closing the installer, but does | 66 // application does correctly terminate after closing the installer, but does |
| 65 // not terminate when we call orderOut: to hide the installer during its | 67 // not terminate when we call orderOut: to hide the installer during its |
| 66 // tear-down steps. | 68 // tear-down steps. If the user force-quits the application, the below delegate |
|
Sidney San Martín
2016/08/31 21:20:16
Force quit (cmd+option+esc) just kills the process
| |
| 69 // method gets called. However, when orderOut is called, the below delegate | |
| 70 // method does not get called. | |
| 67 - (BOOL)windowShouldClose:(id)sender { | 71 - (BOOL)windowShouldClose:(id)sender { |
| 68 [self exit]; | 72 [self exit]; |
| 69 return YES; | 73 return YES; |
| 70 } | 74 } |
| 71 | 75 |
| 72 - (void)exit { | 76 - (void)exit { |
| 73 preventTermination_ = NO; | 77 preventTermination_ = NO; |
| 74 [NSApp terminate:nil]; | 78 [NSApp terminate:nil]; |
| 75 } | 79 } |
| 76 | 80 |
| 77 - (void)startDownload { | 81 - (void)startDownload { |
| 78 [installerWindowController_ updateStatusDescription:@"Initializing..."]; | 82 [installerWindowController_ updateStatusDescription:@"Initializing..."]; |
| 79 | 83 |
| 80 OmahaCommunication* omahaMessenger = [[OmahaCommunication alloc] init]; | 84 OmahaCommunication* omahaMessenger = [[OmahaCommunication alloc] init]; |
| 81 omahaMessenger.delegate = self; | 85 omahaMessenger.delegate = self; |
| 82 [omahaMessenger fetchDownloadURLs]; | 86 [omahaMessenger fetchDownloadURLs]; |
| 83 } | 87 } |
| 84 | 88 |
| 85 - (void)onLoadInstallationToolFailure { | 89 - (void)onLoadInstallationToolFailure { |
| 86 NSError* loadToolError = [NSError | 90 NSError* loadToolError = [NSError |
| 87 errorForAlerts:@"Could not load installion tool" | 91 errorForAlerts:@"Internal Error" |
| 88 withDescription: | 92 withDescription: |
| 89 @"Your Chrome Installer may be corrupted. Download and try again." | 93 @"Your Chrome Installer may be corrupted. Download and try again." |
| 90 isRecoverable:NO]; | 94 isRecoverable:NO]; |
| 91 [self displayError:loadToolError]; | 95 [self displayError:loadToolError]; |
| 92 } | 96 } |
| 93 | 97 |
| 94 - (void)omahaCommunication:(OmahaCommunication*)messenger | 98 - (void)omahaCommunication:(OmahaCommunication*)messenger |
| 95 onSuccess:(NSArray*)URLs { | 99 onSuccess:(NSArray*)URLs { |
| 96 [installerWindowController_ updateStatusDescription:@"Downloading..."]; | 100 [installerWindowController_ updateStatusDescription:@"Downloading..."]; |
| 97 | 101 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 128 NSError* downloadError = | 132 NSError* downloadError = |
| 129 [NSError errorForAlerts:@"Download Failure" | 133 [NSError errorForAlerts:@"Download Failure" |
| 130 withDescription:@"Unable to download Google Chrome." | 134 withDescription:@"Unable to download Google Chrome." |
| 131 isRecoverable:NO]; | 135 isRecoverable:NO]; |
| 132 [self displayError:downloadError]; | 136 [self displayError:downloadError]; |
| 133 } | 137 } |
| 134 | 138 |
| 135 - (void)unpacker:(Unpacker*)unpacker onMountSuccess:(NSString*)tempAppPath { | 139 - (void)unpacker:(Unpacker*)unpacker onMountSuccess:(NSString*)tempAppPath { |
| 136 SecStaticCodeRef diskStaticCode; | 140 SecStaticCodeRef diskStaticCode; |
| 137 SecRequirementRef diskRequirement; | 141 SecRequirementRef diskRequirement; |
| 138 // TODO: flush out error handling more | 142 // TODO: Include some better error handling below than NSLog |
| 139 OSStatus oserror; | 143 OSStatus oserror; |
| 140 oserror = SecStaticCodeCreateWithPath( | 144 oserror = SecStaticCodeCreateWithPath( |
| 141 (__bridge CFURLRef)[NSURL fileURLWithPath:tempAppPath isDirectory:NO], | 145 (__bridge CFURLRef)[NSURL fileURLWithPath:tempAppPath isDirectory:NO], |
| 142 kSecCSDefaultFlags, &diskStaticCode); | 146 kSecCSDefaultFlags, &diskStaticCode); |
| 143 if (oserror != errSecSuccess) | 147 if (oserror != errSecSuccess) |
| 144 NSLog(@"code %d", oserror); | 148 NSLog(@"code %d", oserror); |
| 145 // TODO: add in a more specific code sign requirement | 149 // TODO: The below requirement is too general as most signed entities have the |
| 150 // below requirement; replace it with something adequately specific. | |
| 146 oserror = | 151 oserror = |
| 147 SecRequirementCreateWithString((CFStringRef) @"anchor apple generic", | 152 SecRequirementCreateWithString((CFStringRef) @"anchor apple generic", |
| 148 kSecCSDefaultFlags, &diskRequirement); | 153 kSecCSDefaultFlags, &diskRequirement); |
| 149 if (oserror != errSecSuccess) | 154 if (oserror != errSecSuccess) |
| 150 NSLog(@"requirement %d", oserror); | 155 NSLog(@"requirement %d", oserror); |
| 151 oserror = SecStaticCodeCheckValidity(diskStaticCode, kSecCSDefaultFlags, | 156 oserror = SecStaticCodeCheckValidity(diskStaticCode, kSecCSDefaultFlags, |
| 152 diskRequirement); | 157 diskRequirement); |
| 153 if (oserror != errSecSuccess) | 158 if (oserror != errSecSuccess) |
| 154 NSLog(@"static code %d", oserror); | 159 NSLog(@"static code %d", oserror); |
| 155 | 160 |
| 156 // Calling this function will change the progress bar into an indeterminate | 161 // Calling this function will change the progress bar into an indeterminate |
| 157 // one. We won't need to update the progress bar any more after this point. | 162 // one. We won't need to update the progress bar any more after this point. |
| 158 [installerWindowController_ updateDownloadProgress:-1.0]; | 163 [installerWindowController_ updateDownloadProgress:-1.0]; |
| 159 // By disabling closing the window or quitting, we can tell the user that | 164 // By disabling closing the window or quitting, we can tell the user that |
| 160 // closing the application at this point is not a good idea. | 165 // closing the application at this point is not a good idea. |
| 161 window_.styleMask &= ~NSClosableWindowMask; | 166 window_.styleMask &= ~NSClosableWindowMask; |
| 162 preventTermination_ = YES; | 167 preventTermination_ = YES; |
| 163 | 168 |
| 164 NSString* chromeInApplicationsFolder = | 169 NSString* chromeInApplicationsFolder = |
| 165 [authorizedInstall_ startInstall:tempAppPath]; | 170 [authorizedInstall_ startInstall:tempAppPath]; |
| 166 | 171 |
| 167 NSMutableArray* installerSettings = [[NSMutableArray alloc] init]; | 172 NSMutableArray* installerSettings = [[NSMutableArray alloc] init]; |
| 168 if ([installerWindowController_ isUserMetricsChecked]) | 173 if ([installerWindowController_ isUserMetricsChecked]) |
| 169 [installerSettings | 174 [installerSettings |
| 170 addObject:[NSString stringWithUTF8String:switches::kEnableUserMetrics]]; | 175 addObject:[NSString stringWithUTF8String:switches::kEnableUserMetrics]]; |
| 171 if ([installerWindowController_ isDefaultBrowserChecked]) | 176 if ([installerWindowController_ isDefaultBrowserChecked]) |
| 172 [installerSettings | 177 [installerSettings |
| 173 addObject:[NSString | 178 addObject:[NSString |
| 179 // NOTE: the |kMakeDefaultBrowser| constant used as a | |
| 180 // command-line switch here only will apply at a user | |
| 181 // level, since the application itself is not running with | |
| 182 // privileges. grt@ suggested this constant should be | |
| 183 // renamed |kMakeDefaultBrowserforUser|. | |
| 174 stringWithUTF8String:switches::kMakeDefaultBrowser]]; | 184 stringWithUTF8String:switches::kMakeDefaultBrowser]]; |
| 175 | 185 |
| 176 NSError* error = nil; | 186 NSError* error = nil; |
| 177 [[NSWorkspace sharedWorkspace] | 187 [[NSWorkspace sharedWorkspace] |
| 178 launchApplicationAtURL:[NSURL fileURLWithPath:chromeInApplicationsFolder | 188 launchApplicationAtURL:[NSURL fileURLWithPath:chromeInApplicationsFolder |
| 179 isDirectory:NO] | 189 isDirectory:NO] |
| 180 options:NSWorkspaceLaunchDefault | 190 options:NSWorkspaceLaunchDefault |
| 181 configuration:@{ | 191 configuration:@{ |
| 182 NSWorkspaceLaunchConfigurationArguments : installerSettings | 192 NSWorkspaceLaunchConfigurationArguments : installerSettings |
| 183 } | 193 } |
| 184 error:&error]; | 194 error:&error]; |
| 185 if (error) { | 195 if (error) { |
| 186 NSLog(@"Chrome failed to launch: %@", error); | 196 NSLog(@"Chrome failed to launch: %@", error); |
| 187 } | 197 } |
| 188 | 198 |
| 189 // Begin teardown stuff! | 199 // Begin teardown step! |
| 190 dispatch_async(dispatch_get_main_queue(), ^{ | 200 dispatch_async(dispatch_get_main_queue(), ^{ |
| 191 [window_ orderOut:nil]; | 201 [window_ orderOut:nil]; |
| 192 }); | 202 }); |
| 193 | 203 |
| 194 [unpacker unmountDMG]; | 204 [unpacker unmountDMG]; |
| 195 } | 205 } |
| 196 | 206 |
| 197 - (void)unpacker:(Unpacker*)unpacker onMountFailure:(NSError*)error { | 207 - (void)unpacker:(Unpacker*)unpacker onMountFailure:(NSError*)error { |
| 198 NSError* extractError = | 208 NSError* extractError = |
| 199 [NSError errorForAlerts:@"Install Failure" | 209 [NSError errorForAlerts:@"Install Error" |
| 200 withDescription:@"Unable to add Google Chrome to Applications." | 210 withDescription:@"Unable to add Google Chrome to Applications." |
| 201 isRecoverable:NO]; | 211 isRecoverable:NO]; |
| 202 [self displayError:extractError]; | 212 [self displayError:extractError]; |
| 203 } | 213 } |
| 204 | 214 |
| 205 - (void)unpacker:(Unpacker*)unpacker onUnmountSuccess:(NSString*)mountpath { | 215 - (void)unpacker:(Unpacker*)unpacker onUnmountSuccess:(NSString*)mountpath { |
| 206 NSLog(@"we're done here!"); | 216 NSLog(@"we're done here!"); |
| 207 [self exit]; | 217 [self exit]; |
| 208 } | 218 } |
| 209 | 219 |
| 210 - (void)unpacker:(Unpacker*)unpacker onUnmountFailure:(NSError*)error { | 220 - (void)unpacker:(Unpacker*)unpacker onUnmountFailure:(NSError*)error { |
| 211 NSLog(@"error unmounting"); | 221 NSLog(@"error unmounting"); |
| 212 // NOTE: since we are not deleting the temporary folder if the unmount fails, | 222 // NOTE: Since we are not deleting the temporary folder if the unmount fails, |
| 213 // we'll just leave it up to the computer to delete the temporary folder on | 223 // we'll just leave it up to the computer to delete the temporary folder on |
| 214 // its own time, and to unmount the disk during a restart at some point. There | 224 // its own time and to unmount the disk during a restart at some point. There |
| 215 // is no other work to be done in the mean time. | 225 // is no other work to be done in the mean time. |
| 216 [self exit]; | 226 [self exit]; |
| 217 } | 227 } |
| 218 | 228 |
| 219 // Displays an alert on the main window using the contents of the passed in | 229 // Displays an alert on the main window using the contents of the passed in |
| 220 // error. | 230 // error. |
| 221 - (void)displayError:(NSError*)error { | 231 - (void)displayError:(NSError*)error { |
| 222 NSAlert* alertForUser = [NSAlert alertWithError:error]; | 232 NSAlert* alertForUser = [NSAlert alertWithError:error]; |
| 223 dispatch_async(dispatch_get_main_queue(), ^{ | 233 dispatch_async(dispatch_get_main_queue(), ^{ |
| 224 [alertForUser beginSheetModalForWindow:window_ | 234 [alertForUser beginSheetModalForWindow:window_ |
| 225 completionHandler:^(NSModalResponse returnCode) { | 235 completionHandler:^(NSModalResponse returnCode) { |
| 226 if (returnCode != [alertForUser quitResponse]) { | 236 if (returnCode != [alertForUser quitResponse]) { |
| 227 [self startDownload]; | 237 [self startDownload]; |
| 228 } else { | 238 } else { |
| 229 [NSApp terminate:nil]; | 239 [NSApp terminate:nil]; |
| 230 } | 240 } |
| 231 }]; | 241 }]; |
| 232 }); | 242 }); |
| 233 } | 243 } |
| 234 | 244 |
| 235 @end | 245 @end |
| OLD | NEW |