diff --git a/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart b/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart index e792ac5476d59..2258d9f19d3b5 100644 --- a/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart +++ b/lib/web_ui/lib/src/engine/view_embedder/embedding_strategy/embedding_strategy.dart @@ -26,7 +26,8 @@ abstract class EmbeddingStrategy { } } - /// The host element in which the Flutter view is embedded. + /// The DOM element in which the Flutter view is embedded. + /// This element is the direct parent element of the element. DomElement get hostElement; /// The global event target for the Flutter view. diff --git a/lib/web_ui/lib/src/engine/view_embedder/flutter_view_manager.dart b/lib/web_ui/lib/src/engine/view_embedder/flutter_view_manager.dart index 2d2bc639e361a..685e940a53cf1 100644 --- a/lib/web_ui/lib/src/engine/view_embedder/flutter_view_manager.dart +++ b/lib/web_ui/lib/src/engine/view_embedder/flutter_view_manager.dart @@ -99,6 +99,11 @@ class FlutterViewManager { return _jsViewOptions[viewId]; } + /// Returns the DOM element in which the Flutter view associated to [viewId] is embedded. + DomElement? getHostElement(int viewId) { + return _viewData[viewId]?.embeddingStrategy.hostElement; + } + EngineFlutterView? findViewForElement(DomElement? element) { const String viewRootSelector = '${DomManager.flutterViewTagName}[${GlobalHtmlAttributes.flutterViewIdAttributeName}]'; diff --git a/lib/web_ui/lib/ui_web/src/ui_web/flutter_views_proxy.dart b/lib/web_ui/lib/ui_web/src/ui_web/flutter_views_proxy.dart index 7e7e99f968b44..f19ee0344f54c 100644 --- a/lib/web_ui/lib/ui_web/src/ui_web/flutter_views_proxy.dart +++ b/lib/web_ui/lib/ui_web/src/ui_web/flutter_views_proxy.dart @@ -17,13 +17,19 @@ class FlutterViewManagerProxy { // The proxied viewManager instance. final FlutterViewManager _viewManager; - /// Returns the `hostElement` configuration value passed from JS when `viewId` was added. + /// Returns the host element for [viewId]. + /// + /// In the full-page mode, the host element is the `` element of the page + /// and the view is the one and only [PlatformDispatcher.implicitView]. + /// + /// In the add-to-app mode, the host element is the value of `hostElement` + /// provided when creating the view. /// /// This is useful for plugins and apps to have a safe DOM Element where they /// can add their own custom HTML elements (for example: file inputs for the /// file_selector plugin). JSAny? getHostElement(int viewId) { - return _viewManager.getOptions(viewId)?.hostElement as JSAny?; + return _viewManager.getHostElement(viewId) as JSAny?; } /// Returns the `initialData` configuration value passed from JS when `viewId` was added. diff --git a/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart b/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart index 230d655d17e4d..0b35c5a771862 100644 --- a/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart +++ b/lib/web_ui/test/engine/view_embedder/flutter_views_proxy_test.dart @@ -36,9 +36,9 @@ Future doTests() async { } setUp(() { - view = EngineFlutterView(platformDispatcher, createDomElement('div')); - viewId = view.viewId; hostElement = createDomElement('div'); + view = EngineFlutterView(platformDispatcher, hostElement); + viewId = view.viewId; }); tearDown(() { @@ -60,6 +60,28 @@ Future doTests() async { expect(element, hostElement); }); + + test('can retrieve hostElement for an implicit view with default host element', () { + final view = EngineFlutterView.implicit(platformDispatcher, null); + final viewId = view.viewId; + viewManager.registerView(view); + addTearDown(() => viewManager.unregisterView(viewId)); + + final JSAny? element = views.getHostElement(viewId); + + expect(element, domDocument.body); + }); + + test('can retrieve hostElement for an implicit view with custom host element', () { + final view = EngineFlutterView.implicit(platformDispatcher, hostElement); + final viewId = view.viewId; + viewManager.registerView(view); + addTearDown(() => viewManager.unregisterView(viewId)); + + final JSAny? element = views.getHostElement(viewId); + + expect(element, hostElement); + }); }); group('getInitialData', () {