Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a4473ad

Browse files
formatting
1 parent 8f9233e commit a4473ad

File tree

5 files changed

+47
-29
lines changed

5 files changed

+47
-29
lines changed

shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,14 @@ public interface TextInputMethodHandler {
293293
void requestAutofill();
294294

295295
/**
296-
* Requests that the {@link AutofillManager} cancel or commit the current
297-
* autofill context, depending on the value of {@code shouldSave}.
296+
* Requests that the {@link AutofillManager} cancel or commit the current autofill context.
298297
*
299-
* The method calls {@link android.view.autofill.AutofillManager#commit()} when {@code shouldSave}
300-
* is true, and calls {@link android.view.autofill.AutofillManager#cancel()} otherwise.
298+
* <p>The method calls {@link android.view.autofill.AutofillManager#commit()} when {@code
299+
* shouldSave} is true, and calls {@link android.view.autofill.AutofillManager#cancel()}
300+
* otherwise.
301301
*
302-
* @param shouldSave whether the active autofill service should save the
303-
* current user input for future use.
302+
* @param shouldSave whether the active autofill service should save the current user input for
303+
* future use.
304304
*/
305305
void finishAutofillContext(boolean shouldSave);
306306

shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ public void requestAutofill() {
8484

8585
@Override
8686
public void finishAutofillContext(boolean shouldSave) {
87-
if (afm == null)
87+
if (afm == null) {
8888
return;
89+
}
8990
if (shouldSave) {
9091
afm.commit();
9192
} else {

shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import io.flutter.plugin.common.BinaryMessenger;
3636
import io.flutter.plugin.common.JSONMethodCodec;
3737
import io.flutter.plugin.common.MethodCall;
38-
import io.flutter.plugin.common.MethodChannel;
3938
import io.flutter.plugin.platform.PlatformViewsController;
4039
import java.nio.ByteBuffer;
4140
import java.util.ArrayList;
@@ -71,9 +70,11 @@ private void verifyMethodCall(ByteBuffer buffer, String methodName, String[] exp
7170
}
7271
}
7372

74-
private static void sendToBinaryMessageHandler(BinaryMessenger.BinaryMessageHandler binaryMessageHandler, String method, Object args) {
73+
private static void sendToBinaryMessageHandler(
74+
BinaryMessenger.BinaryMessageHandler binaryMessageHandler, String method, Object args) {
7575
MethodCall methodCall = new MethodCall(method, args);
76-
ByteBuffer encodedMethodCall = JSONMethodCodec.INSTANCE.encodeMethodCall(methodCall).position(0);
76+
ByteBuffer encodedMethodCall =
77+
JSONMethodCodec.INSTANCE.encodeMethodCall(methodCall).position(0);
7778
binaryMessageHandler.onMessage(encodedMethodCall, mock(BinaryMessenger.BinaryReply.class));
7879
}
7980

@@ -539,20 +540,21 @@ public void autofill_onProvideVirtualViewStructure_single() {
539540
}
540541

541542
@Test
542-
public void respondsToInputChannelMessages () {
543-
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> binaryMessageHandlerCaptor = ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
543+
public void respondsToInputChannelMessages() {
544+
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> binaryMessageHandlerCaptor =
545+
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
544546
DartExecutor mockBinaryMessenger = mock(DartExecutor.class);
545-
TextInputChannel.TextInputMethodHandler mockHandler = mock(TextInputChannel.TextInputMethodHandler.class);
547+
TextInputChannel.TextInputMethodHandler mockHandler =
548+
mock(TextInputChannel.TextInputMethodHandler.class);
546549
TextInputChannel textInputChannel = new TextInputChannel(mockBinaryMessenger);
547550

548551
textInputChannel.setTextInputMethodHandler(mockHandler);
549552

550553
verify(mockBinaryMessenger, times(1))
551-
.setMessageHandler(
552-
any(String.class),
553-
binaryMessageHandlerCaptor.capture());
554+
.setMessageHandler(any(String.class), binaryMessageHandlerCaptor.capture());
554555

555-
BinaryMessenger.BinaryMessageHandler binaryMessageHandler = binaryMessageHandlerCaptor.getValue();
556+
BinaryMessenger.BinaryMessageHandler binaryMessageHandler =
557+
binaryMessageHandlerCaptor.getValue();
556558

557559
sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.requestAutofill", null);
558560
verify(mockHandler, times(1)).requestAutofill();

shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,18 @@ static UITextContentType ToUITextContentType(NSArray<NSString*>* hints) {
220220
return [dictionary[@"obscureText"] boolValue] ? @"password" : nil;
221221
}
222222

223-
// We refer to password/username autofill, one-time-code autofill,
224-
// and predictive text for contact information etc. as autofill.
223+
// There're 2 types of autofills on native iOS:
224+
// - Regular autofill, includes contact information autofill and
225+
// one-time-code autofill, takes place in the form of predictive
226+
// text in the quick type bar. This type of autofill does not save
227+
// user input.
228+
// - Password autofill, includes automatic strong password and regular
229+
// password autofill. The former happens automatically when a
230+
// "new password" field is detected, and only that password field
231+
// will be filled. The latter appears in the quick type bar when
232+
// an eligible input field becomes the first responder, and may
233+
// fill both the username and the password fields. iOS will attempt
234+
// to save user input for both kinds of password fields.
225235
typedef NS_ENUM(NSInteger, FlutterAutofillType) {
226236
FlutterAutofillTypeNone,
227237
FlutterAutofillTypeRegular,
@@ -238,7 +248,7 @@ static FlutterAutofillType autofillTypeOf(NSDictionary* configuration) {
238248
// for multiple input fields when there's a password input field among them.
239249
// When the configuration contains more than 1 field, we consider this
240250
// autofill group password related.
241-
if (isSecureTextEntry || (fields && [fields count] > 1))
251+
if (isSecureTextEntry || (fields && fields.count > 1))
242252
return FlutterAutofillTypePassword;
243253

244254
if (uniqueIdFromDictionary(configuration) == nil) {
@@ -324,9 +334,9 @@ - (BOOL)isEqualTo:(FlutterTextRange*)other {
324334
// selectors it can't respond to to a shared UITextField instance.
325335
//
326336
// Relevant API docs claim that password autofill supports any custom view
327-
// that adopts the UITextInput protocol, auto strong password seems to
328-
// currently only support UITextFields and saving username/password
329-
// for autofill only supports UITextFields and UITextViews, as of iOS 13.5.
337+
// that adopts the UITextInput protocol, automatic strong password seems to
338+
// currently only support UITextFields, and password saving only supports
339+
// UITextFields and UITextViews, as of iOS 13.5.
330340
@interface FlutterSecureTextInputView : FlutterTextInputView
331341
@property(class, nonatomic, assign, readonly) UITextField* textField;
332342
@end
@@ -435,11 +445,13 @@ - (void)configureWithDictionary:(NSDictionary*)configuration {
435445
? UITextAutocorrectionTypeNo
436446
: UITextAutocorrectionTypeDefault;
437447
if (@available(iOS 10.0, *)) {
448+
_autofillId = uniqueIdFromDictionary(configuration);
438449
if (autofill == nil) {
439450
self.textContentType = @"";
440451
} else {
441452
self.textContentType = ToUITextContentType(autofill[@"hints"]);
442453
[self setTextInputState:autofill[@"editingValue"]];
454+
NSAssert(_autofillId, @"The autofill configuration must contain an autofill id");
443455
// The input field needs to be visible for the system autofill
444456
// to find it.
445457
self.frame = CGRectMake(0, 0, 1, 1);
@@ -524,7 +536,8 @@ - (NSRange)clampSelection:(NSRange)range forText:(NSString*)text {
524536
- (BOOL)canBecomeFirstResponder {
525537
// Only the currently focused input field can
526538
// become the first responder. This prevents iOS
527-
// from changing focus by itself.
539+
// from changing focus by itself (the framework
540+
// focus will be out of sync if that happens).
528541
return _textInputClient != 0;
529542
}
530543

@@ -1132,11 +1145,12 @@ - (FlutterTextInputView*)getOrCreateAutofillableView:(NSDictionary*)field
11321145
}
11331146

11341147
inputView.textInputDelegate = _textInputDelegate;
1135-
inputView.autofillId = autofillId;
11361148
[inputView configureWithDictionary:field];
11371149
return inputView;
11381150
}
11391151

1152+
// Remove every installed input field, unless it's in the current autofill
1153+
// context.
11401154
- (void)removeNonPasswordAutofillFields:(BOOL)removeNonAutofillField {
11411155
UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow;
11421156

shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.m

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ - (void)testAutofillContext {
258258
oldContext = textInputPlugin.autofillContext;
259259
[self setClientId:200 configuration:config];
260260

261+
// Reuse the input view instance from the last time.
261262
XCTAssertEqual(textInputPlugin.autofillContext.count, 4);
262263
XCTAssertEqual(self.installedInputViews.count, 4);
263264

@@ -348,16 +349,16 @@ - (void)testAutofillInputViews {
348349
OCMVerify([engine updateEditingClient:0 withState:[OCMArg isNotNil] withTag:@"field2"]);
349350
}
350351

351-
-(void)testPasswordAutofillHack {
352+
- (void)testPasswordAutofillHack {
352353
NSDictionary* config = self.mutableTemplateCopy;
353354
[config setValue:@"YES" forKey:@"obscureText"];
354355
[self setClientId:123 configuration:config];
355-
356+
356357
// Find all the FlutterTextInputViews we created.
357358
NSArray<FlutterTextInputView*>* inputFields = self.installedInputViews;
358-
359+
359360
FlutterTextInputView* inputView = inputFields[0];
360-
361+
361362
XCTAssert([inputView isKindOfClass:[UITextField class]]);
362363
// FlutterSecureTextInputView does not respond to font,
363364
// but it should return the default UITextField.font.

0 commit comments

Comments
 (0)