Skip to content

Commit b08f915

Browse files
authored
[google_sign_in_web] Stop relying on framework internals. (#5660)
The private `FlexHtmlElementView` widget that backs the `renderButton` method currently relies on internal web engine knowledge (a CSS selector) to work. This PR reimplements that bit of the `FlexHtmlElementView` so it uses standard framework APIs, and removes its reliance in undocumented behavior. ## Issues * Related to: flutter/engine#48960
1 parent 2b53f72 commit b08f915

File tree

5 files changed

+47
-51
lines changed

5 files changed

+47
-51
lines changed

packages/google_sign_in/google_sign_in_web/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.12.3+1
2+
3+
* Updates `FlexHtmlElementView` (the widget backing `renderButton`) to not
4+
rely on web engine knowledge (a platform view CSS selector) to operate.
5+
16
## 0.12.3
27

38
* Migrates to `package:web`.

packages/google_sign_in/google_sign_in_web/example/integration_test/flexible_size_html_element_view_test.dart

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ void main() {
2222
widgetFactoryNumber++;
2323
});
2424

25-
testWidgets('empty case, calls onPlatformViewCreated',
25+
testWidgets('empty case, calls onElementCreated',
2626
(WidgetTester tester) async {
27-
final Completer<int> viewCreatedCompleter = Completer<int>();
27+
final Completer<Object> viewCreatedCompleter = Completer<Object>();
2828

29-
await pumpResizableWidget(tester, onPlatformViewCreated: (int id) {
30-
viewCreatedCompleter.complete(id);
29+
await pumpResizableWidget(tester, onElementCreated: (Object view) {
30+
viewCreatedCompleter.complete(view);
3131
});
3232
await tester.pumpAndSettle();
3333

@@ -59,7 +59,7 @@ void main() {
5959

6060
final Element element = await pumpResizableWidget(
6161
tester,
62-
onPlatformViewCreated: injectElement(resizable),
62+
onElementCreated: injectElement(resizable),
6363
);
6464
await tester.pumpAndSettle();
6565

@@ -80,7 +80,7 @@ void main() {
8080
final Element element = await pumpResizableWidget(
8181
tester,
8282
initialSize: initialSize,
83-
onPlatformViewCreated: injectElement(resizable),
83+
onElementCreated: injectElement(resizable),
8484
);
8585
await tester.pumpAndSettle();
8686

@@ -103,7 +103,7 @@ void main() {
103103
final Element element = await pumpResizableWidget(
104104
tester,
105105
initialSize: initialSize,
106-
onPlatformViewCreated: injectElement(resizable),
106+
onElementCreated: injectElement(resizable),
107107
);
108108
await tester.pumpAndSettle();
109109

@@ -134,12 +134,12 @@ void main() {
134134
/// Injects a ResizableFromJs widget into the `tester`.
135135
Future<Element> pumpResizableWidget(
136136
WidgetTester tester, {
137-
void Function(int)? onPlatformViewCreated,
137+
void Function(Object)? onElementCreated,
138138
Size? initialSize,
139139
}) async {
140140
await tester.pumpWidget(ResizableFromJs(
141141
instanceId: widgetFactoryNumber,
142-
onPlatformViewCreated: onPlatformViewCreated,
142+
onElementCreated: onElementCreated,
143143
initialSize: initialSize,
144144
));
145145
// Needed for JS to have time to kick-off.
@@ -155,7 +155,7 @@ Future<Element> pumpResizableWidget(
155155
class ResizableFromJs extends StatelessWidget {
156156
ResizableFromJs({
157157
required this.instanceId,
158-
this.onPlatformViewCreated,
158+
this.onElementCreated,
159159
this.initialSize,
160160
super.key,
161161
}) {
@@ -173,7 +173,7 @@ class ResizableFromJs extends StatelessWidget {
173173
}
174174

175175
final int instanceId;
176-
final void Function(int)? onPlatformViewCreated;
176+
final void Function(Object)? onElementCreated;
177177
final Size? initialSize;
178178

179179
@override
@@ -184,7 +184,7 @@ class ResizableFromJs extends StatelessWidget {
184184
child: FlexHtmlElementView(
185185
viewType: 'resizable_from_js_$instanceId',
186186
key: Key('resizable_from_js_$instanceId'),
187-
onPlatformViewCreated: onPlatformViewCreated,
187+
onElementCreated: onElementCreated,
188188
initialSize: initialSize ?? const Size(640, 480),
189189
),
190190
),
@@ -199,11 +199,9 @@ void resize(web.HTMLElement resizable, Size size) {
199199
'width: ${size.width}px; height: ${size.height}px; background: #fabada');
200200
}
201201

202-
/// Returns a function that can be used to inject `element` in `onPlatformViewCreated` callbacks.
203-
void Function(int) injectElement(web.HTMLElement element) {
204-
return (int viewId) {
205-
final web.Element? root =
206-
web.document.querySelector('#test_element_$viewId');
207-
root!.appendChild(element);
202+
/// Returns an `onElementCreated` callback that injects [element].
203+
ElementCreatedCallback injectElement(web.HTMLElement element) {
204+
return (Object root) {
205+
(root as web.HTMLElement).appendChild(element);
208206
};
209207
}

packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,8 @@ class GoogleSignInPlugin extends GoogleSignInPlatform {
195195
if (snapshot.hasData) {
196196
return FlexHtmlElementView(
197197
viewType: 'gsi_login_button',
198-
onPlatformViewCreated: (int viewId) {
199-
final web.Element? element =
200-
web.document.querySelector('#sign_in_button_$viewId');
201-
assert(element != null,
202-
'Cannot render GSI button. DOM is not ready!');
203-
_gisClient.renderButton(element!, config);
198+
onElementCreated: (Object element) {
199+
_gisClient.renderButton(element, config);
204200
});
205201
}
206202
return const Text('Getting ready');

packages/google_sign_in/google_sign_in_web/lib/src/flexible_size_html_element_view.dart

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44
import 'dart:js_interop';
5+
import 'dart:ui_web' as ui_web;
56

7+
import 'package:flutter/foundation.dart';
68
import 'package:flutter/material.dart';
7-
import 'package:flutter/services.dart';
89
import 'package:web/web.dart' as web;
910

1011
/// An HTMLElementView widget that resizes with its contents.
@@ -13,15 +14,15 @@ class FlexHtmlElementView extends StatefulWidget {
1314
const FlexHtmlElementView({
1415
super.key,
1516
required this.viewType,
16-
this.onPlatformViewCreated,
17+
this.onElementCreated,
1718
this.initialSize,
1819
});
1920

2021
/// See [HtmlElementView.viewType].
2122
final String viewType;
2223

23-
/// See [HtmlElementView.onPlatformViewCreated].
24-
final PlatformViewCreatedCallback? onPlatformViewCreated;
24+
/// See [HtmlElementView.fromTagName] `onElementCreated`.
25+
final ElementCreatedCallback? onElementCreated;
2526

2627
/// The initial Size for the widget, before it starts tracking its contents.
2728
final Size? initialSize;
@@ -55,13 +56,15 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
5556
/// Update the state with the new `size`, if needed.
5657
void _doResize(Size size) {
5758
if (size != _lastReportedSize) {
58-
final String log = <Object?>[
59-
'Resizing: ',
60-
widget.viewType,
61-
size.width,
62-
size.height
63-
].join(' ');
64-
web.console.debug(log.toJS);
59+
if (kDebugMode) {
60+
final String log = <Object?>[
61+
'Resizing: ',
62+
widget.viewType,
63+
size.width,
64+
size.height
65+
].join(' ');
66+
web.console.debug(log.toJS);
67+
}
6568
setState(() {
6669
_lastReportedSize = size;
6770
});
@@ -105,12 +108,11 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
105108
}
106109

107110
/// Registers a MutationObserver on the root element of the HtmlElementView.
108-
void _registerListeners(web.Element? root) {
109-
assert(root != null, 'DOM is not ready for the FlexHtmlElementView');
111+
void _registerListeners(web.Element root) {
110112
_mutationObserver = web.MutationObserver(_onMutationRecords.toJS);
111113
// Monitor the size of the child element, whenever it's created...
112114
_mutationObserver!.observe(
113-
root!,
115+
root,
114116
web.MutationObserverInit(
115117
childList: true,
116118
),
@@ -123,10 +125,13 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
123125
size: _lastReportedSize ?? widget.initialSize ?? const Size(1, 1),
124126
child: HtmlElementView(
125127
viewType: widget.viewType,
126-
onPlatformViewCreated: (int viewId) async {
127-
_registerListeners(_locatePlatformViewRoot(viewId));
128-
if (widget.onPlatformViewCreated != null) {
129-
widget.onPlatformViewCreated!(viewId);
128+
onPlatformViewCreated: (int viewId) {
129+
final ElementCreatedCallback? callback = widget.onElementCreated;
130+
final web.Element root =
131+
ui_web.platformViewRegistry.getViewById(viewId) as web.Element;
132+
_registerListeners(root);
133+
if (callback != null) {
134+
callback(root);
130135
}
131136
}),
132137
);
@@ -140,11 +145,3 @@ class _FlexHtmlElementView extends State<FlexHtmlElementView> {
140145
web.Element? _locateSizeProvider(web.NodeList elements) {
141146
return elements.item(0) as web.Element?;
142147
}
143-
144-
/// Finds the root element of a platform view by its `viewId`.
145-
///
146-
/// This element matches the one returned by the registered platform view factory.
147-
web.Element? _locatePlatformViewRoot(int viewId) {
148-
return web.document
149-
.querySelector('flt-platform-view[slot\$="-$viewId"] :first-child');
150-
}

packages/google_sign_in/google_sign_in_web/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Google Sign-In, a secure authentication system
33
for signing in with a Google account on Android, iOS and Web.
44
repository: https://github.com/flutter/packages/tree/main/packages/google_sign_in/google_sign_in_web
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
6-
version: 0.12.3
6+
version: 0.12.3+1
77

88
environment:
99
sdk: ">=3.2.0 <4.0.0"

0 commit comments

Comments
 (0)