Skip to content

Commit

Permalink
[google_identity_services_web] Migrate all types to JSObject (#8053)
Browse files Browse the repository at this point in the history
And cleanup other legacy JS-interop
Also update tests so they pass with WebAssembly
  • Loading branch information
kevmoo authored Nov 16, 2024
1 parent 58d1e6b commit 38b100c
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 117 deletions.
4 changes: 4 additions & 0 deletions packages/google_identity_services_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.3.3

* Moves all the JavaScript types to extend `JSObject`.

## 0.3.2

* Adds the `nonce` parameter to `loadWebSdk`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,24 @@ void main() async {
utils.createExpectConfigValue(config as JSObject);

expectConfigValue('client_id', 'testing_1-2-3');
expectConfigValue('auto_select', isFalse);
expectConfigValue('auto_select', false);
expectConfigValue('callback', utils.isAJs('function'));
expectConfigValue('login_uri', 'https://www.example.com/login');
expectConfigValue('native_callback', utils.isAJs('function'));
expectConfigValue('cancel_on_tap_outside', isFalse);
expectConfigValue('allowed_parent_origin', isA<JSArray<JSString>>());
expectConfigValue('cancel_on_tap_outside', false);
expectConfigValue(
'allowed_parent_origin', <String>['allowed', 'another']);
expectConfigValue('prompt_parent_id', 'some_dom_id');
expectConfigValue('nonce', 's0m3_r4ndOM_vALu3');
expectConfigValue('context', 'signin');
expectConfigValue('state_cookie_domain', 'subdomain.example.com');
expectConfigValue('ux_mode', 'popup');
expectConfigValue(
'allowed_parent_origin', <String>['allowed', 'another']);
expectConfigValue(
'intermediate_iframe_close_callback', utils.isAJs('function'));
expectConfigValue('itp_support', isTrue);
expectConfigValue('itp_support', true);
expectConfigValue('login_hint', '[email protected]');
expectConfigValue('hd', 'hd_value');
expectConfigValue('use_fedcm_for_prompt', isTrue);
expectConfigValue('use_fedcm_for_prompt', true);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ void main() async {
expectConfigValue('client_id', 'testing_1-2-3');
expectConfigValue('callback', utils.isAJs('function'));
expectConfigValue('scope', 'one two three');
expectConfigValue('include_granted_scopes', isTrue);
expectConfigValue('include_granted_scopes', true);
expectConfigValue('prompt', 'some-prompt');
expectConfigValue('enable_granular_consent', isTrue);
expectConfigValue('enable_granular_consent', true);
expectConfigValue('login_hint', '[email protected]');
expectConfigValue('hd', 'hd_value');
expectConfigValue('state', 'some-state');
Expand All @@ -66,9 +66,9 @@ void main() async {
utils.createExpectConfigValue(config as JSObject);

expectConfigValue('scope', 'one two three');
expectConfigValue('include_granted_scopes', isTrue);
expectConfigValue('include_granted_scopes', true);
expectConfigValue('prompt', 'some-prompt');
expectConfigValue('enable_granular_consent', isTrue);
expectConfigValue('enable_granular_consent', true);
expectConfigValue('login_hint', '[email protected]');
expectConfigValue('state', 'some-state');
});
Expand All @@ -93,15 +93,15 @@ void main() async {
utils.createExpectConfigValue(config as JSObject);

expectConfigValue('scope', 'one two three');
expectConfigValue('include_granted_scopes', isTrue);
expectConfigValue('include_granted_scopes', true);
expectConfigValue('redirect_uri', 'https://www.example.com/login');
expectConfigValue('callback', utils.isAJs('function'));
expectConfigValue('state', 'some-state');
expectConfigValue('enable_granular_consent', isTrue);
expectConfigValue('enable_granular_consent', true);
expectConfigValue('login_hint', '[email protected]');
expectConfigValue('hd', 'hd_value');
expectConfigValue('ux_mode', 'popup');
expectConfigValue('select_account', isTrue);
expectConfigValue('select_account', true);
expectConfigValue('error_callback', utils.isAJs('function'));
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ typedef ExpectConfigValueFn = void Function(String name, Object? matcher);
/// Creates a [ExpectConfigValueFn] for the `config` [JSObject].
ExpectConfigValueFn createExpectConfigValue(JSObject config) {
return (String name, Object? matcher) {
if (matcher is String) {
matcher = matcher.toJS;
} else if (matcher is bool) {
matcher = matcher.toJS;
} else if (matcher is List) {
final List<Object?> old = matcher;
matcher = isA<JSAny?>().having(
(JSAny? p0) => (p0 as JSArray<JSAny>?)
?.toDart
.map((JSAny? e) => e.dartify())
.toList(),
'Array with matching values',
old);
}
expect(config[name], matcher, reason: name);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ import 'shared.dart';
external GoogleAccountsId get id;

/// The Dart definition of the `google.accounts.id` global.
@JS()
@staticInterop
abstract class GoogleAccountsId {}

/// The `google.accounts.id` methods
extension GoogleAccountsIdExtension on GoogleAccountsId {
extension type GoogleAccountsId._(JSObject _) implements JSObject {
/// An undocumented method.
///
/// Try it with 'debug'.
Expand Down Expand Up @@ -186,10 +181,7 @@ extension GoogleAccountsIdExtension on GoogleAccountsId {
///
/// Data type: IdConfiguration
/// https://developers.google.com/identity/gsi/web/reference/js-reference#IdConfiguration
@JS()
@anonymous
@staticInterop
abstract class IdConfiguration {
extension type IdConfiguration._(JSObject _) implements JSObject {
/// Constructs a IdConfiguration object in JavaScript.
factory IdConfiguration({
/// Your application's client ID, which is found and created in the Google
Expand Down Expand Up @@ -355,12 +347,7 @@ typedef PromptMomentListenerFn = void Function(PromptMomentNotification moment);
///
/// Data type: PromptMomentNotification
/// https://developers.google.com/identity/gsi/web/reference/js-reference#PromptMomentNotification
@JS()
@staticInterop
abstract class PromptMomentNotification {}

/// The methods of the [PromptMomentNotification] data type:
extension PromptMomentNotificationExtension on PromptMomentNotification {
extension type PromptMomentNotification._(JSObject _) implements JSObject {
/// Is this notification for a display moment?
bool isDisplayMoment() => _isDisplayMoment().toDart;
@JS('isDisplayMoment')
Expand Down Expand Up @@ -415,12 +402,7 @@ extension PromptMomentNotificationExtension on PromptMomentNotification {
///
/// Data type: CredentialResponse
/// https://developers.google.com/identity/gsi/web/reference/js-reference#CredentialResponse
@JS()
@staticInterop
abstract class CredentialResponse {}

/// The fields that are contained in the credential response object.
extension CredentialResponseExtension on CredentialResponse {
extension type CredentialResponse._(JSObject _) implements JSObject {
/// The ClientID for this Credential.
String? get client_id => _client_id?.toDart;
@JS('client_id')
Expand Down Expand Up @@ -469,10 +451,7 @@ typedef CallbackFn = void Function(CredentialResponse credentialResponse);
///
/// Data type: GsiButtonConfiguration
/// https://developers.google.com/identity/gsi/web/reference/js-reference#GsiButtonConfiguration
@JS()
@anonymous
@staticInterop
abstract class GsiButtonConfiguration {
extension type GsiButtonConfiguration._(JSObject _) implements JSObject {
/// Constructs an options object for the [renderButton] method.
factory GsiButtonConfiguration({
/// The button type.
Expand Down Expand Up @@ -535,12 +514,7 @@ abstract class GsiButtonConfiguration {
}

/// The object passed as an optional parameter to `click_listener` function.
@JS()
@staticInterop
abstract class GsiButtonData {}

/// The fields that are contained in the button data.
extension GsiButtonDataExtension on GsiButtonData {
extension type GsiButtonData._(JSObject _) implements JSObject {
/// Nonce
String? get nonce => _nonce?.toDart;
@JS('nonce')
Expand All @@ -565,10 +539,7 @@ typedef GsiButtonClickListenerFn = void Function(GsiButtonData? gsiButtonData);
///
/// Data type: Credential
/// https://developers.google.com/identity/gsi/web/reference/js-reference#type-Credential
@JS()
@anonymous
@staticInterop
abstract class Credential {
extension type Credential._(JSObject _) implements JSObject {
///
factory Credential({
required String id,
Expand Down Expand Up @@ -620,12 +591,7 @@ typedef RevocationResponseHandlerFn = void Function(
///
/// Data type: RevocationResponse
/// https://developers.google.com/identity/gsi/web/reference/js-reference#RevocationResponse
@JS()
@staticInterop
abstract class RevocationResponse {}

/// The fields that are contained in the [RevocationResponse] object.
extension RevocationResponseExtension on RevocationResponse {
extension type RevocationResponse._(JSObject _) implements JSObject {
/// This field is a boolean value set to true if the revoke method call
/// succeeded or false on failure.
bool get successful => _successful.toDart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
// * non_constant_identifier_names required to be able to use the same parameter
// names as the underlying library.

@JS()
library google_accounts_oauth2;

import 'dart:js_interop';

import 'shared.dart';
Expand All @@ -23,12 +20,7 @@ import 'shared.dart';
external GoogleAccountsOauth2 get oauth2;

/// The Dart definition of the `google.accounts.oauth2` global.
@JS()
@staticInterop
abstract class GoogleAccountsOauth2 {}

/// The `google.accounts.oauth2` methods
extension GoogleAccountsOauth2Extension on GoogleAccountsOauth2 {
extension type GoogleAccountsOauth2._(JSObject _) implements JSObject {
/// Initializes and returns a code client, with the passed-in [config].
///
/// Method: google.accounts.oauth2.initCodeClient
Expand Down Expand Up @@ -97,10 +89,7 @@ extension GoogleAccountsOauth2Extension on GoogleAccountsOauth2 {
///
/// Data type: CodeClientConfig
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeClientConfig
@JS()
@anonymous
@staticInterop
abstract class CodeClientConfig {
extension type CodeClientConfig._(JSObject _) implements JSObject {
/// Constructs a CodeClientConfig object in JavaScript.
///
/// The [callback] property must be a Dart function and not a JS function.
Expand Down Expand Up @@ -161,12 +150,7 @@ abstract class CodeClientConfig {
///
/// Data type: CodeClient
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeClient
@JS()
@staticInterop
abstract class CodeClient {}

/// The methods available on the [CodeClient].
extension CodeClientExtension on CodeClient {
extension type CodeClient._(JSObject _) implements JSObject {
/// Starts the OAuth 2.0 Code UX flow.
external void requestCode();
}
Expand All @@ -175,12 +159,7 @@ extension CodeClientExtension on CodeClient {
///
/// Data type: CodeResponse
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeResponse
@JS()
@staticInterop
abstract class CodeResponse {}

/// The fields that are contained in the code response object.
extension CodeResponseExtension on CodeResponse {
extension type CodeResponse._(JSObject _) implements JSObject {
/// The authorization code of a successful token response.
String? get code => _code?.toDart;
@JS('code')
Expand Down Expand Up @@ -223,10 +202,7 @@ typedef CodeClientCallbackFn = void Function(CodeResponse response);
///
/// Data type: TokenClientConfig
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenClientConfig
@JS()
@anonymous
@staticInterop
abstract class TokenClientConfig {
extension type TokenClientConfig._(JSObject _) implements JSObject {
/// Constructs a TokenClientConfig object in JavaScript.
///
/// The [callback] property must be a Dart function and not a JS function.
Expand Down Expand Up @@ -281,12 +257,7 @@ abstract class TokenClientConfig {
///
/// Data type: TokenClient
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenClient
@JS()
@staticInterop
abstract class TokenClient {}

/// The methods available on the [TokenClient].
extension TokenClientExtension on TokenClient {
extension type TokenClient._(JSObject _) implements JSObject {
/// Starts the OAuth 2.0 Code UX flow.
void requestAccessToken([
OverridableTokenClientConfig? overrideConfig,
Expand All @@ -308,10 +279,7 @@ extension TokenClientExtension on TokenClient {
///
/// Data type: OverridableTokenClientConfig
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#OverridableTokenClientConfig
@JS()
@anonymous
@staticInterop
abstract class OverridableTokenClientConfig {
extension type OverridableTokenClientConfig._(JSObject _) implements JSObject {
/// Constructs an OverridableTokenClientConfig object in JavaScript.
factory OverridableTokenClientConfig({
/// A list of scopes that identify the resources that your application could
Expand Down Expand Up @@ -396,12 +364,7 @@ abstract class OverridableTokenClientConfig {
///
/// Data type: TokenResponse
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenResponse
@JS()
@staticInterop
abstract class TokenResponse {}

/// The fields that are contained in the code response object.
extension TokenResponseExtension on TokenResponse {
extension type TokenResponse._(JSObject _) implements JSObject {
/// The access token of a successful token response.
String? get access_token => _access_token?.toDart;
@JS('access_token')
Expand Down Expand Up @@ -465,12 +428,7 @@ typedef TokenClientCallbackFn = void Function(TokenResponse response);
typedef ErrorCallbackFn = void Function(GoogleIdentityServicesError? error);

/// An error returned by `initTokenClient` or `initDataClient`.
@JS()
@staticInterop
abstract class GoogleIdentityServicesError {}

/// Methods of the GoogleIdentityServicesError object.
extension GoogleIdentityServicesErrorExtension on GoogleIdentityServicesError {
extension type GoogleIdentityServicesError._(JSObject _) implements JSObject {
/// The type of error
GoogleIdentityServicesErrorType get type =>
GoogleIdentityServicesErrorType.values.byName(_type.toDart);
Expand All @@ -492,12 +450,7 @@ typedef RevokeTokenDoneFn = void Function(TokenRevocationResponse response);
///
/// Data type: RevocationResponse
/// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenResponse
@JS()
@staticInterop
abstract class TokenRevocationResponse {}

/// The fields that are contained in the [TokenRevocationResponse] object.
extension TokenRevocationResponseExtension on TokenRevocationResponse {
extension type TokenRevocationResponse._(JSObject _) implements JSObject {
/// This field is a boolean value set to true if the revoke method call
/// succeeded or false on failure.
bool get successful => _successful.toDart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
// Methods here are documented in the Google Identity authentication website,
// but they don't really belong to either the authentication nor authorization
// libraries.
@JS()
library id_load_callback;

import 'dart:js_interop';

Expand All @@ -18,7 +16,6 @@ import 'shared.dart';
*/

@JS('onGoogleLibraryLoad')
@staticInterop
external set _onGoogleLibraryLoad(JSFunction callback);

/// Method called after the Sign In With Google JavaScript library is loaded.
Expand Down
2 changes: 1 addition & 1 deletion packages/google_identity_services_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_identity_services_web
description: A Dart JS-interop layer for Google Identity Services. Google's new sign-in SDK for Web that supports multiple types of credentials.
repository: https://github.com/flutter/packages/tree/main/packages/google_identity_services_web
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_identiy_services_web%22
version: 0.3.2
version: 0.3.3

environment:
sdk: ^3.4.0
Expand Down

0 comments on commit 38b100c

Please sign in to comment.