Skip to content

Commit db64467

Browse files
authored
[web] Fix multi-reply on message channel. Add test (flutter#17591)
* Fix multi-reply on message channel. Add test * Add check for viewInstanceCount * skip no-headless test
1 parent 0726621 commit db64467

File tree

7 files changed

+139
-6
lines changed

7 files changed

+139
-6
lines changed

.cirrus.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ task:
172172
- $FRAMEWORK_PATH/flutter/bin/flutter config --local-engine=host_debug_unopt --no-analytics --enable-web
173173
- $FRAMEWORK_PATH/flutter/bin/flutter pub get --local-engine=host_debug_unopt
174174
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/text_editing_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
175+
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/platform_messages_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
175176
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/treeshaking_e2e.dart -d web-server --profile --browser-name=chrome --local-engine=host_debug_unopt
176177
- $FRAMEWORK_PATH/flutter/bin/flutter drive -v --target=test_driver/image_loading_e2e.dart -d web-server --release --browser-name=chrome --local-engine=host_debug_unopt
177178

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter/services.dart';
7+
8+
void main() => runApp(MyApp());
9+
10+
Future<ClipboardData> dataFuture;
11+
12+
class MyApp extends StatelessWidget {
13+
@override
14+
Widget build(BuildContext context) {
15+
return MaterialApp(
16+
key: const Key('mainapp'),
17+
title: 'Integration Test App For Platform Messages',
18+
home: MyHomePage(title: 'Integration Test App For Platform Messages'),
19+
);
20+
}
21+
}
22+
23+
class MyHomePage extends StatefulWidget {
24+
MyHomePage({Key key, this.title}) : super(key: key);
25+
26+
final String title;
27+
28+
@override
29+
_MyHomePageState createState() => _MyHomePageState();
30+
}
31+
32+
class _MyHomePageState extends State<MyHomePage> {
33+
final TextEditingController _controller =
34+
TextEditingController(text: 'Text1');
35+
36+
@override
37+
Widget build(BuildContext context) {
38+
return Scaffold(
39+
appBar: AppBar(
40+
title: Text(widget.title),
41+
),
42+
body: Center(
43+
child: Column(
44+
mainAxisAlignment: MainAxisAlignment.center,
45+
children: <Widget>[
46+
const Text('Hello World',
47+
),
48+
// Create a text form field since we can't test clipboard unless
49+
// html document has focus.
50+
TextFormField(
51+
key: const Key('input'),
52+
enabled: true,
53+
controller: _controller,
54+
//initialValue: 'Text1',
55+
decoration: const InputDecoration(
56+
labelText: 'Text Input Field:',
57+
),
58+
),
59+
],
60+
),
61+
),
62+
);
63+
}
64+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:html' as html;
6+
// ignore: undefined_shown_name
7+
import 'dart:ui' as ui show platformViewRegistry;
8+
import 'package:flutter/material.dart';
9+
import 'package:flutter/services.dart';
10+
import 'package:flutter_test/flutter_test.dart';
11+
import 'package:regular_integration_tests/platform_messages_main.dart' as app;
12+
13+
import 'package:e2e/e2e.dart';
14+
15+
void main() async {
16+
E2EWidgetsFlutterBinding.ensureInitialized() as E2EWidgetsFlutterBinding;
17+
18+
testWidgets('platform message for Clipboard.setData reply with future',
19+
(WidgetTester tester) async {
20+
app.main();
21+
await tester.pumpAndSettle();
22+
23+
// TODO(nurhan): https://github.com/flutter/flutter/issues/51885
24+
SystemChannels.textInput.setMockMethodCallHandler(null);
25+
// Focus on a TextFormField.
26+
final Finder finder = find.byKey(const Key('input'));
27+
expect(finder, findsOneWidget);
28+
await tester.tap(find.byKey(const Key('input')));
29+
// Focus in input, otherwise clipboard will fail with
30+
// 'document is not focused' platform exception.
31+
html.document.querySelector('input').focus();
32+
await Clipboard.setData(const ClipboardData(text: 'sample text'));
33+
}, skip: true); // https://github.com/flutter/flutter/issues/54296
34+
35+
testWidgets('Should create and dispose view embedder',
36+
(WidgetTester tester) async {
37+
int viewInstanceCount = 0;
38+
39+
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
40+
// ignore: undefined_prefixed_name
41+
ui.platformViewRegistry.registerViewFactory('MyView', (int viewId) {
42+
++viewInstanceCount;
43+
return html.DivElement();
44+
});
45+
46+
app.main();
47+
await tester.pumpAndSettle();
48+
final Map<String, dynamic> createArgs = <String, dynamic>{
49+
'id': '567',
50+
'viewType': 'MyView',
51+
};
52+
await SystemChannels.platform_views.invokeMethod<void>('create', createArgs);
53+
final Map<String, dynamic> disposeArgs = <String, dynamic>{
54+
'id': '567',
55+
};
56+
await SystemChannels.platform_views.invokeMethod<void>('dispose', disposeArgs);
57+
expect(viewInstanceCount, 1);
58+
});
59+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:e2e/e2e_driver.dart' as e2e;
6+
7+
Future<void> main() async => e2e.main();

lib/web_ui/lib/src/engine/clipboard.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class ClipboardMessageHandler {
1818
void setDataMethodCall(
1919
MethodCall methodCall, ui.PlatformMessageResponseCallback callback) {
2020
const MethodCodec codec = JSONMethodCodec();
21+
bool errorEnvelopeEncoded = false;
2122
_copyToClipboardStrategy
2223
.setData(methodCall.arguments['text'])
2324
.then((bool success) {
@@ -26,10 +27,15 @@ class ClipboardMessageHandler {
2627
} else {
2728
callback(codec.encodeErrorEnvelope(
2829
code: 'copy_fail', message: 'Clipboard.setData failed'));
30+
errorEnvelopeEncoded = true;
2931
}
3032
}).catchError((dynamic _) {
31-
callback(codec.encodeErrorEnvelope(
32-
code: 'copy_fail', message: 'Clipboard.setData failed'));
33+
// Don't encode a duplicate reply if we already failed and an error
34+
// was already encoded.
35+
if (!errorEnvelopeEncoded) {
36+
callback(codec.encodeErrorEnvelope(
37+
code: 'copy_fail', message: 'Clipboard.setData failed'));
38+
}
3339
});
3440
}
3541

lib/web_ui/lib/src/engine/compositor/embedded_views.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,9 @@ class HtmlViewEmbedder {
6969
switch (decoded.method) {
7070
case 'create':
7171
_create(decoded, callback);
72-
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
7372
return;
7473
case 'dispose':
7574
_dispose(decoded, callback);
76-
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
7775
return;
7876
}
7977
callback(null);

lib/web_ui/lib/src/engine/platform_views.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,9 @@ void handlePlatformViewCall(
5050
switch (decoded.method) {
5151
case 'create':
5252
_createPlatformView(decoded, callback);
53-
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
5453
return;
5554
case 'dispose':
5655
_disposePlatformView(decoded, callback);
57-
window._replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
5856
return;
5957
}
6058
callback(null);

0 commit comments

Comments
 (0)