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 "Unpacker.h" | |
| 6 | |
| 7 #include <DiskArbitration/DiskArbitration.h> | |
| 8 | |
| 9 #import "Downloader.h" | |
| 10 | |
| 11 // TODO: make paths not depend on location of executable | |
| 12 // cocoa temporary folders: nstemporarydirectory | |
| 13 #define PATH_FROM_EXECUTABLE(x) \ | |
| 14 [[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:x] \ | |
| 15 stringByResolvingSymlinksInPath] | |
|
Sidney San Martín
2016/08/05 20:35:04
This should be a pretty quick change, any reason n
Anna Zeng
2016/08/05 21:48:40
I plan to include progress on this in the other re
| |
| 16 | |
| 17 @implementation Unpacker | |
| 18 | |
| 19 @synthesize delegate = delegate_; | |
| 20 | |
| 21 DASessionRef session; | |
| 22 | |
| 23 // TODO: make testing more convenient | |
| 24 | |
| 25 - (void)unpackDMG { | |
| 26 // TODO: how to find this from the PATH env variable? | |
| 27 NSString* path = @"/usr/bin/hdiutil"; | |
| 28 NSArray* args = @[ | |
| 29 // TODO: break getDownloadsFilePath out of the downloader file | |
| 30 @"mount", [Downloader getDownloadsFilePath], @"-nobrowse", @"-mountpoint", | |
| 31 PATH_FROM_EXECUTABLE(@"tmp") | |
| 32 ]; | |
| 33 | |
| 34 NSTask* unmountTask = [[NSTask alloc] init]; | |
| 35 unmountTask.launchPath = path; | |
| 36 unmountTask.arguments = args; | |
| 37 unmountTask.terminationHandler = ^void(NSTask* task) { | |
|
Mark Mentovai
2016/08/02 19:01:32
Aha! This is what’s causing all of the trouble wit
Anna Zeng
2016/08/02 23:58:22
Awesome! This helped immensely. I ended up using a
| |
| 38 [self extractChrome]; | |
| 39 }; | |
| 40 [unmountTask launch]; | |
| 41 } | |
| 42 | |
| 43 - (void)extractChrome { | |
| 44 NSLog(@"extracting chrome"); | |
| 45 NSFileManager* fileManager = [NSFileManager defaultManager]; | |
| 46 if (![fileManager | |
| 47 fileExistsAtPath:PATH_FROM_EXECUTABLE(@"tmp/Google Chrome.app")]) { | |
| 48 NSLog(@"File in DMG doesn't exist"); | |
| 49 } | |
| 50 | |
| 51 // TODO: make async | |
| 52 NSError* err; | |
| 53 if (![fileManager | |
| 54 copyItemAtPath:PATH_FROM_EXECUTABLE(@"tmp/Google Chrome.app") | |
| 55 toPath:@"/Applications/Google Chromo.app" | |
| 56 error:&err]) { | |
| 57 NSLog(@"%@", err); | |
| 58 } | |
| 59 | |
| 60 [self cleanUp]; | |
| 61 } | |
| 62 - (void)cleanUp { | |
| 63 NSFileManager* fileManager = [NSFileManager defaultManager]; | |
| 64 if ([fileManager removeItemAtPath:[Downloader getDownloadsFilePath] | |
| 65 error:nil]) { | |
| 66 NSLog(@"Disk image removed!"); | |
| 67 } | |
| 68 | |
| 69 // TODO: run the app instead of removing it every time | |
| 70 if ([fileManager removeItemAtPath:@"/Applications/Google Chromo.app" | |
| 71 error:nil]) { | |
| 72 NSLog(@"Application removed!"); | |
| 73 } | |
| 74 | |
| 75 session = DASessionCreate(nil); | |
| 76 DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), | |
| 77 kCFRunLoopCommonModes); | |
| 78 // TODO: how can we make the run loop run using the nsrunloop? | |
| 79 // DASessionScheduleWithRunLoop(session, [[NSRunLoop currentRunLoop] | |
| 80 // getCFRunLoop], | |
| 81 // (CFStringRef)NSDefaultRunLoopMode); | |
| 82 DADiskRef child_disk = DADiskCreateFromVolumePath( | |
| 83 nil, session, | |
| 84 (CFURLRef)[NSURL URLWithString:PATH_FROM_EXECUTABLE(@"tmp")]); | |
| 85 DADiskRef whole_disk = DADiskCopyWholeDisk(child_disk); | |
| 86 DADiskUnmount(whole_disk, kDADiskUnmountOptionWhole, unmount_callback, | |
| 87 (void*)self); | |
| 88 NSLog(@"Releasing disk"); | |
| 89 CFRelease(whole_disk); | |
| 90 CFRelease(child_disk); | |
| 91 | |
| 92 // TODO: when ivan's cr lands eliminate this bandaid | |
| 93 CFRunLoopRun(); | |
| 94 } | |
| 95 | |
| 96 void unmount_callback(DADiskRef disk, DADissenterRef dissenter, void* context) { | |
| 97 NSLog(@"reached unmount callback"); | |
| 98 if (dissenter) { | |
| 99 DAReturn status = DADissenterGetStatus(dissenter); | |
| 100 if (unix_err(status)) { | |
| 101 int code = err_get_code(status); | |
| 102 NSLog(@"Error code %d", code); | |
| 103 } | |
| 104 } else { | |
| 105 DADiskEject(disk, kDADiskEjectOptionDefault, eject_callback, context); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 void eject_callback(DADiskRef disk, DADissenterRef dissenter, void* context) { | |
| 110 NSLog(@"reached eject callback"); | |
| 111 if (dissenter) { | |
| 112 DAReturn status = DADissenterGetStatus(dissenter); | |
| 113 if (unix_err(status)) { | |
| 114 int code = err_get_code(status); | |
| 115 NSLog(@"Error code %d", code); | |
| 116 } | |
| 117 } | |
| 118 Unpacker* obj_self = (__bridge Unpacker*)context; | |
|
Sidney San Martín
2016/08/05 20:35:04
These functions aren't really part of Unpacker, so
Sidney San Martín
2016/08/05 21:13:40
You should also use `static` on these functions to
Anna Zeng
2016/08/05 21:48:40
Done.
Anna Zeng
2016/08/05 21:48:40
Done.
| |
| 119 [obj_self callbackFollowDisk:disk]; | |
|
Sidney San Martín
2016/08/05 20:35:04
Could you include error info in the callback?
Anna Zeng
2016/08/05 21:48:40
Done, with more progress to come!
| |
| 120 } | |
| 121 | |
| 122 - (void)callbackFollowDisk:(DADiskRef)disk { | |
| 123 NSLog(@"Unscheduling session"); | |
| 124 DASessionUnscheduleFromRunLoop( | |
| 125 session, CFRunLoopGetCurrent(), | |
| 126 kCFRunLoopCommonModes); // kCFRunLoopDefaultMode); | |
| 127 | |
| 128 [delegate_ onUnpackSuccess]; | |
| 129 } | |
| 130 | |
| 131 @end | |
| OLD | NEW |