Fix a crash when setting clipboardData to null on iOS (flutter/engine#32413)

This commit is contained in:
Chris Yang 2022-04-04 19:11:04 -07:00 committed by GitHub
parent 9710156fe2
commit ede2fb5e11
2 changed files with 53 additions and 18 deletions

View File

@ -267,8 +267,9 @@ using namespace flutter;
- (void)setClipboardData:(NSDictionary*)data {
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
if (data[@"text"]) {
pasteboard.string = data[@"text"];
id copyText = data[@"text"];
if ([copyText isKindOfClass:[NSString class]]) {
pasteboard.string = copyText;
} else {
pasteboard.string = @"null";
}

View File

@ -16,37 +16,71 @@
@implementation FlutterPlatformPluginTest
- (void)testHasStrings {
- (void)testClipboardHasCorrectStrings {
[UIPasteboard generalPasteboard].string = nil;
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
std::unique_ptr<fml::WeakPtrFactory<FlutterEngine>> _weakFactory =
std::make_unique<fml::WeakPtrFactory<FlutterEngine>>(engine);
FlutterPlatformPlugin* plugin =
[[FlutterPlatformPlugin alloc] initWithEngine:_weakFactory->GetWeakPtr()];
// Set some string to the pasteboard.
__block bool calledSet = false;
XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setString"];
FlutterResult resultSet = ^(id result) {
calledSet = true;
[setStringExpectation fulfill];
};
FlutterMethodCall* methodCallSet =
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.setClipboardData"
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
arguments:@{@"text" : @"some string"}];
[plugin handleMethodCall:methodCallSet result:resultSet];
XCTAssertEqual(calledSet, true);
[self waitForExpectationsWithTimeout:1 handler:nil];
// Call hasStrings and expect it to be true.
__block bool called = false;
__block bool value;
XCTestExpectation* hasStringsExpectation = [self expectationWithDescription:@"hasStrings"];
FlutterResult result = ^(id result) {
called = true;
value = result[@"value"];
XCTAssertTrue([result[@"value"] boolValue]);
[hasStringsExpectation fulfill];
};
FlutterMethodCall* methodCall =
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:nil];
[plugin handleMethodCall:methodCall result:result];
[self waitForExpectationsWithTimeout:1 handler:nil];
XCTAssertEqual(called, true);
XCTAssertEqual(value, true);
XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
FlutterResult getDataResult = ^(id result) {
XCTAssertEqualObjects(result[@"text"], @"some string");
[getDataExpectation fulfill];
};
FlutterMethodCall* methodCallGetData =
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData" arguments:@"text/plain"];
[plugin handleMethodCall:methodCallGetData result:getDataResult];
[self waitForExpectationsWithTimeout:1 handler:nil];
}
- (void)testClipboardSetDataToNullDoNotCrash {
[UIPasteboard generalPasteboard].string = nil;
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
std::unique_ptr<fml::WeakPtrFactory<FlutterEngine>> _weakFactory =
std::make_unique<fml::WeakPtrFactory<FlutterEngine>>(engine);
FlutterPlatformPlugin* plugin =
[[FlutterPlatformPlugin alloc] initWithEngine:_weakFactory->GetWeakPtr()];
XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setData"];
FlutterResult resultSet = ^(id result) {
[setStringExpectation fulfill];
};
FlutterMethodCall* methodCallSet =
[FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
arguments:@{@"text" : [NSNull null]}];
[plugin handleMethodCall:methodCallSet result:resultSet];
XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
FlutterResult result = ^(id result) {
XCTAssertEqualObjects(result[@"text"], @"null");
[getDataExpectation fulfill];
};
FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData"
arguments:@"text/plain"];
[plugin handleMethodCall:methodCall result:result];
[self waitForExpectationsWithTimeout:1 handler:nil];
}
- (void)testPopSystemNavigator {
@ -66,14 +100,14 @@
id navigationControllerMock = OCMPartialMock(navigationController);
OCMStub([navigationControllerMock popViewControllerAnimated:YES]);
// Set some string to the pasteboard.
__block bool calledSet = false;
XCTestExpectation* navigationPopCalled = [self expectationWithDescription:@"SystemNavigator.pop"];
FlutterResult resultSet = ^(id result) {
calledSet = true;
[navigationPopCalled fulfill];
};
FlutterMethodCall* methodCallSet =
[FlutterMethodCall methodCallWithMethodName:@"SystemNavigator.pop" arguments:@(YES)];
[plugin handleMethodCall:methodCallSet result:resultSet];
XCTAssertEqual(calledSet, true);
[self waitForExpectationsWithTimeout:1 handler:nil];
OCMVerify([navigationControllerMock popViewControllerAnimated:YES]);
}