Skip to content

Commit ea8f195

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Move shared callback bridge functionality to MTRCallbackBridgeBase. (#24738)
Also eliminates the last direct (and hence not interceptible by API consumers) NSLog calls in the Darwin framework and adds a lint for those. Fixes #23597
1 parent 9a05cf5 commit ea8f195

File tree

2 files changed

+105
-82
lines changed

2 files changed

+105
-82
lines changed

.github/workflows/lint.yml

+7
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,10 @@ jobs:
181181
if: always()
182182
run: |
183183
git grep -n '0x%[0-9-]*" *PRI[^xX]' -- './*' ':(exclude).github/workflows/lint.yml' && exit 1 || exit 0
184+
185+
# git grep exits with 0 if it finds a match, but we want
186+
# to fail (exit nonzero) on match.
187+
- name: Check for use of NSLog instead of Matter logging in Matter framework
188+
if: always()
189+
run: |
190+
git grep -n 'NSLog(' -- src/darwin/Framework/CHIP && exit 1 || exit 0

src/darwin/Framework/CHIP/MTRCallbackBridgeBase.h

+98-82
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,92 @@ NS_ASSUME_NONNULL_BEGIN
3535
* know.
3636
*/
3737
class MTRCallbackBridgeBase {
38+
public:
39+
/**
40+
* Run the given MTRActionBlock on the Matter thread, after getting a CASE
41+
* session (possibly pre-existing) to the given node ID on the fabric
42+
* represented by the given MTRDeviceController. On success, convert the
43+
* success value to whatever type it needs to be to call the callback type
44+
* we're templated over. Once this function has been called, on a callback
45+
* bridge allocated with `new`, the bridge object must not be accessed by
46+
* the caller. The action block will handle deleting the bridge.
47+
*/
48+
void DispatchAction(chip::NodeId nodeID, MTRDeviceController * controller) && { ActionWithNodeID(nodeID, controller); }
49+
50+
/**
51+
* Run the given MTRActionBlock on the Matter thread after getting a secure
52+
* session corresponding to the given MTRBaseDevice. On success, convert
53+
* the success value to whatever type it needs to be to call the callback
54+
* type we're templated over. Once this function has been called, on a callback
55+
* bridge allocated with `new`, the bridge object must not be accessed by
56+
* the caller. The action block will handle deleting the bridge.
57+
*/
58+
void DispatchAction(MTRBaseDevice * device) &&
59+
{
60+
if (device.isPASEDevice) {
61+
ActionWithPASEDevice(device);
62+
} else {
63+
ActionWithNodeID(device.nodeID, device.deviceController);
64+
}
65+
}
66+
67+
protected:
68+
MTRCallbackBridgeBase(dispatch_queue_t queue)
69+
: mQueue(queue)
70+
{
71+
}
72+
73+
virtual ~MTRCallbackBridgeBase() {};
74+
75+
virtual void MaybeDoAction(chip::Messaging::ExchangeManager * _Nullable exchangeManager,
76+
const chip::Optional<chip::SessionHandle> & session, NSError * _Nullable error)
77+
= 0;
78+
virtual void LogRequestStart() = 0;
79+
80+
void ActionWithPASEDevice(MTRBaseDevice * device)
81+
{
82+
LogRequestStart();
83+
84+
[device.deviceController getSessionForCommissioneeDevice:device.nodeID
85+
completion:^(chip::Messaging::ExchangeManager * exchangeManager,
86+
const chip::Optional<chip::SessionHandle> & session, NSError * error) {
87+
MaybeDoAction(exchangeManager, session, error);
88+
}];
89+
}
90+
91+
void ActionWithNodeID(chip::NodeId nodeID, MTRDeviceController * controller)
92+
{
93+
LogRequestStart();
94+
95+
[controller getSessionForNode:nodeID
96+
completion:^(chip::Messaging::ExchangeManager * exchangeManager,
97+
const chip::Optional<chip::SessionHandle> & session, NSError * error) {
98+
MaybeDoAction(exchangeManager, session, error);
99+
}];
100+
}
101+
102+
// OnDone and KeepAliveOnCallback really only make sense for subscription
103+
// bridges, but we put them here to avoid many copies of this code in
104+
// generated bits.
105+
void OnDone()
106+
{
107+
if (!mQueue) {
108+
delete this;
109+
return;
110+
}
111+
112+
// Delete ourselves async, so that any error/data reports we
113+
// queued up before getting OnDone have a chance to run.
114+
auto * self = this;
115+
dispatch_async(mQueue, ^{
116+
delete self;
117+
});
118+
}
119+
120+
void KeepAliveOnCallback() { mKeepAlive = true; }
121+
122+
dispatch_queue_t mQueue;
123+
bool mKeepAlive = false;
38124
};
39125

40126
typedef void (^MTRResponseHandler)(id _Nullable value, NSError * _Nullable error);
@@ -72,7 +158,7 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
72158
* on it.
73159
*/
74160
MTRCallbackBridge(dispatch_queue_t queue, MTRResponseHandler handler, T OnSuccessFn)
75-
: mQueue(queue)
161+
: MTRCallbackBridgeBase(queue)
76162
, mHandler(handler)
77163
, mSuccess(OnSuccessFn)
78164
, mFailure(OnFailureFn)
@@ -84,42 +170,14 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
84170
* on it.
85171
*/
86172
MTRCallbackBridge(dispatch_queue_t queue, MTRResponseHandler handler, MTRActionBlock _Nonnull action, T OnSuccessFn)
87-
: mQueue(queue)
173+
: MTRCallbackBridgeBase(queue)
88174
, mHandler(handler)
89175
, mAction(action)
90176
, mSuccess(OnSuccessFn)
91177
, mFailure(OnFailureFn)
92178
{
93179
}
94180

95-
/**
96-
* Run the given MTRActionBlock on the Matter thread, after getting a CASE
97-
* session (possibly pre-existing) to the given node ID on the fabric
98-
* represented by the given MTRDeviceController. On success, convert the
99-
* success value to whatever type it needs to be to call the callback type
100-
* we're templated over. Once this function has been called, on a callback
101-
* bridge allocated with `new`, the bridge object must not be accessed by
102-
* the caller. The action block will handle deleting the bridge.
103-
*/
104-
void DispatchAction(chip::NodeId nodeID, MTRDeviceController * controller) && { ActionWithNodeID(nodeID, controller); }
105-
106-
/**
107-
* Run the given MTRActionBlock on the Matter thread after getting a secure
108-
* session corresponding to the given MTRBaseDevice. On success, convert
109-
* the success value to whatever type it needs to be to call the callback
110-
* type we're templated over. Once this function has been called, on a callback
111-
* bridge allocated with `new`, the bridge object must not be accessed by
112-
* the caller. The action block will handle deleting the bridge.
113-
*/
114-
void DispatchAction(MTRBaseDevice * device) &&
115-
{
116-
if (device.isPASEDevice) {
117-
ActionWithPASEDevice(device);
118-
} else {
119-
ActionWithNodeID(device.nodeID, device.deviceController);
120-
}
121-
}
122-
123181
/**
124182
* Try to run the given MTRLocalActionBlock on the Matter thread, if we have
125183
* a device and it's attached to a running controller, then handle
@@ -142,8 +200,8 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
142200
asyncDispatchToMatterQueue:^() {
143201
CHIP_ERROR err = action(mSuccess, mFailure);
144202
if (err != CHIP_NO_ERROR) {
145-
NSLog(@"Failure performing action. C++-mangled success callback type: '%s', error: %s", typeid(T).name(),
146-
chip::ErrorStr(err));
203+
ChipLogError(Controller, "Failure performing action. C++-mangled success callback type: '%s', error: %s",
204+
typeid(T).name(), chip::ErrorStr(err));
147205

148206
// Take the normal async error-reporting codepath. This will also
149207
// handle cleaning us up properly.
@@ -155,29 +213,7 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
155213
}];
156214
}
157215

158-
void ActionWithPASEDevice(MTRBaseDevice * device)
159-
{
160-
LogRequestStart();
161-
162-
[device.deviceController getSessionForCommissioneeDevice:device.nodeID
163-
completion:^(chip::Messaging::ExchangeManager * exchangeManager,
164-
const chip::Optional<chip::SessionHandle> & session, NSError * error) {
165-
MaybeDoAction(exchangeManager, session, error);
166-
}];
167-
}
168-
169-
void ActionWithNodeID(chip::NodeId nodeID, MTRDeviceController * controller)
170-
{
171-
LogRequestStart();
172-
173-
[controller getSessionForNode:nodeID
174-
completion:^(chip::Messaging::ExchangeManager * exchangeManager,
175-
const chip::Optional<chip::SessionHandle> & session, NSError * error) {
176-
MaybeDoAction(exchangeManager, session, error);
177-
}];
178-
}
179-
180-
void LogRequestStart()
216+
void LogRequestStart() override
181217
{
182218
mRequestTime = [NSDate date];
183219
// Generate a unique cookie to track this operation
@@ -186,7 +222,7 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
186222
}
187223

188224
void MaybeDoAction(chip::Messaging::ExchangeManager * _Nullable exchangeManager,
189-
const chip::Optional<chip::SessionHandle> & session, NSError * _Nullable error)
225+
const chip::Optional<chip::SessionHandle> & session, NSError * _Nullable error) override
190226
{
191227
// Make sure we don't hold on to our action longer than we have to.
192228
auto action = mAction;
@@ -198,8 +234,8 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
198234

199235
CHIP_ERROR err = action(*exchangeManager, session.Value(), mSuccess, mFailure, this);
200236
if (err != CHIP_NO_ERROR) {
201-
NSLog(@"Failure performing action. C++-mangled success callback type: '%s', error: %s", typeid(T).name(),
202-
chip::ErrorStr(err));
237+
ChipLogError(Controller, "Failure performing action. C++-mangled success callback type: '%s', error: %s",
238+
typeid(T).name(), chip::ErrorStr(err));
203239

204240
// Take the normal async error-reporting codepath. This will also
205241
// handle cleaning us up properly.
@@ -209,35 +245,13 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
209245

210246
virtual ~MTRCallbackBridge() {};
211247

248+
protected:
212249
static void OnFailureFn(void * context, CHIP_ERROR error) { DispatchFailure(context, [MTRError errorForCHIPErrorCode:error]); }
213250

214251
static void DispatchSuccess(void * context, id _Nullable value) { DispatchCallbackResult(context, nil, value); }
215252

216253
static void DispatchFailure(void * context, NSError * error) { DispatchCallbackResult(context, error, nil); }
217254

218-
protected:
219-
// OnDone and KeepAliveOnCallback really only make sense for subscription
220-
// bridges, but we put them here to avoid many copies of this code in
221-
// generated bits.
222-
void OnDone()
223-
{
224-
if (!mQueue) {
225-
delete this;
226-
return;
227-
}
228-
229-
// Delete ourselves async, so that any error/data reports we
230-
// queued up before getting OnDone have a chance to run.
231-
auto * self = this;
232-
dispatch_async(mQueue, ^{
233-
delete self;
234-
});
235-
}
236-
237-
void KeepAliveOnCallback() { mKeepAlive = true; }
238-
239-
dispatch_queue_t mQueue;
240-
241255
private:
242256
static void DispatchCallbackResult(void * context, NSError * _Nullable error, id _Nullable value)
243257
{
@@ -266,7 +280,9 @@ template <class T> class MTRCallbackBridge : public MTRCallbackBridgeBase {
266280

267281
MTRResponseHandler mHandler;
268282
MTRActionBlock _Nullable mAction;
269-
bool mKeepAlive = false;
283+
// Keep our subclasses from accessing mKeepAlive directly, by putting this
284+
// "using" in our private section.
285+
using MTRCallbackBridgeBase::mKeepAlive;
270286

271287
T mSuccess;
272288
MTRErrorCallback mFailure;

0 commit comments

Comments
 (0)