File: CRURegistration-Private.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (191 lines) | stat: -rw-r--r-- 7,679 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// CRURegistration-Private contains declarations of CRURegistration
// implementation details that need unit testing.

#ifndef CHROME_UPDATER_MAC_CLIENT_LIB_CRUREGISTRATION_PRIVATE_H_
#define CHROME_UPDATER_MAC_CLIENT_LIB_CRUREGISTRATION_PRIVATE_H_

#import <Foundation/Foundation.h>

#import "CRURegistration.h"

NS_ASSUME_NONNULL_BEGIN

extern NSString* const CRUReturnCodeErrorDomain;

typedef NS_ERROR_ENUM(CRURegistrationInternalErrorDomain,
                      CRURegistrationInternalError){
    CRURegistrationInternalErrorTaskAlreadyLaunched = 1,

    // An underlying API that can fail returned an error that we did not
    // specifically anticipate.
    CRURegistrationInternalErrorUnrecognized = 9999,
};

/***
 * CRUTaskResultCallback is a block receiving the result of an NSTask
 * invocation.
 *
 * Parameters:
 *  NSString* -- all stdout content, nil if the process never launched.
 *  NSString* -- all stderr content. nil if the process never launched.
 *  NSError* -- return value of the process.
 *      * nil: the process ran and returned zero
 *      * error domain is CRUReturnCodeErrorDomain: process ran and returned
 *      nonzero; error code
 *          is the return value. NSData* arguments will be nonnil.
 *      * any other error domain: the task could not be launched; this is the
 *      error from NSTask or
 *          is in CRURegistrationErrorDomain. NSData* elements will be nil.
 */
typedef void (^CRUTaskResultCallback)(NSString* _Nullable,
                                      NSString* _Nullable,
                                      NSError* _Nullable);

@class CRURegistrationWorkItem;  // break circular reference
/***
 * CRUNextTaskCallback is similar to CRUTaskResultCallback, but it is run
 * synchronously by the work queue and may return a new work item to perform
 * next, preempting any other queued task. The current work item (that has just
 * completed or failed its task) is provided to the callback to make it easier
 * to avoid dependency cycles.
 *
 * Parameters:
 *  CRURegistrationWorkItem* -- the work item that just completed, which
 *      contained this block as its `onDone` callback.
 *  NSString* -- all stdout content, nil if the process never launched.
 *  NSString* -- all stderr content. nil if the process never launched.
 *  NSError* -- return value of the process.
 *      * nil: the process ran and returned zero
 *      * error domain is CRUReturnCodeErrorDomain: process ran and returned
 *      nonzero; error code
 *          is the return value. NSData* arguments will be nonnil.
 *      * any other error domain: the task could not be launched; this is the
 *      error from NSTask or
 *          is in CRURegistrationErrorDomain. NSData* elements will be nil.
 */
typedef CRURegistrationWorkItem* _Nullable (^CRUNextTaskCallback)(
    CRURegistrationWorkItem*,
    NSString* _Nullable,
    NSString* _Nullable,
    NSError* _Nullable);

/**
 * CRUAsyncTaskRunner runs an NSTask and asynchronously accumulates its stdout
 * and stderr streams into NSMutableData buffers.
 */
@interface CRUAsyncTaskRunner : NSObject

- (instancetype)initWithTask:(NSTask*)task
                 targetQueue:(dispatch_queue_t)targetQueue
    NS_DESIGNATED_INITIALIZER;

- (instancetype)init NS_UNAVAILABLE;

/**
 * launchWithReply launches the task and buffers its output. It calls `reply`
 * with the results of the task when the task completes. If the task cannot
 * be launched, it invokes `reply` with nil NSString* args and the NSError* from
 * NSTask's launch failure.
 */
- (void)launchWithReply:(CRUTaskResultCallback)reply;

@end

/**
 * CRURegistrationWorkItem represents a task to be constructed and invoked.
 *
 * It is plain data represented as an Objective-C class (instead of a struct)
 * so it can be contained in an NSMutableArray.
 */
@interface CRURegistrationWorkItem : NSObject

/**
 * Callback returning the path of the binary to run. This is invoked immediately
 * before the path is needed to construct an NSTask.
 *
 * This is a callback because some work items -- notably, installing the updater
 * itself -- may affect where future work items should look for the binaries
 * they intend to run, so searching for them needs to be deferred until
 * prior tasks have completed.
 */
@property(nonatomic, copy) NSURL* (^binPathCallback)();

/**
 * Arguments to invoke the NSTask with.
 */
@property(nonatomic, copy) NSArray<NSString*>* args;

/**
 * Handler to asynchronously invoke with task results. This handler is
 * _not_ responsible for cycling the task queue.
 */
@property(nonatomic, copy) CRUTaskResultCallback resultCallback;

/**
 * Handler invoked synchronously with the task results, which has the
 * opportunity to preempt the next task or edit this CRURegistrationWorkItem
 * (for example, to change `resultCallback`) before `resultCallback` is
 * asynchronously invoked.
 */
@property(nonatomic, copy) CRUNextTaskCallback onDone;

@end

@interface CRURegistration (VisibleForTesting)

/**
 * Asynchronously add work items and, if the work queue is not currently being
 * processed, starts processing them. (If work is already in progress, these
 * items will be picked up by its continued execution.)
 */
- (void)addWorkItems:(NSArray<CRURegistrationWorkItem*>*)item;

/**
 * Synchronously finds the path to an installed KSAdmin binary. If a systemwide
 * ksadmin is available, it prefers it; otherwise, if a user ksadmin is
 * available, it returns that; if neither can be found, it returns nil.
 *
 * This does not depend on, or mutate, any protected state inside
 * CRURegistration itself, but does check filesystem state. If the updater is
 * concurrently being installed, it might not find it. This is intended for
 * use while CRURegistration is not concurrently running a task.
 */
- (nullable NSURL*)syncFindBestKSAdmin;

/**
 * Wrap an NSError from a failed attempt to run a task with a semantically
 * appropriate domain and code. If the error is an intended part of the library
 * API, it will be in CRURegistrationErrorDomain; otherwise, it represents a
 * library bug that the user should, ideally, not rely on and will be wrapped
 * under CRURegistrationInternalErrorDomain.
 *
 * Errors already in one of these two error domains are returned unchanged.
 * Nil is also returned unchanged. Otherwise:
 * - errors representing nonzero return codes from tasks are converted to
 *   CRURegistrationErrorTaskFailed
 * - "file not found" errors from Apple APIs are assumed to be NSTask failing
 *   to find a binary and are converted to CRURegistrationErrorHelperNotFound
 * - other errors are unexpected
 *
 * If the returned error is not the same as the input error, the result error's
 * `userInfo` dictionary contains a value under `NSUnderlyingErrorKey` with the
 * original error unchanged. A wrapped error's `userInfo` also contains the
 * values of `gotStdout` and `gotStderr` under `CRUStdoutKey` and `CRUStderrKey`
 * respectively. Values in `userInfo` are intended to assist with debugging, but
 * production code should not rely on these values for identifying and handling
 * the disposition of an error; file bugs against this library if more detail
 * is required than is available, or if any internal error is encountered.
 */
- (nullable NSError*)wrapError:(nullable NSError*)error
                    withStdout:(nullable NSString*)gotStdout
                     andStderr:(nullable NSString*)gotStderr;

@end

NS_ASSUME_NONNULL_END

#endif  // CHROME_UPDATER_MAC_CLIENT_LIB_CRUREGISTRATION_PRIVATE_H_