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

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: Resolved comments, made many minor changes, ready for review! 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 #import <AppKit/AppKit.h>
8 #include <DiskArbitration/DiskArbitration.h>
9 #include <dispatch/dispatch.h>
10
11 #import "Downloader.h"
12
13 @interface Unpacker () {
14 NSURL* temporaryDirectoryURL_;
15 NSString* mountPath_;
16
17 NSTask* __weak mountTask_;
18
19 DASessionRef session_;
20 dispatch_queue_t unpack_dq_;
21 }
22 - (void)didFinishEjectingDisk:(DADiskRef)disk
23 withDissenter:(DADissenterRef)dissenter;
24 @end
25
26 static void eject_callback(DADiskRef disk,
27 DADissenterRef dissenter,
28 void* context) {
29 Unpacker* unpacker = (__bridge Unpacker*)context;
30 [unpacker didFinishEjectingDisk:disk withDissenter:dissenter];
31 }
32
33 static void unmount_callback(DADiskRef disk,
34 DADissenterRef dissenter,
35 void* context) {
36 if (dissenter) {
37 Unpacker* unpacker = (__bridge Unpacker*)context;
38 [unpacker didFinishEjectingDisk:disk withDissenter:dissenter];
39 } else {
40 DADiskEject(disk, kDADiskEjectOptionDefault, eject_callback, context);
41 }
42 }
43
44 @implementation Unpacker
45
46 @synthesize delegate = delegate_;
47 @synthesize appPath = appPath_;
48
49 - (void)cleanUp {
50 [mountTask_ terminate];
51 // It's not the end of the world if this temporary directory is not removed
52 // here. It will be deleted when the operating system itself decides to
53 // anyway.
54 [[NSFileManager defaultManager] removeItemAtURL:temporaryDirectoryURL_
55 error:nil];
56 [[NSNotificationCenter defaultCenter] removeObserver:self];
57 }
58
59 // TODO: the failure delegate methods need to be revised to be more meaningfully
60 // deal with the errors (pipe in stderr / stdout)
61 - (void)mountDMGFromURL:(NSURL*)fileURL {
62 NSError* error = nil;
63 temporaryDirectoryURL_ = [[NSFileManager defaultManager]
64 URLForDirectory:NSItemReplacementDirectory
65 inDomain:NSUserDomainMask
66 appropriateForURL:[NSURL fileURLWithPath:@"/" isDirectory:YES]
67 create:YES
68 error:&error];
69 if (error) {
70 [delegate_ unpacker:self onMountFailure:error];
71 return;
72 }
73
74 NSURL* temporaryDiskImageURL =
75 [temporaryDirectoryURL_ URLByAppendingPathComponent:@"GoogleChrome.dmg"];
76 mountPath_ = [[temporaryDirectoryURL_ URLByAppendingPathComponent:@"mnt"
77 isDirectory:YES] path];
78 [[NSFileManager defaultManager] createDirectoryAtPath:mountPath_
79 withIntermediateDirectories:YES
80 attributes:nil
81 error:&error];
82 if (error) {
83 [delegate_ unpacker:self onMountFailure:error];
84 return;
85 }
86 [[NSNotificationCenter defaultCenter]
87 addObserver:self
88 selector:@selector(cleanUp)
89 name:NSApplicationWillTerminateNotification
90 object:nil];
91
92 [[NSFileManager defaultManager] moveItemAtURL:fileURL
93 toURL:temporaryDiskImageURL
94 error:nil];
95
96 NSString* path = @"/usr/bin/hdiutil";
97 NSArray* args = @[
98 @"attach", temporaryDiskImageURL, @"-nobrowse", @"-noverify",
99 @"-mountpoint", mountPath_
100 ];
101
102 NSTask* mountTask = [[NSTask alloc] init];
103 mountTask.launchPath = path;
104 mountTask.arguments = args;
105 mountTask.terminationHandler = ^void(NSTask* task) {
106 [delegate_ unpacker:self onMountSuccess:mountPath_];
107 };
108 mountTask_ = mountTask;
109 [mountTask launch];
110 }
111
112 - (void)unmountDMG {
113 session_ = DASessionCreate(nil);
114 unpack_dq_ =
115 dispatch_queue_create("com.google.chrome.unpack", DISPATCH_QUEUE_SERIAL);
116 DASessionSetDispatchQueue(session_, unpack_dq_);
117 DADiskRef child_disk = DADiskCreateFromVolumePath(
118 nil, session_,
119 (CFURLRef)[NSURL fileURLWithPath:mountPath_ isDirectory:YES]);
120 DADiskRef whole_disk = DADiskCopyWholeDisk(child_disk);
121
122 DADiskUnmount(whole_disk,
123 kDADiskUnmountOptionWhole | kDADiskUnmountOptionForce,
124 unmount_callback, (void*)self);
125
126 CFRelease(whole_disk);
127 CFRelease(child_disk);
128 }
129
130 - (void)didFinishEjectingDisk:(DADiskRef)disk
131 withDissenter:(DADissenterRef)dissenter {
132 DASessionSetDispatchQueue(session_, NULL);
133 dispatch_release(unpack_dq_);
134 CFRelease(session_);
135 NSError* error = nil;
136 if (dissenter) {
137 DAReturn status = DADissenterGetStatus(dissenter);
138 error = [NSError
139 errorWithDomain:@"ChromeErrorDomain"
140 code:err_get_code(status)
141 userInfo:@{
142 NSLocalizedDescriptionKey :
143 (__bridge NSString*)DADissenterGetStatusString(dissenter)
144 }];
145 [delegate_ unpacker:self onUnmountFailure:error];
146 } else {
147 [self cleanUp];
148 if (error) {
149 [delegate_ unpacker:self onUnmountFailure:error];
150 } else {
151 [delegate_ unpacker:self onUnmountSuccess:mountPath_];
152 }
153 }
154 }
155
156 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698