[macOS,iOS] Expose channel buffers 'resize' and 'overflow' control co… (flutter/engine#44848)

## Description

This PR update the helper function that invokes the control channel 'resize' command (previous implementation relied on a deprecated format). It also adds a similar helper function for the 'overflow' commands exposed by the control channel.

See:

c00c022036/lib/ui/channel_buffers.dart (L302-L309)

## Related Issue

iOS and macOS implementation for https://github.com/flutter/flutter/issues/132386

Similar implementations:
- Android: https://github.com/flutter/engine/pull/44434
- Linux: https://github.com/flutter/engine/pull/44636

## Tests

Adds two tests.
This commit is contained in:
Bruno Leroux 2023-09-19 11:40:18 +02:00 committed by GitHub
parent d9a3f74eec
commit 195a313245
3 changed files with 117 additions and 7 deletions

View File

@ -143,9 +143,46 @@ FLUTTER_DARWIN_EXPORT
* Adjusts the number of messages that will get buffered when sending messages to
* channels that aren't fully set up yet. For example, the engine isn't running
* yet or the channel's message handler isn't set up on the Dart side yet.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param newSize The number of messages that will get buffered.
*/
+ (void)resizeChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
size:(NSInteger)newSize;
/**
* Adjusts the number of messages that will get buffered when sending messages to
* channels that aren't fully set up yet. For example, the engine isn't running
* yet or the channel's message handler isn't set up on the Dart side yet.
*
* @param newSize The number of messages that will get buffered.
*/
- (void)resizeChannelBuffer:(NSInteger)newSize;
/**
* Defines whether the channel should show warning messages when discarding messages
* due to overflow.
*
* @param warns When false, the channel is expected to overflow and warning messages
* will not be shown.
* @param name The channel name.
* @param messenger The binary messenger.
*/
+ (void)setWarnsOnOverflow:(BOOL)warns
forChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Defines whether the channel should show warning messages when discarding messages
* due to overflow.
*
* @param warns When false, the channel is expected to overflow and warning messages
* will not be shown.
*/
- (void)setWarnsOnOverflow:(BOOL)warns;
@end
/**

View File

@ -9,12 +9,41 @@ FLUTTER_ASSERT_ARC
#pragma mark - Basic message channel
static NSString* const kFlutterChannelBuffersChannel = @"dev.flutter/channel-buffers";
static NSString* const kResizeMethod = @"resize";
static NSString* const kOverflowMethod = @"overflow";
static void ResizeChannelBuffer(NSObject<FlutterBinaryMessenger>* binaryMessenger,
NSString* channel,
NSInteger newSize) {
NSString* messageString = [NSString stringWithFormat:@"resize\r%@\r%@", channel, @(newSize)];
NSData* message = [messageString dataUsingEncoding:NSUTF8StringEncoding];
NSCAssert(newSize >= 0, @"Channel buffer size must be non-negative");
// Cast newSize to int because the deserialization logic handles only 32 bits values,
// see
// https://github.com/flutter/engine/blob/93e8901490e78c7ba7e319cce4470d9c6478c6dc/lib/ui/channel_buffers.dart#L495.
NSArray* args = @[ channel, @(static_cast<int>(newSize)) ];
FlutterMethodCall* resizeMethodCall = [FlutterMethodCall methodCallWithMethodName:kResizeMethod
arguments:args];
NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
NSData* message = [codec encodeMethodCall:resizeMethodCall];
[binaryMessenger sendOnChannel:kFlutterChannelBuffersChannel message:message];
}
/**
* Defines whether a channel should show warning messages when discarding messages
* due to overflow.
*
* @param binaryMessenger The binary messenger.
* @param channel The channel name.
* @param warns When false, the channel is expected to overflow and warning messages
* will not be shown.
*/
static void SetWarnsOnOverflow(NSObject<FlutterBinaryMessenger>* binaryMessenger,
NSString* channel,
BOOL warns) {
FlutterMethodCall* overflowMethodCall =
[FlutterMethodCall methodCallWithMethodName:kOverflowMethod
arguments:@[ channel, @(!warns) ]];
NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
NSData* message = [codec encodeMethodCall:overflowMethodCall];
[binaryMessenger sendOnChannel:kFlutterChannelBuffersChannel message:message];
}
@ -114,10 +143,26 @@ static FlutterBinaryMessengerConnection SetMessageHandler(
_connection = SetMessageHandler(_messenger, _name, messageHandler, _taskQueue);
}
+ (void)resizeChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
size:(NSInteger)newSize {
ResizeChannelBuffer(messenger, name, newSize);
}
- (void)resizeChannelBuffer:(NSInteger)newSize {
ResizeChannelBuffer(_messenger, _name, newSize);
}
+ (void)setWarnsOnOverflow:(BOOL)warns
forChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
SetWarnsOnOverflow(messenger, name, warns);
}
- (void)setWarnsOnOverflow:(BOOL)warns {
SetWarnsOnOverflow(_messenger, _name, warns);
}
@end
#pragma mark - Method channel

View File

@ -147,7 +147,7 @@ FLUTTER_ASSERT_ARC
}
- (void)testResize {
NSString* channelName = @"foo";
NSString* channelName = @"flutter/test";
id binaryMessenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
FlutterBasicMessageChannel* channel =
@ -156,11 +156,39 @@ FLUTTER_ASSERT_ARC
codec:codec];
XCTAssertNotNil(channel);
NSString* expectedMessageString =
[NSString stringWithFormat:@"resize\r%@\r%@", channelName, @100];
NSData* expectedMessage = [expectedMessageString dataUsingEncoding:NSUTF8StringEncoding];
// The expected content was created from the following Dart code:
// MethodCall call = MethodCall('resize', ['flutter/test',3]);
// StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
const unsigned char bytes[] = {7, 6, 114, 101, 115, 105, 122, 101, 12, 2,
7, 12, 102, 108, 117, 116, 116, 101, 114, 47,
116, 101, 115, 116, 3, 3, 0, 0, 0};
NSData* expectedMessage = [NSData dataWithBytes:bytes length:sizeof(bytes)];
OCMExpect([binaryMessenger sendOnChannel:@"dev.flutter/channel-buffers" message:expectedMessage]);
[channel resizeChannelBuffer:100];
[channel resizeChannelBuffer:3];
OCMVerifyAll(binaryMessenger);
[binaryMessenger stopMocking];
}
- (bool)testSetWarnsOnOverflow {
NSString* channelName = @"flutter/test";
id binaryMessenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
id codec = OCMProtocolMock(@protocol(FlutterMethodCodec));
FlutterBasicMessageChannel* channel =
[[FlutterBasicMessageChannel alloc] initWithName:channelName
binaryMessenger:binaryMessenger
codec:codec];
XCTAssertNotNil(channel);
// The expected content was created from the following Dart code:
// MethodCall call = MethodCall('overflow',['flutter/test', true]);
// StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
const unsigned char bytes[] = {7, 8, 111, 118, 101, 114, 102, 108, 111, 119, 12, 2, 7, 12,
102, 108, 117, 116, 116, 101, 114, 47, 116, 101, 115, 116, 1};
NSData* expectedMessage = [NSData dataWithBytes:bytes length:sizeof(bytes)];
OCMExpect([binaryMessenger sendOnChannel:@"dev.flutter/channel-buffers" message:expectedMessage]);
[channel setWarnsOnOverflow:NO];
OCMVerifyAll(binaryMessenger);
[binaryMessenger stopMocking];
}