Unverified Commit 22436cca authored by Angjie Li's avatar Angjie Li Committed by GitHub

Revert "Avoid passive clipboard read on Android (#86791)" (#87375)

parent 962f57f8
...@@ -1655,26 +1655,18 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget ...@@ -1655,26 +1655,18 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
/// Check the [Clipboard] and update [value] if needed. /// Check the [Clipboard] and update [value] if needed.
Future<void> update() async { Future<void> update() async {
// iOS 14 added a notification that appears when an app accesses the
// clipboard. To avoid the notification, don't access the clipboard on iOS,
// and instead always show the paste button, even when the clipboard is
// empty.
// TODO(justinmc): Use the new iOS 14 clipboard API method hasStrings that
// won't trigger the notification.
// https://github.com/flutter/flutter/issues/60145
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
// Android 12 introduces a toast message that appears when an app reads
// the content on the clipboard. To avoid unintended access, both the
// Flutter engine and the Flutter framework need to be updated to use the
// appropriate API to check whether the clipboard is empty.
// As a short-term workaround, always show the paste button.
// TODO(justinmc): Expose `hasStrings` in `Clipboard` and use that instead
// https://github.com/flutter/flutter/issues/74139
case TargetPlatform.android:
// Intentionally fall through.
// iOS 14 added a notification that appears when an app accesses the
// clipboard. To avoid the notification, don't access the clipboard on iOS,
// and instead always show the paste button, even when the clipboard is
// empty.
// TODO(justinmc): Use the new iOS 14 clipboard API method hasStrings that
// won't trigger the notification.
// https://github.com/flutter/flutter/issues/60145
case TargetPlatform.iOS: case TargetPlatform.iOS:
value = ClipboardStatus.pasteable; value = ClipboardStatus.pasteable;
return; return;
case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
case TargetPlatform.linux: case TargetPlatform.linux:
case TargetPlatform.macOS: case TargetPlatform.macOS:
......
...@@ -928,7 +928,7 @@ void main() { ...@@ -928,7 +928,7 @@ void main() {
), ),
); );
focusNode.requestFocus(); focusNode.requestFocus();
await tester.pumpAndSettle(); await tester.pump();
await expectLater( await expectLater(
find.byType(TextField), find.byType(TextField),
...@@ -956,7 +956,7 @@ void main() { ...@@ -956,7 +956,7 @@ void main() {
), ),
); );
focusNode.requestFocus(); focusNode.requestFocus();
await tester.pumpAndSettle(); await tester.pump();
await expectLater( await expectLater(
find.byType(TextField), find.byType(TextField),
...@@ -984,7 +984,7 @@ void main() { ...@@ -984,7 +984,7 @@ void main() {
), ),
); );
focusNode.requestFocus(); focusNode.requestFocus();
await tester.pumpAndSettle(); await tester.pump();
await expectLater( await expectLater(
find.byType(TextField), find.byType(TextField),
...@@ -6223,13 +6223,10 @@ void main() { ...@@ -6223,13 +6223,10 @@ void main() {
semantics.dispose(); semantics.dispose();
// On web, we don't check for pasteability because that triggers a // On web (just like iOS), we don't check for pasteability because that
// permission dialog in the browser. // triggers a permission dialog in the browser.
// https://github.com/flutter/flutter/pull/57139#issuecomment-629048058 // https://github.com/flutter/flutter/pull/57139#issuecomment-629048058
// TODO(justinmc): Remove TargetPlatform override when Android and iOS uses }, skip: isBrowser);
// `hasStrings` to check for pasteability.
// https://github.com/flutter/flutter/issues/74139
}, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux }));
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async { testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
const Widget textField = TextField(); const Widget textField = TextField();
...@@ -9591,10 +9588,7 @@ void main() { ...@@ -9591,10 +9588,7 @@ void main() {
// pasted. // pasted.
expect(triedToReadClipboard, true); expect(triedToReadClipboard, true);
} }
// TODO(justinmc): Eventually, all platform should call `hasStrings` instead. });
// This entire test will become irrelevant after the fact.
// https://github.com/flutter/flutter/issues/74139
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux }));
testWidgets('TextField changes mouse cursor when hovered', (WidgetTester tester) async { testWidgets('TextField changes mouse cursor when hovered', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
......
...@@ -615,9 +615,7 @@ void main() { ...@@ -615,9 +615,7 @@ void main() {
}); });
}); });
// TODO(justinmc): Paste should only appears when the clipboard has contents. testWidgets('Paste only appears when clipboard has contents', (WidgetTester tester) async {
// https://github.com/flutter/flutter/issues/74139
testWidgets('Paste always appears regardless of clipboard content on Android', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
); );
...@@ -645,10 +643,8 @@ void main() { ...@@ -645,10 +643,8 @@ void main() {
await tester.tapAt(textOffsetToPosition(tester, index)); await tester.tapAt(textOffsetToPosition(tester, index));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// Paste is showing even though clipboard is empty. // No Paste yet, because nothing has been copied.
// TODO(justinmc): Paste should not appears when the clipboard is empty. expect(find.text('Paste'), findsNothing);
// https://github.com/flutter/flutter/issues/74139
expect(find.text('Paste'), findsOneWidget);
expect(find.text('Copy'), findsOneWidget); expect(find.text('Copy'), findsOneWidget);
expect(find.text('Cut'), findsOneWidget); expect(find.text('Cut'), findsOneWidget);
expect(find.text('Select all'), findsOneWidget); expect(find.text('Select all'), findsOneWidget);
......
...@@ -2553,7 +2553,7 @@ void main() { ...@@ -2553,7 +2553,7 @@ void main() {
)); ));
semanticsOwner.performAction(inputFieldId, SemanticsAction.longPress); semanticsOwner.performAction(inputFieldId, SemanticsAction.longPress);
await tester.pumpAndSettle(); await tester.pump();
expect(semantics, hasSemantics( expect(semantics, hasSemantics(
TestSemantics.root( TestSemantics.root(
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton; import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -766,19 +765,13 @@ void main() { ...@@ -766,19 +765,13 @@ void main() {
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
}); });
// TODO(justinmc): See if `testWidgets` can be reverted to `test`. test('Clipboard API failure is gracefully recovered from', () async {
testWidgets('Clipboard API failure is gracefully recovered from', (WidgetTester tester) async {
final ClipboardStatusNotifier notifier = ClipboardStatusNotifier(); final ClipboardStatusNotifier notifier = ClipboardStatusNotifier();
expect(notifier.value, ClipboardStatus.unknown); expect(notifier.value, ClipboardStatus.unknown);
await expectLater(notifier.update(), completes); await expectLater(notifier.update(), completes);
expect(notifier.value, ClipboardStatus.unknown); expect(notifier.value, ClipboardStatus.unknown);
// TODO(justinmc): Currently on Android and iOS, ClipboardStatus.pasteable });
// is always returned. Once both platforms properly use
// `hasStrings` to check whether the clipboard has any
// content, try to see if this override can be removed.
// https://github.com/flutter/flutter/issues/74139
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux }));
}); });
group('when Clipboard succeeds', () { group('when Clipboard succeeds', () {
...@@ -792,8 +785,7 @@ void main() { ...@@ -792,8 +785,7 @@ void main() {
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null); TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
}); });
// TODO(justinmc): See if `testWidgets` can be reverted to `test`. test('update sets value based on clipboard contents', () async {
testWidgets('update sets value based on clipboard contents', (WidgetTester tester) async {
final ClipboardStatusNotifier notifier = ClipboardStatusNotifier(); final ClipboardStatusNotifier notifier = ClipboardStatusNotifier();
expect(notifier.value, ClipboardStatus.unknown); expect(notifier.value, ClipboardStatus.unknown);
...@@ -808,12 +800,7 @@ void main() { ...@@ -808,12 +800,7 @@ void main() {
)); ));
await expectLater(notifier.update(), completes); await expectLater(notifier.update(), completes);
expect(notifier.value, ClipboardStatus.pasteable); expect(notifier.value, ClipboardStatus.pasteable);
// TODO(justinmc): Currently on Android and iOS, ClipboardStatus.pasteable });
// is always returned. Once both platforms properly use
// `hasStrings` to check whether the clipboard has any
// content, try to see if this override can be removed.
// https://github.com/flutter/flutter/issues/74139
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.linux }));
}); });
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment