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

Side by Side Diff: chrome/installer/mac/app/Unpacker.m

Issue 2203583002: Added unpacking step (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added use of temporary folders, removed semaphore from main installer code, adjusted some files' APIs, resolved remaining comments Created 4 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
OLDNEW
(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 #include <dispatch/dispatch.h>
9
10 #import "Downloader.h"
11
12 @interface Unpacker () {
13 DASessionRef session;
14 dispatch_queue_t unpack_dq;
15
16 // TODO: narrow the scope for these variables
17 NSURL* temporaryDirectoryURL;
18 NSURL* temporaryDiskImageURL;
19 NSString* mountPath;
Sidney San Martín 2016/08/13 12:37:18 I believe instance variables should always have tr
Anna Zeng 2016/08/16 23:07:39 Done.
20 }
21 @end
22
23 @implementation Unpacker
24
25 @synthesize delegate = delegate_;
26 @synthesize appPath = appPath_;
27
28 // TODO: clean up error handling & pass up to appdelegate
29 static void unmount_callback(DADiskRef disk,
Sidney San Martín 2016/08/13 12:37:19 These functions should not be in the @implementati
Anna Zeng 2016/08/16 23:07:39 Done.
30 DADissenterRef dissenter,
31 void* context) {
32 if (dissenter) {
Sidney San Martín 2016/08/13 12:37:19 There's a similar block of code in eject_callback.
Anna Zeng 2016/08/16 23:07:40 Done.
33 DAReturn status = DADissenterGetStatus(dissenter);
34 if (unix_err(status)) {
35 int code = err_get_code(status);
36 NSLog(@"Unmount error code %d", code);
37 }
38 } else {
39 DADiskEject(disk, kDADiskEjectOptionDefault, eject_callback, context);
40 }
41 }
42
43 static void eject_callback(DADiskRef disk,
44 DADissenterRef dissenter,
45 void* context) {
46 NSError* error = nil;
47 if (dissenter) {
48 DAReturn status = DADissenterGetStatus(dissenter);
49 if (unix_err(status)) {
50 int code = err_get_code(status);
51 NSLog(@"Eject error code %d", code);
52 error = [NSError
53 errorWithDomain:@"ChromeErrorDomain"
54 code:code
55 userInfo:@{
56 NSLocalizedDescriptionKey :
57 (__bridge NSString*)DADissenterGetStatusString(dissenter)
58 }];
59 }
60 } else {
61 Unpacker* unpacker = (__bridge Unpacker*)context;
62 [unpacker didFinishEjectingDisk:disk WithError:error];
63 }
64 }
65
66 // TODO: presumably we'd pass in the authenticated/unauthenticated path in here;
67 // however we will change this to a different model that will allow for a
68 // separate authenticated process to run
69 - (id)initWithFinalAppPath:(NSString*)appPath {
70 if ((self = [super init])) {
71 appPath_ = appPath;
72 }
73 return self;
74 }
75
76 // TODO: the failure delegate methods need to be revised to be more meaningfully
77 // deal with the errors (pipe in stderr / stdout)
78 - (void)mountDMGFromURL:(NSURL*)fileURL {
79 NSError* error = nil;
80 temporaryDirectoryURL = [[NSFileManager defaultManager]
81 URLForDirectory:NSItemReplacementDirectory
82 inDomain:NSUserDomainMask
83 appropriateForURL:[NSURL fileURLWithPath:@"/" isDirectory:YES]
84 create:YES
85 error:&error];
86 if (error) {
87 [delegate_ unpacker:self onMountFailure:nil];
88 }
89
90 temporaryDiskImageURL =
91 [temporaryDirectoryURL URLByAppendingPathComponent:@"GoogleChrome.dmg"];
92 mountPath = [[temporaryDirectoryURL URLByAppendingPathComponent:@"mnt"
93 isDirectory:YES] path];
94 [[NSFileManager defaultManager] createDirectoryAtPath:mountPath
95 withIntermediateDirectories:YES
96 attributes:nil
97 error:&error];
98 if (error) {
99 [delegate_ unpacker:self onMountFailure:nil];
100 }
101
102 [[NSFileManager defaultManager] moveItemAtURL:fileURL
103 toURL:temporaryDiskImageURL
104 error:nil];
105
106 dispatch_semaphore_t mount_semaphore = dispatch_semaphore_create(0);
107 NSString* path = @"/usr/bin/hdiutil";
108 NSArray* args = @[
109 @"mount", temporaryDiskImageURL, @"-nobrowse", @"-mountpoint", mountPath
110 ];
111
112 NSTask* mountTask = [[NSTask alloc] init];
113 mountTask.launchPath = path;
114 mountTask.arguments = args;
115 mountTask.terminationHandler = ^void(NSTask* task) {
116 // unpack_dq = dispatch_queue_create("com.google.chrome.unpack",
Elly Fong-Jones 2016/08/16 15:26:18 does this commented code need to be here?
Anna Zeng 2016/08/16 23:07:40 This code was not completely deleted in case I nee
117 // DISPATCH_QUEUE_SERIAL);
118 // dispatch_async(unpack_dq, ^{
119 dispatch_semaphore_signal(mount_semaphore);
120 // });
121 };
122 [mountTask launch];
123
124 dispatch_semaphore_wait(mount_semaphore, DISPATCH_TIME_FOREVER);
Elly Fong-Jones 2016/08/16 15:26:18 is this running on a work queue or somesuch? other
Anna Zeng 2016/08/16 23:07:40 Currently, it is not. Would you recommend running
125 [delegate_ unpacker:self onMountSuccess:mountPath];
126 }
127
128 - (void)extractChrome {
129 NSString* diskAppPath = [[temporaryDirectoryURL
130 URLByAppendingPathComponent:@"mnt/Google Chrome.app"
131 isDirectory:YES] path];
132 if (![[NSFileManager defaultManager] fileExistsAtPath:diskAppPath]) {
133 NSLog(@"File in DMG doesn't exist");
134 [delegate_ unpacker:self onExtractFailure:appPath_];
135 }
136
137 // TODO: add progress
138 NSError* err;
139 if (![[NSFileManager defaultManager] copyItemAtPath:diskAppPath
140 toPath:appPath_
141 error:&err]) {
142 NSLog(@"%@", err);
143 [delegate_ unpacker:self onExtractFailure:appPath_];
144 }
145 [delegate_ unpacker:self onExtractSuccess:appPath_];
146 }
147
148 - (void)unmountDMG {
149 session = DASessionCreate(nil);
150 unpack_dq =
151 dispatch_queue_create("com.google.chrome.unpack", DISPATCH_QUEUE_SERIAL);
152 DASessionSetDispatchQueue(session, unpack_dq);
153 DADiskRef child_disk = DADiskCreateFromVolumePath(
154 nil, session, (CFURLRef)[NSURL URLWithString:mountPath]);
155 DADiskRef whole_disk = DADiskCopyWholeDisk(child_disk);
156
157 DADiskUnmount(whole_disk, kDADiskUnmountOptionWhole, unmount_callback,
Sidney San Martín 2016/08/13 12:37:18 I might also pass `kDADiskUnmountOptionForce`. If
Anna Zeng 2016/08/16 23:07:40 Done.
158 (void*)self);
159
160 CFRelease(whole_disk);
161 CFRelease(child_disk);
162 }
163
164 - (void)didFinishEjectingDisk:(DADiskRef)disk WithError:(NSError*)error {
165 DASessionSetDispatchQueue(session, NULL);
166 dispatch_release(unpack_dq);
167 if (error) {
168 [delegate_ unpacker:self onUnmountFailure:error];
169 } else {
170 [delegate_ unpacker:self onUnmountSuccess:nil];
171 }
172 }
173
174 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698