From e41fd62d4fb3c35e858a4749bd6eb9919d456181 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Sat, 21 Sep 2024 17:39:21 -0700 Subject: [PATCH 1/3] [iOS] sprinkle some null checks on BringLayersIntoView. --- .../ios/framework/Source/platform_views_controller.mm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm b/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm index 0ad4ad6ff5517..7f8a73294953c 100644 --- a/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm +++ b/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm @@ -797,13 +797,18 @@ bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, NSMutableArray* desired_platform_subviews = [NSMutableArray array]; for (int64_t platform_view_id : composition_order) { UIView* platform_view_root = platform_views_[platform_view_id].root_view.get(); - [desired_platform_subviews addObject:platform_view_root]; + if (platform_view_root != nil) { + [desired_platform_subviews addObject:platform_view_root]; + } auto maybe_layer_data = layer_map.find(platform_view_id); if (maybe_layer_data != layer_map.end()) { - [desired_platform_subviews addObject:maybe_layer_data->second.layer->overlay_view_wrapper]; + auto view = maybe_layer_data->second.layer->overlay_view_wrapper; + if (view != nil) { + [desired_platform_subviews addObject:view]; + previous_composition_order_.push_back(platform_view_id); + } } - previous_composition_order_.push_back(platform_view_id); } NSSet* desired_platform_subviews_set = [NSSet setWithArray:desired_platform_subviews]; From efbdbe0d78e91c16447a68c4f7bc84e0281a0fcc Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 23 Sep 2024 09:13:49 -0700 Subject: [PATCH 2/3] ++ --- .../Source/FlutterPlatformViewsTest.mm | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 07d2885c04410..d6a2421f33c51 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -83,6 +83,18 @@ @implementation FlutterPlatformViewsTestMockFlutterPlatformFactory @end +@interface FlutterPlatformViewsTestNilFlutterPlatformFactory : NSObject +@end + +@implementation FlutterPlatformViewsTestNilFlutterPlatformFactory +- (NSObject*)createWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args { + return nil; +} + +@end + namespace flutter { namespace { class FlutterPlatformViewsTestMockPlatformViewDelegate : public PlatformView::Delegate { @@ -3692,6 +3704,62 @@ - (void)testOnlyPlatformViewsAreRemovedWhenReset { XCTAssertEqual(flutterView.subviews.firstObject, someView); } +- (void)testNilPlatformViewDoesntCrash { + flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate; + + flutter::TaskRunners runners(/*label=*/self.name.UTF8String, + /*platform=*/GetDefaultTaskRunner(), + /*raster=*/GetDefaultTaskRunner(), + /*ui=*/GetDefaultTaskRunner(), + /*io=*/GetDefaultTaskRunner()); + auto flutterPlatformViewsController = std::make_shared(); + flutterPlatformViewsController->SetTaskRunner(GetDefaultTaskRunner()); + auto platform_view = std::make_unique( + /*delegate=*/mock_delegate, + /*rendering_api=*/mock_delegate.settings_.enable_impeller + ? flutter::IOSRenderingAPI::kMetal + : flutter::IOSRenderingAPI::kSoftware, + /*platform_views_controller=*/flutterPlatformViewsController, + /*task_runners=*/runners, + /*worker_task_runner=*/nil, + /*is_gpu_disabled_jsync_switch=*/std::make_shared()); + + FlutterPlatformViewsTestNilFlutterPlatformFactory* factory = + [[FlutterPlatformViewsTestNilFlutterPlatformFactory alloc] init]; + flutterPlatformViewsController->RegisterViewFactory( + factory, @"MockFlutterPlatformView", + FlutterPlatformViewGestureRecognizersBlockingPolicyEager); + FlutterResult result = ^(id result) { + }; + flutterPlatformViewsController->OnMethodCall( + [FlutterMethodCall + methodCallWithMethodName:@"create" + arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}], + result); + UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; + flutterPlatformViewsController->SetFlutterView(flutterView); + + flutter::MutatorsStack stack; + auto embeddedViewParams = + std::make_unique(finalMatrix, SkSize::Make(300, 300), stack); + + flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams)); + + // SKSurface is required if the root FlutterView is present. + const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000); + sk_sp mock_sk_surface = SkSurfaces::Raster(image_info); + flutter::SurfaceFrame::FramebufferInfo framebuffer_info; + auto mock_surface = std::make_unique( + std::move(mock_sk_surface), framebuffer_info, + [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, + [](const flutter::SurfaceFrame& surface_frame) { return true; }, + /*frame_size=*/SkISize::Make(800, 600)); + + flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)); + + XCTAssertEqual(flutterView.subviews.count, 1u); +} + - (void)testFlutterTouchInterceptingViewLinksToAccessibilityContainer { FlutterTouchInterceptingView* touchInteceptorView = [[FlutterTouchInterceptingView alloc] init]; NSObject* container = [[NSObject alloc] init]; From af8260b9b754510c65a5a154f9823536d3eade83 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 23 Sep 2024 09:34:56 -0700 Subject: [PATCH 3/3] ++ --- .../ios/framework/Source/FlutterPlatformViewsTest.mm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index d6a2421f33c51..904a3eace2564 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -3739,7 +3739,18 @@ - (void)testNilPlatformViewDoesntCrash { UIView* flutterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; flutterPlatformViewsController->SetFlutterView(flutterView); + // Create embedded view params flutter::MutatorsStack stack; + // Layer tree always pushes a screen scale factor to the stack + SkMatrix screenScaleMatrix = + SkMatrix::Scale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale); + stack.PushTransform(screenScaleMatrix); + // Push a translate matrix + SkMatrix translateMatrix = SkMatrix::Translate(100, 100); + stack.PushTransform(translateMatrix); + SkMatrix finalMatrix; + finalMatrix.setConcat(screenScaleMatrix, translateMatrix); + auto embeddedViewParams = std::make_unique(finalMatrix, SkSize::Make(300, 300), stack);