diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index bd1705440040d..69621369096c5 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc @@ -532,7 +532,15 @@ std::unique_ptr FlutterWindowsEngine::CreateView( captures->latch.Signal(); }; - embedder_api_.AddView(engine_, &info); + FlutterEngineResult result = embedder_api_.AddView(engine_, &info); + if (result != kSuccess) { + FML_LOG(ERROR) + << "Starting the add view operation failed. FlutterEngineAddView " + "returned an unexpected result: " + << result << ". This indicates a bug in the Windows embedder."; + FML_DCHECK(false); + return nullptr; + } // Block the platform thread until the engine has added the view. // TODO(loicsharma): This blocks the platform thread eagerly and can @@ -573,15 +581,24 @@ void FlutterWindowsEngine::RemoveView(FlutterViewId view_id) { info.view_id = view_id; info.user_data = &captures; info.remove_view_callback = [](const FlutterRemoveViewResult* result) { - // This is invoked on the raster thread, the same thread that the present - // callback is invoked. If |FlutterRemoveViewResult.removed| is `true`, - // the engine guarantees the view won't be presented. + // This is invoked on an engine thread. If + // |FlutterRemoveViewResult.removed| is `true`, the engine guarantees the + // view won't be presented. Captures* captures = reinterpret_cast(result->user_data); captures->removed = result->removed; captures->latch.Signal(); }; - embedder_api_.RemoveView(engine_, &info); + FlutterEngineResult result = embedder_api_.RemoveView(engine_, &info); + if (result != kSuccess) { + FML_LOG(ERROR) << "Starting the remove view operation failed. " + "FlutterEngineRemoveView " + "returned an unexpected result: " + << result + << ". This indicates a bug in the Windows embedder."; + FML_DCHECK(false); + return; + } // Block the platform thread until the engine has removed the view. // TODO(loicsharma): This blocks the platform thread eagerly and can diff --git a/shell/platform/windows/flutter_windows_engine_unittests.cc b/shell/platform/windows/flutter_windows_engine_unittests.cc index f9ebdbc278dfb..a7b45f7490ef3 100644 --- a/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -1265,5 +1265,53 @@ TEST_F(FlutterWindowsEngineTest, ReceivePlatformViewMessage) { } } +TEST_F(FlutterWindowsEngineTest, AddViewFailureDoesNotHang) { + FlutterWindowsEngineBuilder builder{GetContext()}; + auto engine = builder.Build(); + + EngineModifier modifier{engine.get()}; + + modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; + modifier.embedder_api().AddView = MOCK_ENGINE_PROC( + AddView, + [](FLUTTER_API_SYMBOL(FlutterEngine) engine, + const FlutterAddViewInfo* info) { return kInternalInconsistency; }); + + ASSERT_TRUE(engine->Run()); + + // Create the first view. This is the implicit view and isn't added to the + // engine. + auto implicit_window = std::make_unique>(); + + std::unique_ptr implicit_view = + engine->CreateView(std::move(implicit_window)); + + EXPECT_TRUE(implicit_view); + + // Create a second view. The embedder attempts to add it to the engine. + auto second_window = std::make_unique>(); + + EXPECT_DEBUG_DEATH(engine->CreateView(std::move(second_window)), + "FlutterEngineAddView returned an unexpected result"); +} + +TEST_F(FlutterWindowsEngineTest, RemoveViewFailureDoesNotHang) { + FlutterWindowsEngineBuilder builder{GetContext()}; + builder.SetDartEntrypoint("sendCreatePlatformViewMethod"); + auto engine = builder.Build(); + + EngineModifier modifier{engine.get()}; + + modifier.embedder_api().RunsAOTCompiledDartCode = []() { return false; }; + modifier.embedder_api().RemoveView = MOCK_ENGINE_PROC( + RemoveView, + [](FLUTTER_API_SYMBOL(FlutterEngine) engine, + const FlutterRemoveViewInfo* info) { return kInternalInconsistency; }); + + ASSERT_TRUE(engine->Run()); + EXPECT_DEBUG_DEATH(engine->RemoveView(123), + "FlutterEngineRemoveView returned an unexpected result"); +} + } // namespace testing } // namespace flutter