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

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 DMG to build file 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
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_transfer 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
87 // If the user closes the app at any time, we make sure that the cleanUp
88 // function deletes the temporary folder we just created.
89 [[NSNotificationCenter defaultCenter]
90 addObserver:self
91 selector:@selector(cleanUp)
92 name:NSApplicationWillTerminateNotification
93 object:nil];
94
95 [[NSFileManager defaultManager] moveItemAtURL:fileURL
96 toURL:temporaryDiskImageURL
97 error:nil];
98
99 NSString* path = @"/usr/bin/hdiutil";
100 NSArray* args = @[
101 @"attach", temporaryDiskImageURL, @"-nobrowse", @"-noverify",
102 @"-mountpoint", mountPath_
103 ];
104
105 NSTask* mountTask = [[NSTask alloc] init];
106 mountTask.launchPath = path;
107 mountTask.arguments = args;
108 mountTask.terminationHandler = ^void(NSTask* task) {
109 NSError* error = nil;
110 NSString* diskAppPath =
111 [NSString pathWithComponents:@[ mountPath_, @"Google Chrome.app" ]];
112 NSString* tempAppPath = [[temporaryDirectoryURL_
113 URLByAppendingPathComponent:@"Google Chrome.app"] path];
114 [[NSFileManager defaultManager] copyItemAtPath:diskAppPath
115 toPath:tempAppPath
116 error:&error];
117 if (error) {
118 [delegate_ unpacker:self onMountFailure:error];
119 } else {
120 [delegate_ unpacker:self onMountSuccess:tempAppPath];
121 }
122 };
123 mountTask_ = mountTask;
124 [mountTask launch];
125 }
126
127 - (void)unmountDMG {
128 session_ = DASessionCreate(nil);
129 unpack_dq_ =
130 dispatch_queue_create("com.google.chrome.unpack", DISPATCH_QUEUE_SERIAL);
131 DASessionSetDispatchQueue(session_, unpack_dq_);
132 DADiskRef child_disk = DADiskCreateFromVolumePath(
133 nil, session_,
134 (__bridge CFURLRef)[NSURL fileURLWithPath:mountPath_ isDirectory:YES]);
135 DADiskRef whole_disk = DADiskCopyWholeDisk(child_disk);
136
137 DADiskUnmount(whole_disk,
138 kDADiskUnmountOptionWhole | kDADiskUnmountOptionForce,
139 unmount_callback, (__bridge_retained void*)self);
140
141 CFRelease(whole_disk);
142 CFRelease(child_disk);
143 }
144
145 - (void)didFinishEjectingDisk:(DADiskRef)disk
146 withDissenter:(DADissenterRef)dissenter {
147 DASessionSetDispatchQueue(session_, NULL);
148 dispatch_release(unpack_dq_);
149 CFRelease(session_);
150 NSError* error = nil;
151 if (dissenter) {
152 DAReturn status = DADissenterGetStatus(dissenter);
153 error = [NSError
154 errorWithDomain:@"ChromeErrorDomain"
155 code:err_get_code(status)
156 userInfo:@{
157 NSLocalizedDescriptionKey :
158 (__bridge NSString*)DADissenterGetStatusString(dissenter)
159 }];
160 [delegate_ unpacker:self onUnmountFailure:error];
161 } else {
162 [self cleanUp];
163 [delegate_ unpacker:self onUnmountSuccess:mountPath_];
164 }
165 }
166
167 @end
OLDNEW
« no previous file with comments | « chrome/installer/mac/app/Unpacker.h ('k') | chrome/installer/mac/app/testing/OmahaXMLRequest_test.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698