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

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 in SecCodeCheckValidity in place of the hdiutil checksum Created 4 years, 3 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 #import <AppKit/AppKit.h>
8 #include <DiskArbitration/DiskArbitration.h>
9 #include <dispatch/dispatch.h>
10 #include <Security/Security.h>
11
12 #import "Downloader.h"
13
14 @interface Unpacker () {
15 NSURL* temporaryDirectoryURL_;
16 NSString* mountPath_;
17
18 NSTask* __weak mountTask_;
19
20 DASessionRef session_;
21 dispatch_queue_t unpack_dq_;
22 }
23 - (void)didFinishEjectingDisk:(DADiskRef)disk
24 withDissenter:(DADissenterRef)dissenter;
25 @end
26
27 static void eject_callback(DADiskRef disk,
28 DADissenterRef dissenter,
29 void* context) {
30 Unpacker* unpacker = (__bridge Unpacker*)context;
31 [unpacker didFinishEjectingDisk:disk withDissenter:dissenter];
32 }
33
34 static void unmount_callback(DADiskRef disk,
35 DADissenterRef dissenter,
36 void* context) {
37 if (dissenter) {
38 Unpacker* unpacker = (__bridge Unpacker*)context;
39 [unpacker didFinishEjectingDisk:disk withDissenter:dissenter];
40 } else {
41 DADiskEject(disk, kDADiskEjectOptionDefault, eject_callback, context);
42 }
43 }
44
45 @implementation Unpacker
46
47 @synthesize delegate = delegate_;
48 @synthesize appPath = appPath_;
49
50 - (void)cleanUp {
51 [mountTask_ terminate];
52 // It's not the end of the world if this temporary directory is not removed
53 // here. It will be deleted when the operating system itself decides to
54 // anyway.
55 [[NSFileManager defaultManager] removeItemAtURL:temporaryDirectoryURL_
56 error:nil];
57 [[NSNotificationCenter defaultCenter] removeObserver:self];
58 }
59
60 // TODO: the failure delegate methods need to be revised to be more meaningfully
61 // deal with the errors (pipe in stderr / stdout)
62 - (void)mountDMGFromURL:(NSURL*)fileURL {
63 NSError* error = nil;
64 temporaryDirectoryURL_ = [[NSFileManager defaultManager]
65 URLForDirectory:NSItemReplacementDirectory
66 inDomain:NSUserDomainMask
67 appropriateForURL:[NSURL fileURLWithPath:@"/" isDirectory:YES]
68 create:YES
69 error:&error];
70 if (error) {
71 [delegate_ unpacker:self onMountFailure:error];
72 return;
73 }
74
75 NSURL* temporaryDiskImageURL =
76 [temporaryDirectoryURL_ URLByAppendingPathComponent:@"GoogleChrome.dmg"];
77 mountPath_ = [[temporaryDirectoryURL_ URLByAppendingPathComponent:@"mnt"
78 isDirectory:YES] path];
79 [[NSFileManager defaultManager] createDirectoryAtPath:mountPath_
80 withIntermediateDirectories:YES
81 attributes:nil
82 error:&error];
83 if (error) {
84 [delegate_ unpacker:self onMountFailure:error];
85 return;
86 }
87 [[NSNotificationCenter defaultCenter]
88 addObserver:self
89 selector:@selector(cleanUp)
90 name:NSApplicationWillTerminateNotification
91 object:nil];
92
93 [[NSFileManager defaultManager] moveItemAtURL:fileURL
94 toURL:temporaryDiskImageURL
95 error:nil];
96
97 // FIXME: type mismatch using these coderefs?
98 SecStaticCodeRef diskStaticCode;
99 SecRequirementRef diskRequirement;
100 SecStaticCodeCreateWithPath((CFURLRef)CFBridgingRetain(temporaryDiskImageURL),
101 kSecCSDefaultFlags, &diskStaticCode);
102 // TODO: what requirement goes in here??
103 SecRequirementCreateWithString((CFStringRef) @"", kSecCSDefaultFlags,
104 &diskRequirement);
105 if (SecCodeCheckValidity(diskStaticCode, kSecCSDefaultFlags,
106 diskRequirement) != errSecSuccess) {
107 NSLog(@"verification failed");
108 }
109
110 NSString* path = @"/usr/bin/hdiutil";
111 NSArray* args = @[
112 @"attach", temporaryDiskImageURL, @"-nobrowse", @"-noverify",
113 @"-mountpoint", mountPath_
114 ];
115
116 NSTask* mountTask = [[NSTask alloc] init];
117 mountTask.launchPath = path;
118 mountTask.arguments = args;
119 mountTask.terminationHandler = ^void(NSTask* task) {
120 NSError* error = nil;
121 NSString* diskAppPath =
122 [NSString pathWithComponents:@[ mountPath_, @"Google Chrome.app" ]];
123 NSString* tempAppPath = [[temporaryDirectoryURL_
124 URLByAppendingPathComponent:@"Google Chrome.app"] path];
125 [[NSFileManager defaultManager] copyItemAtPath:diskAppPath
126 toPath:tempAppPath
127 error:&error];
128 if (error) {
129 [delegate_ unpacker:self onMountFailure:error];
130 } else {
131 [delegate_ unpacker:self onMountSuccess:tempAppPath];
132 }
133 };
134 mountTask_ = mountTask;
135 [mountTask launch];
136 }
137
138 // TODO: make this immediately follow from mount and copy
139 // on unpack success / on unpack failure / on cleanup completion
140
141 - (void)unmountDMG {
142 session_ = DASessionCreate(nil);
143 unpack_dq_ =
144 dispatch_queue_create("com.google.chrome.unpack", DISPATCH_QUEUE_SERIAL);
145 DASessionSetDispatchQueue(session_, unpack_dq_);
146 DADiskRef child_disk = DADiskCreateFromVolumePath(
147 nil, session_,
148 (CFURLRef)[NSURL fileURLWithPath:mountPath_ isDirectory:YES]);
149 DADiskRef whole_disk = DADiskCopyWholeDisk(child_disk);
150
151 DADiskUnmount(whole_disk,
152 kDADiskUnmountOptionWhole | kDADiskUnmountOptionForce,
153 unmount_callback, (void*)self);
154
155 CFRelease(whole_disk);
156 CFRelease(child_disk);
157 }
158
159 - (void)didFinishEjectingDisk:(DADiskRef)disk
160 withDissenter:(DADissenterRef)dissenter {
161 DASessionSetDispatchQueue(session_, NULL);
162 dispatch_release(unpack_dq_);
163 CFRelease(session_);
164 NSError* error = nil;
165 if (dissenter) {
166 DAReturn status = DADissenterGetStatus(dissenter);
167 error = [NSError
168 errorWithDomain:@"ChromeErrorDomain"
169 code:err_get_code(status)
170 userInfo:@{
171 NSLocalizedDescriptionKey :
172 (__bridge NSString*)DADissenterGetStatusString(dissenter)
173 }];
174 [delegate_ unpacker:self onUnmountFailure:error];
175 } else {
176 [self cleanUp];
177 if (error) {
178 [delegate_ unpacker:self onUnmountFailure:error];
179 } else {
180 [delegate_ unpacker:self onUnmountSuccess:mountPath_];
181 }
182 }
183 }
184
185 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698