Skip to content

Commit

Permalink
[google_sign_in] Update Pigeon for non-nullable generics (#7785)
Browse files Browse the repository at this point in the history
Updates the Pigeon definition to uses non-nullable generics now that it's possible.

In practice for this plugin it's currently a no-op: the only affected collection is passed from Dart to native, on the Dart side the source was already a `List<String>`, and on the native side we are using languages without nullability support in generics (Java and Obj-C). However, to do this now eliminates tech debt, and will avoid problems if/when the native side switches to Kotlin/Swift.

The Android implementation required some non-trivial changes to adapt to an earlier Pigeon change that we hadn't picked up yet, which was the change from `Result<Void>` (which turned out to be incompatible with Kotlin) to the separate `VoidResult` class.

Part of flutter/flutter#155891
  • Loading branch information
stuartmorgan authored Oct 7, 2024
1 parent e784c3e commit bb00d34
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 263 deletions.
4 changes: 4 additions & 0 deletions packages/google_sign_in/google_sign_in_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.1.33

* Updates Pigeon for non-nullable collection type support.

## 6.1.32

* Updates Java compatibility version to 11.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ public void initInstance(
@NonNull GoogleSignInWrapper googleSignInWrapper) {
this.messenger = messenger;
delegate = new Delegate(context, googleSignInWrapper);
GoogleSignInApi.setup(messenger, delegate);
GoogleSignInApi.setUp(messenger, delegate);
}

private void dispose() {
delegate = null;
if (messenger != null) {
GoogleSignInApi.setup(messenger, null);
GoogleSignInApi.setUp(messenger, null);
messenger = null;
}
}
Expand Down Expand Up @@ -241,6 +241,30 @@ void requestScopes(
final @NonNull MethodChannel.Result result, final @NonNull List<String> scopes);
}

/**
* Helper class for supporting the legacy IDelegate interface based on raw method channels, which
* handles converting any FlutterErrors (or other {@code Throwable}s in case any non- FlutterError
* exceptions slip through) thrown by the new code paths into {@code error} callbacks.
*/
private abstract static class ErrorConvertingMethodChannelVoidResult
implements Messages.VoidResult {
final @NonNull MethodChannel.Result result;

public ErrorConvertingMethodChannelVoidResult(@NonNull MethodChannel.Result result) {
this.result = result;
}

@Override
public void error(@NonNull Throwable error) {
if (error instanceof FlutterError) {
FlutterError flutterError = (FlutterError) error;
result.error(flutterError.code, flutterError.getMessage(), flutterError.details);
} else {
result.error("exception", error.getMessage(), null);
}
}
}

/**
* Helper class for supporting the legacy IDelegate interface based on raw method channels, which
* handles converting any FlutterErrors (or other {@code Throwable}s in case any non- FlutterError
Expand Down Expand Up @@ -296,13 +320,13 @@ public void success(Messages.UserData data) {
* Helper class for supporting the legacy IDelegate interface based on raw method channels, which
* handles converting responses from methods that return {@code Void}.
*/
private static class VoidMethodChannelResult extends ErrorConvertingMethodChannelResult<Void> {
private static class VoidMethodChannelResult extends ErrorConvertingMethodChannelVoidResult {
public VoidMethodChannelResult(MethodChannel.Result result) {
super(result);
}

@Override
public void success(Void unused) {
public void success() {
result.success(null);
}
}
Expand Down Expand Up @@ -367,7 +391,7 @@ public void setActivity(@Nullable Activity activity) {
private void checkAndSetPendingOperation(
String method,
Messages.Result<Messages.UserData> userDataResult,
Messages.Result<Void> voidResult,
Messages.VoidResult voidResult,
Messages.Result<Boolean> boolResult,
Messages.Result<String> stringResult,
Object data) {
Expand All @@ -385,7 +409,7 @@ private void checkAndSetPendingSignInOperation(
}

private void checkAndSetPendingVoidOperation(
String method, @NonNull Messages.Result<Void> result) {
String method, @NonNull Messages.VoidResult result) {
checkAndSetPendingOperation(method, null, result, null, null, null);
}

Expand Down Expand Up @@ -557,7 +581,7 @@ public void signIn(@NonNull MethodChannel.Result result) {
* sign back in.
*/
@Override
public void signOut(@NonNull Messages.Result<Void> result) {
public void signOut(@NonNull Messages.VoidResult result) {
checkAndSetPendingVoidOperation("signOut", result);

signInClient
Expand All @@ -580,7 +604,7 @@ public void signOut(@NonNull MethodChannel.Result result) {

/** Signs the user out, and revokes their credentials. */
@Override
public void disconnect(@NonNull Messages.Result<Void> result) {
public void disconnect(@NonNull Messages.VoidResult result) {
checkAndSetPendingVoidOperation("disconnect", result);

signInClient
Expand Down Expand Up @@ -705,7 +729,7 @@ private String errorCodeForStatus(int statusCode) {
}

private void finishWithSuccess() {
Objects.requireNonNull(pendingOperation.voidResult).success(null);
Objects.requireNonNull(pendingOperation.voidResult).success();
pendingOperation = null;
}

Expand All @@ -720,32 +744,35 @@ private void finishWithUserData(Messages.UserData data) {
}

private void finishWithError(String errorCode, String errorMessage) {
Messages.Result<?> result;
if (pendingOperation.userDataResult != null) {
result = pendingOperation.userDataResult;
} else if (pendingOperation.boolResult != null) {
result = pendingOperation.boolResult;
} else if (pendingOperation.stringResult != null) {
result = pendingOperation.stringResult;
if (pendingOperation.voidResult != null) {
Objects.requireNonNull(pendingOperation.voidResult)
.error(new FlutterError(errorCode, errorMessage, null));
} else {
result = pendingOperation.voidResult;
Messages.Result<?> result;
if (pendingOperation.userDataResult != null) {
result = pendingOperation.userDataResult;
} else if (pendingOperation.boolResult != null) {
result = pendingOperation.boolResult;
} else {
result = pendingOperation.stringResult;
}
Objects.requireNonNull(result).error(new FlutterError(errorCode, errorMessage, null));
}
Objects.requireNonNull(result).error(new FlutterError(errorCode, errorMessage, null));
pendingOperation = null;
}

private static class PendingOperation {
final @NonNull String method;
final @Nullable Messages.Result<Messages.UserData> userDataResult;
final @Nullable Messages.Result<Void> voidResult;
final @Nullable Messages.VoidResult voidResult;
final @Nullable Messages.Result<Boolean> boolResult;
final @Nullable Messages.Result<String> stringResult;
final @Nullable Object data;

PendingOperation(
@NonNull String method,
@Nullable Messages.Result<Messages.UserData> userDataResult,
@Nullable Messages.Result<Void> voidResult,
@Nullable Messages.VoidResult voidResult,
@Nullable Messages.Result<Boolean> boolResult,
@Nullable Messages.Result<String> stringResult,
@Nullable Object data) {
Expand All @@ -764,7 +791,7 @@ private static class PendingOperation {

/** Clears the token kept in the client side cache. */
@Override
public void clearAuthCache(@NonNull String token, @NonNull Messages.Result<Void> result) {
public void clearAuthCache(@NonNull String token, @NonNull Messages.VoidResult result) {
Callable<Void> clearTokenTask =
() -> {
GoogleAuthUtil.clearToken(context, token);
Expand All @@ -775,7 +802,8 @@ public void clearAuthCache(@NonNull String token, @NonNull Messages.Result<Void>
clearTokenTask,
clearTokenFuture -> {
try {
result.success(clearTokenFuture.get());
clearTokenFuture.get();
result.success();
} catch (ExecutionException e) {
@Nullable Throwable cause = e.getCause();
result.error(
Expand Down
Loading

0 comments on commit bb00d34

Please sign in to comment.