mirror of
https://github.com/flutter/packages.git
synced 2025-07-02 08:34:31 +08:00
[gis_web] Introduce new GIS SDK JS-Interop package. (#2653)
This commit is contained in:
@ -5,9 +5,9 @@
|
||||
|
||||
# Exclusions
|
||||
#
|
||||
# cross_file
|
||||
# script/configs/linux_only_custom_test.yaml
|
||||
# Custom tests need Chrome. (They run in linux-custom_package_tests)
|
||||
|
||||
dart pub global run flutter_plugin_tools custom-test \
|
||||
--packages-for-branch --log-timing \
|
||||
--exclude=cross_file
|
||||
--exclude=script/configs/linux_only_custom_test.yaml
|
||||
|
@ -261,12 +261,12 @@ task:
|
||||
local_tests_script:
|
||||
# flutter_image
|
||||
# https://github.com/flutter/flutter/issues/100387
|
||||
# cross_file
|
||||
# Custom tests need Chrome. (They run in linux-custom_package_tests)
|
||||
# script/configs/linux_only_custom_test.yaml
|
||||
# Custom tests need Chrome for these packages. (They run in linux-custom_package_tests)
|
||||
- if [[ "$CHANNEL" == "master" ]]; then
|
||||
- ./script/tool_runner.sh custom-test --exclude=cross_file
|
||||
- ./script/tool_runner.sh custom-test --exclude=script/configs/linux_only_custom_test.yaml
|
||||
- else
|
||||
- ./script/tool_runner.sh custom-test --exclude=cross_file,flutter_image
|
||||
- ./script/tool_runner.sh custom-test --exclude=flutter_image,script/configs/linux_only_custom_test.yaml
|
||||
- fi
|
||||
### macOS desktop tasks ###
|
||||
- name: macos-platform_tests
|
||||
|
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@ -37,6 +37,9 @@
|
||||
'p: go_router_builder':
|
||||
- packages/go_router_builder/**/*
|
||||
|
||||
'p: google_identity_services':
|
||||
- packages/google_indentity_services_web/**
|
||||
|
||||
'p: imitation_game':
|
||||
- packages/imitation_game/**/*
|
||||
|
||||
|
7
packages/google_identity_services_web/AUTHORS
Normal file
7
packages/google_identity_services_web/AUTHORS
Normal file
@ -0,0 +1,7 @@
|
||||
# Below is a list of people and organizations that have contributed
|
||||
# to the Flutter project. Names should be added to the list like so:
|
||||
#
|
||||
# Name/Organization <email address>
|
||||
|
||||
Google Inc.
|
||||
The Chromium Authors
|
3
packages/google_identity_services_web/CHANGELOG.md
Normal file
3
packages/google_identity_services_web/CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
||||
## 0.1.0
|
||||
|
||||
* Initial release.
|
25
packages/google_identity_services_web/LICENSE
Normal file
25
packages/google_identity_services_web/LICENSE
Normal file
@ -0,0 +1,25 @@
|
||||
Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
87
packages/google_identity_services_web/README.md
Normal file
87
packages/google_identity_services_web/README.md
Normal file
@ -0,0 +1,87 @@
|
||||
<?code-excerpt path-base="excerpts/packages/google_identity_services_web_example"?>
|
||||
|
||||
# google_identity_services_web
|
||||
|
||||
A JS-interop layer for Google Identity's Sign In With Google SDK.
|
||||
|
||||
See the original JS SDK reference:
|
||||
|
||||
* [Sign In With Google](https://developers.google.com/identity/gsi/web)
|
||||
|
||||
## Usage
|
||||
|
||||
This package is the Dart JS-interop layer of the new **Sign In With Google**
|
||||
SDK. Here's the API references for both of the sub-libraries:
|
||||
|
||||
* `id.dart`: [Sign In With Google JavaScript API reference](https://developers.google.com/identity/gsi/web/reference/js-reference)
|
||||
* `oauth2.dart`: [Google 3P Authorization JavaScript Library for websites - API reference](https://developers.google.com/identity/oauth2/web/reference/js-reference)
|
||||
* `loader.dart`: An (optional) loader mechanism that installs the library and
|
||||
resolves a `Future<void>` when it's ready.
|
||||
|
||||
### Loading the SDK
|
||||
|
||||
There are two ways to load the JS SDK in your app.
|
||||
|
||||
#### Modify your index.html (most performant)
|
||||
|
||||
The most performant way is to modify your `web/index.html` file to insert a
|
||||
script tag [as recommended](https://developers.google.com/identity/gsi/web/guides/client-library).
|
||||
Place the `script` tag in the `<head>` of your site, next to the script tag that
|
||||
loads `flutter.js`, so the browser can downloaded both in parallel:
|
||||
|
||||
<?code-excerpt "../../web/index-with-script-tag.html (script-tag)"?>
|
||||
```html
|
||||
<head>
|
||||
<!-- ··· -->
|
||||
<!-- Include the GSI SDK below -->
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
<!-- This script adds the flutter initialization JS code -->
|
||||
<script src="flutter.js" defer></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
#### With the `loadWebSdk` function (on-demand)
|
||||
|
||||
An alternative way, that downloads the SDK on demand, is to use the
|
||||
**`loadWebSdk`** function provided by the library. A simple location to embed
|
||||
this in a Flutter Web only app can be the `main.dart`:
|
||||
|
||||
<?code-excerpt "main.dart (use-loader)"?>
|
||||
```dart
|
||||
import 'package:google_identity_services_web/loader.dart' as gis;
|
||||
// ···
|
||||
void main() async {
|
||||
await gis.loadWebSdk(); // Load the GIS SDK
|
||||
// The rest of your code...
|
||||
// ···
|
||||
}
|
||||
```
|
||||
|
||||
(Note that the above won't compile for mobile apps, so if you're developing a
|
||||
cross-platform app, you'll probably need to hide the call to `loadWebSdk`
|
||||
behind a [conditional import/export](https://dart.dev/guides/libraries/create-library-packages#conditionally-importing-and-exporting-library-files).)
|
||||
|
||||
### Using the SDK
|
||||
|
||||
Once the SDK has been loaded, it can be used by importing the correct library:
|
||||
|
||||
* `import 'package:google_identity_services/id.dart' as id;` for Authentication
|
||||
* `import 'package:google_identity_services/oauth2.dart' as oauth2;` for
|
||||
Authorization.
|
||||
|
||||
## Browser compatibility
|
||||
|
||||
The new SDK is introducing concepts that are on track for standardization to
|
||||
most browsers, and it might not be compatible with older browsers.
|
||||
|
||||
Refer to the official documentation site for the latest browser compatibility
|
||||
information of the underlying JS SDK:
|
||||
|
||||
* **Sign In With Google > [Supported browsers and platforms](https://developers.google.com/identity/gsi/web/guides/supported-browsers)**
|
||||
|
||||
## Testing
|
||||
|
||||
This web-only package uses `dart:test` to test its features. They can be run
|
||||
with `dart test -p chrome`.
|
||||
|
||||
_(Look at `test/README.md` and `tool/run_tests.dart` for more info.)_
|
6
packages/google_identity_services_web/dart_test.yaml
Normal file
6
packages/google_identity_services_web/dart_test.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments
|
||||
override_platforms:
|
||||
chrome:
|
||||
settings:
|
||||
executable: chrome
|
||||
arguments: --no-sandbox
|
44
packages/google_identity_services_web/example/.gitignore
vendored
Normal file
44
packages/google_identity_services_web/example/.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
45
packages/google_identity_services_web/example/.metadata
Normal file
45
packages/google_identity_services_web/example/.metadata
Normal file
@ -0,0 +1,45 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
channel: master
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: android
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: ios
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: linux
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: macos
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: web
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
- platform: windows
|
||||
create_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
base_revision: 822f6e3595d63f864ae2027ea37fd645b313b71b
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
4
packages/google_identity_services_web/example/README.md
Normal file
4
packages/google_identity_services_web/example/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# google_identity_services_web_example
|
||||
|
||||
* `lib/main.dart`: An example on how to use the google_identiy_services_web `id` library from Dart.
|
||||
* `lib/main_oauth.dart`: An example for the `oauth2` library from the same SDK.
|
@ -0,0 +1,19 @@
|
||||
targets:
|
||||
$default:
|
||||
sources:
|
||||
include:
|
||||
- lib/**
|
||||
- web/**
|
||||
# Some default includes that aren't really used here but will prevent
|
||||
# false-negative warnings:
|
||||
- $package$
|
||||
- lib/$lib$
|
||||
exclude:
|
||||
- '**/.*/**'
|
||||
- '**/build/**'
|
||||
builders:
|
||||
code_excerpter|code_excerpter:
|
||||
enabled: true
|
||||
generate_for:
|
||||
- '**/*.dart'
|
||||
- '**/*.html'
|
56
packages/google_identity_services_web/example/lib/main.dart
Normal file
56
packages/google_identity_services_web/example/lib/main.dart
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'package:google_identity_services_web/id.dart' as id;
|
||||
// #docregion use-loader
|
||||
import 'package:google_identity_services_web/loader.dart' as gis;
|
||||
// #enddocregion use-loader
|
||||
import 'package:js/js.dart' show allowInterop;
|
||||
import 'package:jwt_decoder/jwt_decoder.dart' as jwt;
|
||||
|
||||
// #docregion use-loader
|
||||
void main() async {
|
||||
await gis.loadWebSdk(); // Load the GIS SDK
|
||||
// The rest of your code...
|
||||
// #enddocregion use-loader
|
||||
id.setLogLevel('debug');
|
||||
|
||||
final id.IdConfiguration config = id.IdConfiguration(
|
||||
client_id: 'your-client_id.apps.googleusercontent.com',
|
||||
ux_mode: id.UxMode.popup,
|
||||
callback: allowInterop(onCredentialResponse),
|
||||
);
|
||||
|
||||
id.initialize(config);
|
||||
id.prompt(allowInterop(onPromptMoment));
|
||||
// #docregion use-loader
|
||||
}
|
||||
// #enddocregion use-loader
|
||||
|
||||
/// Handles the ID token returned from the One Tap prompt.
|
||||
/// See: https://developers.google.com/identity/gsi/web/reference/js-reference#callback
|
||||
void onCredentialResponse(id.CredentialResponse o) {
|
||||
final Map<String, dynamic>? payload = jwt.JwtDecoder.tryDecode(o.credential);
|
||||
if (payload != null) {
|
||||
print('Hello, ${payload["name"]}');
|
||||
print(o.select_by);
|
||||
print(payload);
|
||||
} else {
|
||||
print('Could not decode ${o.credential}');
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles Prompt UI status notifications.
|
||||
/// See: https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.prompt
|
||||
void onPromptMoment(id.PromptMomentNotification o) {
|
||||
final id.MomentType type = o.getMomentType();
|
||||
print(type.runtimeType);
|
||||
print(type);
|
||||
print(type.index);
|
||||
print(o.getDismissedReason());
|
||||
print(o.getNotDisplayedReason());
|
||||
print(o.getSkippedReason());
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'package:google_identity_services_web/id.dart' as id show setLogLevel;
|
||||
import 'package:google_identity_services_web/loader.dart' as gis;
|
||||
import 'package:google_identity_services_web/oauth2.dart' as oauth2;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:js/js.dart' show allowInterop;
|
||||
|
||||
/// The scopes to be requested
|
||||
const List<String> scopes = <String>[
|
||||
'email',
|
||||
'profile',
|
||||
'https://www.googleapis.com/auth/contacts.readonly',
|
||||
];
|
||||
|
||||
void main() async {
|
||||
await gis.loadWebSdk(); // Load the GIS SDK
|
||||
|
||||
id.setLogLevel('debug');
|
||||
|
||||
final oauth2.TokenClientConfig config = oauth2.TokenClientConfig(
|
||||
client_id: 'your-client_id.apps.googleusercontent.com',
|
||||
scope: scopes.join(' '),
|
||||
callback: allowInterop(onTokenResponse),
|
||||
);
|
||||
|
||||
final oauth2.OverridableTokenClientConfig overridableCfg =
|
||||
oauth2.OverridableTokenClientConfig(
|
||||
prompt: '',
|
||||
);
|
||||
|
||||
final oauth2.TokenClient client = oauth2.initTokenClient(config);
|
||||
|
||||
// Disable the Popup Blocker for this to work, or move this to a Button press.
|
||||
client.requestAccessToken(overridableCfg);
|
||||
}
|
||||
|
||||
/// Handles the returned (auth) token response.
|
||||
/// See: https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenResponse
|
||||
Future<void> onTokenResponse(oauth2.TokenResponse response) async {
|
||||
if (response.error != null) {
|
||||
print('Authorization error!');
|
||||
print(response.error);
|
||||
print(response.error_description);
|
||||
print(response.error_uri);
|
||||
return;
|
||||
}
|
||||
|
||||
// Has granted all the scopes?
|
||||
if (!oauth2.hasGrantedAllScopes(response, scopes[2])) {
|
||||
print('The user has NOT granted the required scope!');
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to do a request to the `people` API
|
||||
final http.Response apiResponse = await http.get(
|
||||
Uri.parse('https://people.googleapis.com/v1/people/me/connections'
|
||||
'?requestMask.includeField=person.names'),
|
||||
headers: <String, String>{
|
||||
'Authorization': '${response.token_type} ${response.access_token}',
|
||||
},
|
||||
);
|
||||
if (apiResponse.statusCode == 200) {
|
||||
print('People API ${apiResponse.statusCode} OK!');
|
||||
} else {
|
||||
print(
|
||||
'People API ${apiResponse.statusCode} Oops! Something wrong happened!');
|
||||
}
|
||||
print(apiResponse.body);
|
||||
|
||||
print('Revoking token...');
|
||||
oauth2.revokeToken(response.access_token, allowInterop((String status) {
|
||||
print(status);
|
||||
}));
|
||||
}
|
24
packages/google_identity_services_web/example/pubspec.yaml
Normal file
24
packages/google_identity_services_web/example/pubspec.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
name: google_identity_services_web_example
|
||||
description: An example for the google_identity_services_web package, OneTap.
|
||||
publish_to: 'none'
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
google_identity_services_web:
|
||||
path: ../
|
||||
http: ^0.13.5
|
||||
js: ^0.6.4
|
||||
jwt_decoder: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.1.10 # To extract README excerpts only.
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
BIN
packages/google_identity_services_web/example/web/favicon.png
Normal file
BIN
packages/google_identity_services_web/example/web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 917 B |
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the LICENSE file. -->
|
||||
<html>
|
||||
<!--#docregion script-tag-->
|
||||
<head>
|
||||
<!--#enddocregion script-tag-->
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="example">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<title>Authentication Example</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<script>
|
||||
// The value below is injected by flutter build, do not touch.
|
||||
var serviceWorkerVersion = null;
|
||||
</script>
|
||||
<!--#docregion script-tag-->
|
||||
<!-- Include the GSI SDK below -->
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
<!-- This script adds the flutter initialization JS code -->
|
||||
<script src="flutter.js" defer></script>
|
||||
</head>
|
||||
<!--#enddocregion script-tag-->
|
||||
<body>
|
||||
<script>
|
||||
window.addEventListener('load', function(ev) {
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: function(engineInitializer) {
|
||||
engineInitializer.autoStart();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
51
packages/google_identity_services_web/example/web/index.html
Normal file
51
packages/google_identity_services_web/example/web/index.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style license that can be
|
||||
found in the LICENSE file. -->
|
||||
<html>
|
||||
<head>
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="example">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<title>Authentication Example</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<script>
|
||||
// The value below is injected by flutter build, do not touch.
|
||||
var serviceWorkerVersion = null;
|
||||
</script>
|
||||
<!-- Trusted Types API config (disabled) -->
|
||||
<!-- <meta http-equiv="Content-Security-Policy" content="trusted-types;"> -->
|
||||
<!-- Load the GSI SDK -->
|
||||
<!-- <script src="https://accounts.google.com/gsi/client" async defer></script> -->
|
||||
<!-- This script adds the flutter initialization JS code -->
|
||||
<script src="flutter.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.addEventListener('load', function(ev) {
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: function(engineInitializer) {
|
||||
engineInitializer.autoStart();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "example",
|
||||
"short_name": "example",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export 'loader.dart';
|
14
packages/google_identity_services_web/lib/id.dart
Normal file
14
packages/google_identity_services_web/lib/id.dart
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export 'src/js_interop/google_accounts_id.dart';
|
||||
export 'src/js_interop/shared.dart'
|
||||
show
|
||||
CredentialSelectBy,
|
||||
MomentDismissedReason,
|
||||
MomentNotDisplayedReason,
|
||||
MomentSkippedReason,
|
||||
MomentType,
|
||||
OneTapContext,
|
||||
UxMode;
|
5
packages/google_identity_services_web/lib/loader.dart
Normal file
5
packages/google_identity_services_web/lib/loader.dart
Normal file
@ -0,0 +1,5 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export 'src/js_loader.dart' show TrustedTypesException, loadWebSdk;
|
6
packages/google_identity_services_web/lib/oauth2.dart
Normal file
6
packages/google_identity_services_web/lib/oauth2.dart
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
export 'src/js_interop/google_accounts_oauth2.dart';
|
||||
export 'src/js_interop/shared.dart' show UxMode;
|
@ -0,0 +1,164 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/*
|
||||
// DOM shim. This file contains everything we need from the DOM API written as
|
||||
// @staticInterop, so we don't need dart:html
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/
|
||||
*/
|
||||
|
||||
import 'package:js/js.dart';
|
||||
|
||||
/// Document interface
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomHtmlDocument {}
|
||||
|
||||
/// Some methods of document
|
||||
extension DomHtmlDocumentExtension on DomHtmlDocument {
|
||||
/// document.head
|
||||
external DomHtmlElement get head;
|
||||
|
||||
/// document.createElement
|
||||
external DomHtmlElement createElement(String tagName);
|
||||
}
|
||||
|
||||
/// console interface
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomConsole {}
|
||||
|
||||
/// The interface of window.console
|
||||
extension DomConsoleExtension on DomConsole {
|
||||
/// console.debug
|
||||
external DomConsoleDumpFn get debug;
|
||||
|
||||
/// console.info
|
||||
external DomConsoleDumpFn get info;
|
||||
|
||||
/// console.log
|
||||
external DomConsoleDumpFn get log;
|
||||
|
||||
/// console.warn
|
||||
external DomConsoleDumpFn get warn;
|
||||
|
||||
/// console.error
|
||||
external DomConsoleDumpFn get error;
|
||||
}
|
||||
|
||||
/// Fakey variadic-type for console-dumping methods (like console.log or info).
|
||||
typedef DomConsoleDumpFn = void Function(
|
||||
Object? arg, [
|
||||
Object? arg2,
|
||||
Object? arg3,
|
||||
Object? arg4,
|
||||
Object? arg5,
|
||||
Object? arg6,
|
||||
Object? arg7,
|
||||
Object? arg8,
|
||||
Object? arg9,
|
||||
Object? arg10,
|
||||
]);
|
||||
|
||||
/// An instance of an HTMLElement
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomHtmlElement {}
|
||||
|
||||
/// (Some) methods of HtmlElement
|
||||
extension DomHtmlElementExtension on DomHtmlElement {
|
||||
/// Node.appendChild
|
||||
external DomHtmlElement appendChild(DomHtmlElement child);
|
||||
}
|
||||
|
||||
/// An instance of an HTMLScriptElement
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomHtmlScriptElement extends DomHtmlElement {}
|
||||
|
||||
/// Some methods exclusive of Script elements
|
||||
extension DomHtmlScriptElementExtension on DomHtmlScriptElement {
|
||||
external set src(Object stringOrSafeScriptURL);
|
||||
external set async(bool async);
|
||||
external set defer(bool defer);
|
||||
}
|
||||
|
||||
/*
|
||||
// Trusted Types API (TrustedTypePolicy, TrustedScript, TrustedScriptURL)
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypesAPI
|
||||
*/
|
||||
|
||||
/// A factory to create `TrustedTypePolicy` objects.
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomTrustedTypePolicyFactory {}
|
||||
|
||||
/// (Some) methods of the [DomTrustedTypePolicyFactory]:
|
||||
extension DomTrustedTypePolicyFactoryExtension on DomTrustedTypePolicyFactory {
|
||||
/// createPolicy
|
||||
external DomTrustedTypePolicy createPolicy(
|
||||
String policyName,
|
||||
DomTrustedTypePolicyOptions? policyOptions,
|
||||
);
|
||||
}
|
||||
|
||||
/// Options to create a trusted type policy.
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomTrustedTypePolicyOptions {
|
||||
/// Constructs a TrustedPolicyOptions object in JavaScript.
|
||||
///
|
||||
/// The following properties need to be manually wrapped in [allowInterop]
|
||||
/// before being passed to this constructor: [createScriptURL].
|
||||
external factory DomTrustedTypePolicyOptions({
|
||||
DomCreateScriptUrlOptionFn? createScriptURL,
|
||||
});
|
||||
}
|
||||
|
||||
/// Type of the function to configure createScriptURL
|
||||
typedef DomCreateScriptUrlOptionFn = String Function(String input);
|
||||
|
||||
/// An instance of a TrustedTypePolicy
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomTrustedTypePolicy {}
|
||||
|
||||
/// (Some) methods of the [DomTrustedTypePolicy]
|
||||
extension DomTrustedTypePolicyExtension on DomTrustedTypePolicy {
|
||||
/// Create a `TrustedScriptURL` for the given [input].
|
||||
external DomTrustedScriptUrl createScriptURL(String input);
|
||||
}
|
||||
|
||||
/// An instance of a DomTrustedScriptUrl
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
abstract class DomTrustedScriptUrl {}
|
||||
|
||||
// Getters
|
||||
|
||||
/// window.document
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
external DomHtmlDocument get document;
|
||||
|
||||
/// window.trustedTypes (may or may not be supported by the browser)
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
external DomTrustedTypePolicyFactory? get trustedTypes;
|
||||
|
||||
/// window.console
|
||||
@JS()
|
||||
@staticInterop
|
||||
@anonymous
|
||||
external DomConsole get console;
|
@ -0,0 +1,440 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Authentication. API reference:
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference
|
||||
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// * non_constant_identifier_names required to be able to use the same parameter
|
||||
// names as the underlying library.
|
||||
|
||||
@JS('google.accounts.id')
|
||||
library id;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
|
||||
import 'shared.dart';
|
||||
|
||||
/// An undocumented method. Try with 'debug'.
|
||||
@JS()
|
||||
external SetLogLevelFn get setLogLevel;
|
||||
|
||||
///
|
||||
typedef SetLogLevelFn = void Function(String level);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.initialize
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.initialize
|
||||
*/
|
||||
|
||||
/// Initializes the Sign In With Google client based on [IdConfiguration].
|
||||
///
|
||||
/// The `initialize` method creates a Sign In With Google client instance that
|
||||
/// can be implicitly used by all modules in the same web page.
|
||||
///
|
||||
/// * You only need to call the `initialize` method once even if you use
|
||||
/// multiple modules (like One Tap, Personalized button, revocation, etc.) in
|
||||
/// the same web page.
|
||||
/// * If you do call the google.accounts.id.initialize method multiple times,
|
||||
/// only the configurations in the last call will be remembered and used.
|
||||
///
|
||||
/// You actually reset the configurations whenever you call the `initialize`
|
||||
/// method, and all subsequent methods in the same web page will use the new
|
||||
/// configurations immediately.
|
||||
///
|
||||
/// WARNING: The `initialize` method should be called only once, even if you
|
||||
/// use both One Tap and button in the same web page.
|
||||
@JS()
|
||||
external InitializeFn get initialize;
|
||||
|
||||
/// The type of the [initialize] function.
|
||||
typedef InitializeFn = void Function(IdConfiguration idConfiguration);
|
||||
|
||||
/*
|
||||
// Data type: IdConfiguration
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#IdConfiguration
|
||||
*/
|
||||
|
||||
/// The configuration object for the [initialize] method.
|
||||
@JS()
|
||||
@anonymous
|
||||
@staticInterop
|
||||
abstract class IdConfiguration {
|
||||
/// Constructs a IdConfiguration object in JavaScript.
|
||||
///
|
||||
/// The following properties need to be manually wrapped in [allowInterop]
|
||||
/// before being passed to this constructor: [callback], [native_callback],
|
||||
/// and [intermediate_iframe_close_callback].
|
||||
external factory IdConfiguration({
|
||||
/// Your application's client ID, which is found and created in the Google
|
||||
/// Developers Console.
|
||||
required String client_id,
|
||||
|
||||
/// Determines if an ID token is automatically returned without any user
|
||||
/// interaction when there's only one Google session that has approved your
|
||||
/// app before. The default value is `false`.
|
||||
bool? auto_select,
|
||||
|
||||
/// The function that handles the ID token returned from the One Tap prompt
|
||||
/// or the pop-up window. This attribute is required if Google One Tap or
|
||||
/// the Sign In With Google button `popup` UX mode is used.
|
||||
CallbackFn? callback,
|
||||
|
||||
/// This attribute is the URI of your login endpoint. May be omitted if the
|
||||
/// current page is your login page, in which case the credential is posted
|
||||
/// to this page by default.
|
||||
///
|
||||
/// The ID token credential response is posted to your login endpoint when
|
||||
/// a user clicks on the Sign In With Google button and `redirect` UX mode
|
||||
/// is used.
|
||||
///
|
||||
/// Your login endpoint must handle POST requests containing a credential
|
||||
/// key with an ID token value in the body.
|
||||
Uri? login_uri,
|
||||
|
||||
/// The function that handles the password credential returned from the
|
||||
/// browser's native credential manager.
|
||||
NativeCallbackFn? native_callback,
|
||||
|
||||
/// Whether or not to cancel the One Tap request if a user clicks outside
|
||||
/// the prompt. The default value is `true`.
|
||||
bool? cancel_on_tap_outside,
|
||||
|
||||
/// The DOM ID of the container element. If it's not set, the One Tap prompt
|
||||
/// is displayed in the top-right corner of the window.
|
||||
String? prompt_parent_id,
|
||||
|
||||
/// A random string used by the ID token to prevent replay attacks.
|
||||
///
|
||||
/// Nonce length is limited to the maximum JWT size supported by your
|
||||
/// environment, and individual browser and server HTTP size constraints.
|
||||
String? nonce,
|
||||
|
||||
/// Changes the text of the title and messages in the One Tap prompt.
|
||||
OneTapContext? context,
|
||||
|
||||
/// If you need to display One Tap in the parent domain and its subdomains,
|
||||
/// pass the parent domain to this field so that a single shared-state
|
||||
/// cookie is used.
|
||||
///
|
||||
/// See: https://developers.google.com/identity/gsi/web/guides/subdomains
|
||||
String? state_cookie_domain,
|
||||
|
||||
/// Set the UX flow used by the Sign In With Google button. The default
|
||||
/// value is `popup`. **This attribute has no impact on the OneTap UX.**
|
||||
UxMode? ux_mode,
|
||||
|
||||
/// The origins that are allowed to embed the intermediate iframe. One Tap
|
||||
/// will run in the intermediate iframe mode if this field presents.
|
||||
///
|
||||
/// Wildcard prefixes are also supported. Wildcard domains must begin with
|
||||
/// a secure `https://` scheme, otherwise they'll be considered invalid.
|
||||
List<String>? allowed_parent_origin,
|
||||
|
||||
/// Overrides the default intermediate iframe behavior when users manually
|
||||
/// close One Tap by tapping on the 'X' button in the One Tap UI. The
|
||||
/// default behavior is to remove the intermediate iframe from the DOM
|
||||
/// immediately.
|
||||
///
|
||||
/// The `intermediate_iframe_close_callback` field takes effect only in
|
||||
/// intermediate iframe mode. And it has impact only to the intermediate
|
||||
/// iframe, instead of the One Tap iframe. The One Tap UI is removed before
|
||||
/// the callback is invoked.
|
||||
Function? intermediate_iframe_close_callback,
|
||||
|
||||
/// determines if the upgraded One Tap UX should be enabled on browsers
|
||||
/// that support Intelligent Tracking Prevention (ITP). The default value
|
||||
/// is false.
|
||||
///
|
||||
/// See: https://developers.google.com/identity/gsi/web/guides/features#upgraded_ux_on_itp_browsers
|
||||
bool? itp_support,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.prompt
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.prompt
|
||||
*/
|
||||
|
||||
/// The `prompt` method displays the One Tap prompt or the browser native
|
||||
/// credential manager after the [initialize] method is invoked.
|
||||
///
|
||||
/// Normally, the `prompt` method is called on page load. Due to the session
|
||||
/// status and user settings on the Google side, the One Tap prompt UI might
|
||||
/// not be displayed. To get notified on the UI status for different moments,
|
||||
/// pass a [PromptMomentListenerFn] to receive UI status notifications.
|
||||
///
|
||||
/// Notifications are fired on the following moments:
|
||||
///
|
||||
/// * Display moment: This occurs after the `prompt` method is called. The
|
||||
/// notification contains a boolean value to indicate whether the UI is
|
||||
/// displayed or not.
|
||||
/// * Skipped moment: This occurs when the One Tap prompt is closed by an auto
|
||||
/// cancel, a manual cancel, or when Google fails to issue a credential, such
|
||||
/// as when the selected session has signed out of Google.
|
||||
/// In these cases, we recommend that you continue on to the next identity
|
||||
/// providers, if there are any.
|
||||
/// * Dismissed moment: This occurs when Google successfully retrieves a
|
||||
/// credential or a user wants to stop the credential retrieval flow. For
|
||||
/// example, when the user begins to input their username and password in
|
||||
/// your login dialog, you can call the [cancel] method to close the One Tap
|
||||
/// prompt and trigger a dismissed moment.
|
||||
///
|
||||
/// WARNING: When on a dismissed moment, do not try any of the next identity
|
||||
/// providers.
|
||||
@JS()
|
||||
external PromptFn get prompt;
|
||||
|
||||
/// The type of the [prompt] function.
|
||||
///
|
||||
/// The [momentListener] parameter must be manually wrapped in [allowInterop]
|
||||
/// before being passed to the [prompt] function.
|
||||
typedef PromptFn = void Function(PromptMomentListenerFn? momentListener);
|
||||
|
||||
/// The type of the function that can be passed to [prompt] to listen for [PromptMomentNotification]s.
|
||||
typedef PromptMomentListenerFn = void Function(PromptMomentNotification moment);
|
||||
|
||||
/*
|
||||
// Data type: PromptMomentNotification
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#PromptMomentNotification
|
||||
*/
|
||||
|
||||
/// A moment (status) notification from the [prompt] method.
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class PromptMomentNotification {}
|
||||
|
||||
/// The methods of the [PromptMomentNotification] data type:
|
||||
extension PromptMomentNotificationExtension on PromptMomentNotification {
|
||||
/// Is this notification for a display moment?
|
||||
external bool isDisplayMoment();
|
||||
|
||||
/// Is this notification for a display moment, and the UI is displayed?
|
||||
external bool isDisplayed();
|
||||
|
||||
/// Is this notification for a display moment, and the UI isn't displayed?
|
||||
external bool isNotDisplayed();
|
||||
|
||||
/// Is this notification for a skipped moment?
|
||||
external bool isSkippedMoment();
|
||||
|
||||
/// Is this notification for a dismissed moment?
|
||||
external bool isDismissedMoment();
|
||||
@JS('getMomentType')
|
||||
external String _getMomentType();
|
||||
@JS('getNotDisplayedReason')
|
||||
external String? _getNotDisplayedReason();
|
||||
@JS('getSkippedReason')
|
||||
external String? _getSkippedReason();
|
||||
@JS('getDismissedReason')
|
||||
external String? _getDismissedReason();
|
||||
|
||||
/// The moment type.
|
||||
MomentType getMomentType() => MomentType.values.byName(_getMomentType());
|
||||
|
||||
/// The detailed reason why the UI isn't displayed.
|
||||
MomentNotDisplayedReason? getNotDisplayedReason() =>
|
||||
maybeEnum(_getNotDisplayedReason(), MomentNotDisplayedReason.values);
|
||||
|
||||
/// The detailed reason for the skipped moment.
|
||||
MomentSkippedReason? getSkippedReason() =>
|
||||
maybeEnum(_getSkippedReason(), MomentSkippedReason.values);
|
||||
|
||||
/// The detailed reason for the dismissal.
|
||||
MomentDismissedReason? getDismissedReason() =>
|
||||
maybeEnum(_getDismissedReason(), MomentDismissedReason.values);
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: CredentialResponse
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#CredentialResponse
|
||||
*/
|
||||
|
||||
/// The object passed as the parameter of your [CallbackFn].
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class CredentialResponse {}
|
||||
|
||||
/// The fields that are contained in the credential response object.
|
||||
extension CredentialResponseExtension on CredentialResponse {
|
||||
/// This field is the ID token as a base64-encoded JSON Web Token (JWT)
|
||||
/// string.
|
||||
///
|
||||
/// See more: https://developers.google.com/identity/gsi/web/reference/js-reference#credential
|
||||
external String get credential;
|
||||
@JS('select_by')
|
||||
external String get _select_by;
|
||||
|
||||
/// This field sets how the credential was selected.
|
||||
///
|
||||
/// The type of button used along with the session and consent state are used
|
||||
/// to set the value.
|
||||
///
|
||||
/// See more: https://developers.google.com/identity/gsi/web/reference/js-reference#select_by
|
||||
CredentialSelectBy get select_by =>
|
||||
CredentialSelectBy.values.byName(_select_by);
|
||||
}
|
||||
|
||||
/// The type of the `callback` used to create an [IdConfiguration].
|
||||
///
|
||||
/// Describes a JavaScript function that handles ID tokens from
|
||||
/// [CredentialResponse]s.
|
||||
///
|
||||
/// Google One Tap and the Sign In With Google button popup UX mode use this
|
||||
/// attribute.
|
||||
typedef CallbackFn = void Function(CredentialResponse credentialResponse);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.renderButton
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.renderButton
|
||||
//
|
||||
// Data type: GsiButtonConfiguration
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#GsiButtonConfiguration
|
||||
//
|
||||
// Question: Do we need to implement renderButton and its options?
|
||||
*/
|
||||
|
||||
/*
|
||||
// Data type: Credential
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#type-Credential
|
||||
*/
|
||||
|
||||
/// The object passed to the [NativeCallbackFn]. Represents a PasswordCredential
|
||||
/// that was returned by the Browser.
|
||||
///
|
||||
/// `Credential` objects can also be programmatically created to be stored
|
||||
/// in the browser through the [storeCredential] method.
|
||||
///
|
||||
/// See also: https://developer.mozilla.org/en-US/docs/Web/API/PasswordCredential/PasswordCredential
|
||||
@JS()
|
||||
@anonymous
|
||||
@staticInterop
|
||||
abstract class Credential {
|
||||
///
|
||||
external factory Credential({
|
||||
required String id,
|
||||
required String password,
|
||||
});
|
||||
}
|
||||
|
||||
/// The fields that are contained in the [Credential] object.
|
||||
extension CredentialExtension on Credential {
|
||||
/// Identifies the user.
|
||||
external String get id;
|
||||
|
||||
/// The password.
|
||||
external String get password;
|
||||
}
|
||||
|
||||
/// The type of the `native_callback` used to create an [IdConfiguration].
|
||||
///
|
||||
/// Describes a JavaScript function that handles password [Credential]s coming
|
||||
/// from the native Credential manager of the user's browser.
|
||||
typedef NativeCallbackFn = void Function(Credential credential);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.disableAutoselect
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.disableAutoSelect
|
||||
*/
|
||||
|
||||
/// When the user signs out of your website, you need to call this method to
|
||||
/// record the status in cookies.
|
||||
///
|
||||
/// This prevents a UX dead loop.
|
||||
@JS()
|
||||
external VoidFn get disableAutoSelect;
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.storeCredential
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.storeCredential
|
||||
*/
|
||||
|
||||
/// This method is a simple wrapper for the `store` method of the browser's
|
||||
/// native credential manager API.
|
||||
///
|
||||
/// It can only be used to store a Password [Credential].
|
||||
///
|
||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/store
|
||||
@JS()
|
||||
external StoreCredentialFn get storeCredential;
|
||||
|
||||
/// The type of the [storeCredential] function.
|
||||
///
|
||||
/// The [callback] parameter must be manually wrapped in [allowInterop]
|
||||
/// before being passed to the [storeCredential] function.
|
||||
// Question: What's the type of the callback function??? VoidFn?
|
||||
typedef StoreCredentialFn = void Function(
|
||||
Credential credential,
|
||||
Function? callback,
|
||||
);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.cancel
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.cancel
|
||||
*/
|
||||
|
||||
/// You can cancel the One Tap flow if you remove the prompt from the relying
|
||||
/// party DOM. The cancel operation is ignored if a credential is already
|
||||
/// selected.
|
||||
@JS()
|
||||
external VoidFn get cancel;
|
||||
|
||||
/*
|
||||
// Library load callback: onGoogleLibraryLoad
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#onGoogleLibraryLoad
|
||||
// See: `load_callback.dart` and `loader.dart`
|
||||
*/
|
||||
|
||||
/*
|
||||
// Method: google.accounts.id.revoke
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#google.accounts.id.revoke
|
||||
*/
|
||||
|
||||
/// The `revoke` method revokes the OAuth grant used to share the ID token for
|
||||
/// the specified user.
|
||||
@JS()
|
||||
external RevokeFn get revoke;
|
||||
|
||||
/// The type of the [revoke] function.
|
||||
///
|
||||
/// [hint] is the email address or unique ID of the user's Google Account. The
|
||||
/// ID is the `sub` property of the [CredentialResponse.credential] payload.
|
||||
///
|
||||
/// The optional [callback] is a function that gets called to report on the
|
||||
/// success of the revocation call.
|
||||
///
|
||||
/// The [callback] parameter must be manually wrapped in [allowInterop]
|
||||
/// before being passed to the [revoke] function.
|
||||
typedef RevokeFn = void Function(
|
||||
String hint,
|
||||
RevocationResponseHandlerFn? callback,
|
||||
);
|
||||
|
||||
/// The type of the `callback` function passed to [revoke], to be notified of
|
||||
/// the success of the revocation operation.
|
||||
typedef RevocationResponseHandlerFn = void Function(
|
||||
RevocationResponse revocationResponse,
|
||||
);
|
||||
|
||||
/*
|
||||
// Data type: RevocationResponse
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#RevocationResponse
|
||||
*/
|
||||
|
||||
/// The parameter passed to the optional [RevocationResponseHandlerFn]
|
||||
/// `callback` of the [revoke] function.
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class RevocationResponse {}
|
||||
|
||||
/// The fields that are contained in the [RevocationResponse] object.
|
||||
extension RevocationResponseExtension on RevocationResponse {
|
||||
/// This field is a boolean value set to true if the revoke method call
|
||||
/// succeeded or false on failure.
|
||||
external bool get successful;
|
||||
|
||||
/// This field is a string value and contains a detailed error message if the
|
||||
/// revoke method call failed, it is undefined on success.
|
||||
external String? get error;
|
||||
}
|
@ -0,0 +1,339 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Authorization. API reference:
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference
|
||||
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// * non_constant_identifier_names required to be able to use the same parameter
|
||||
// names as the underlying library.
|
||||
|
||||
@JS('google.accounts.oauth2')
|
||||
library oauth2;
|
||||
|
||||
import 'package:js/js.dart';
|
||||
|
||||
import 'shared.dart';
|
||||
|
||||
// Code Client
|
||||
|
||||
/*
|
||||
// Method: google.accounts.oauth2.initCodeClient
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#google.accounts.oauth2.initCodeClient
|
||||
*/
|
||||
|
||||
/// The initCodeClient method initializes and returns a code client, with the
|
||||
/// passed-in [config].
|
||||
@JS()
|
||||
external InitCodeClientFn get initCodeClient;
|
||||
|
||||
/// The type of the [initCodeClient] function.
|
||||
typedef InitCodeClientFn = CodeClient Function(CodeClientConfig config);
|
||||
|
||||
/*
|
||||
// Data type: CodeClientConfig
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeClientConfig
|
||||
*/
|
||||
|
||||
/// The configuration object for the [initCodeClient] method.
|
||||
@JS()
|
||||
@anonymous
|
||||
@staticInterop
|
||||
abstract class CodeClientConfig {
|
||||
/// Constructs a CodeClientConfig object in JavaScript.
|
||||
///
|
||||
/// The [callback] property must be wrapped in [allowInterop] before it's
|
||||
/// passed to this constructor.
|
||||
external factory CodeClientConfig({
|
||||
required String client_id,
|
||||
required String scope,
|
||||
String? redirect_uri,
|
||||
bool? auto_select,
|
||||
CodeClientCallbackFn? callback,
|
||||
String? state,
|
||||
bool? enable_serial_consent,
|
||||
String? hint,
|
||||
String? hosted_domain,
|
||||
UxMode? ux_mode,
|
||||
bool? select_account,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: CodeClient
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeClient
|
||||
*/
|
||||
|
||||
/// A client that can start the OAuth 2.0 Code UX flow.
|
||||
///
|
||||
/// See: https://developers.google.com/identity/oauth2/web/guides/use-code-model
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class CodeClient {}
|
||||
|
||||
/// The methods available on the [CodeClient].
|
||||
extension CodeClientExtension on CodeClient {
|
||||
/// Starts the OAuth 2.0 Code UX flow.
|
||||
external void requestCode();
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: CodeResponse
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#CodeResponse
|
||||
*/
|
||||
|
||||
/// The object passed as the parameter of your [CodeClientCallbackFn].
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class CodeResponse {}
|
||||
|
||||
/// The fields that are contained in the code response object.
|
||||
extension CodeResponseExtension on CodeResponse {
|
||||
/// The authorization code of a successful token response.
|
||||
external String get code;
|
||||
|
||||
/// A space-delimited list of scopes that are approved by the user.
|
||||
external String get scope;
|
||||
|
||||
/// The string value that your application uses to maintain state between your
|
||||
/// authorization request and the response.
|
||||
external String get state;
|
||||
|
||||
/// A single ASCII error code.
|
||||
external String? get error;
|
||||
|
||||
/// Human-readable ASCII text providing additional information, used to assist
|
||||
/// the client developer in understanding the error that occurred.
|
||||
external String? get error_description;
|
||||
|
||||
/// A URI identifying a human-readable web page with information about the
|
||||
/// error, used to provide the client developer with additional information
|
||||
/// about the error.
|
||||
external String? get error_uri;
|
||||
}
|
||||
|
||||
/// The type of the `callback` function passed to [CodeClientConfig].
|
||||
typedef CodeClientCallbackFn = void Function(CodeResponse response);
|
||||
|
||||
// Token Client
|
||||
|
||||
/*
|
||||
// Method: google.accounts.oauth2.initTokenClient
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#google.accounts.oauth2.initTokenClient
|
||||
*/
|
||||
|
||||
/// The initCodeClient method initializes and returns a code client, with the
|
||||
/// passed-in [config].
|
||||
@JS()
|
||||
external InitTokenClientFn get initTokenClient;
|
||||
|
||||
/// The type of the [initCodeClient] function.
|
||||
typedef InitTokenClientFn = TokenClient Function(TokenClientConfig config);
|
||||
|
||||
/*
|
||||
// Data type: TokenClientConfig
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenClientConfig
|
||||
*/
|
||||
|
||||
/// The configuration object for the [initTokenClient] method.
|
||||
@JS()
|
||||
@anonymous
|
||||
@staticInterop
|
||||
abstract class TokenClientConfig {
|
||||
/// Constructs a TokenClientConfig object in JavaScript.
|
||||
///
|
||||
/// The [callback] property must be wrapped in [allowInterop] before it's
|
||||
/// passed to this constructor.
|
||||
external factory TokenClientConfig({
|
||||
required String client_id,
|
||||
required TokenClientCallbackFn? callback,
|
||||
required String scope,
|
||||
String? prompt,
|
||||
bool? enable_serial_consent,
|
||||
String? hint,
|
||||
String? hosted_domain,
|
||||
String? state,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: TokenClient
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenClient
|
||||
*/
|
||||
|
||||
/// A client that can start the OAuth 2.0 Token UX flow.
|
||||
///
|
||||
/// See: https://developers.google.com/identity/oauth2/web/guides/use-token-model
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class TokenClient {}
|
||||
|
||||
/// The methods available on the [TokenClient].
|
||||
extension TokenClientExtension on TokenClient {
|
||||
/// Starts the OAuth 2.0 Code UX flow.
|
||||
external void requestAccessToken([
|
||||
OverridableTokenClientConfig overrideConfig,
|
||||
]);
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: OverridableTokenClientConfig
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#OverridableTokenClientConfig
|
||||
*/
|
||||
|
||||
/// The overridable configuration object for the
|
||||
/// [TokenClientExtension.requestAccessToken] method.
|
||||
@JS()
|
||||
@anonymous
|
||||
@staticInterop
|
||||
abstract class OverridableTokenClientConfig {
|
||||
/// Constructs an OverridableTokenClientConfig object in JavaScript.
|
||||
///
|
||||
/// The [callback] property must be wrapped in [allowInterop] before it's
|
||||
/// passed to this constructor.
|
||||
external factory OverridableTokenClientConfig({
|
||||
/// A space-delimited, case-sensitive list of prompts to present the user.
|
||||
///
|
||||
/// See `prompt` in [TokenClientConfig].
|
||||
String? prompt,
|
||||
|
||||
/// For clients created before 2019, when set to `false`, disables "more
|
||||
/// granular Google Account permissions".
|
||||
///
|
||||
/// This setting has no effect in newer clients.
|
||||
///
|
||||
/// See: https://developers.googleblog.com/2018/10/more-granular-google-account.html
|
||||
bool? enable_serial_consent,
|
||||
|
||||
/// When your app knows which user it is trying to authenticate, it can
|
||||
/// provide this parameter as a hint to the authentication server. Passing
|
||||
/// this hint suppresses the account chooser and either pre-fills the email
|
||||
/// box on the sign-in form, or selects the proper session (if the user is
|
||||
/// using multiple sign-in), which can help you avoid problems that occur if
|
||||
/// your app logs in the wrong user account.
|
||||
///
|
||||
/// The value can be either an email address or the `sub` string, which is
|
||||
/// equivalent to the user's Google ID.
|
||||
///
|
||||
/// About Multiple Sign-in: https://support.google.com/accounts/answer/1721977
|
||||
String? hint,
|
||||
|
||||
/// **Not recommended.** Specifies any string value that your application
|
||||
/// uses to maintain state between your authorization request and the
|
||||
/// authorization server's response.
|
||||
String? state,
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
// Data type: TokenResponse
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#TokenResponse
|
||||
*/
|
||||
|
||||
/// The object passed as the parameter of your [TokenClientCallbackFn].
|
||||
@JS()
|
||||
@staticInterop
|
||||
abstract class TokenResponse {}
|
||||
|
||||
/// The fields that are contained in the code response object.
|
||||
extension TokenResponseExtension on TokenResponse {
|
||||
/// The access token of a successful token response.
|
||||
external String get access_token;
|
||||
|
||||
/// The lifetime in seconds of the access token.
|
||||
external int get expires_in;
|
||||
|
||||
/// The hosted domain the signed-in user belongs to.
|
||||
external String get hd;
|
||||
|
||||
/// The prompt value that was used from the possible list of values specified
|
||||
/// by [TokenClientConfig] or [OverridableTokenClientConfig].
|
||||
external String get prompt;
|
||||
|
||||
/// The type of the token issued.
|
||||
external String get token_type;
|
||||
|
||||
/// A space-delimited list of scopes that are approved by the user.
|
||||
external String get scope;
|
||||
|
||||
/// The string value that your application uses to maintain state between your
|
||||
/// authorization request and the response.
|
||||
external String get state;
|
||||
|
||||
/// A single ASCII error code.
|
||||
external String? get error;
|
||||
|
||||
/// Human-readable ASCII text providing additional information, used to assist
|
||||
/// the client developer in understanding the error that occurred.
|
||||
external String? get error_description;
|
||||
|
||||
/// A URI identifying a human-readable web page with information about the
|
||||
/// error, used to provide the client developer with additional information
|
||||
/// about the error.
|
||||
external String? get error_uri;
|
||||
}
|
||||
|
||||
/// The type of the `callback` function passed to [TokenClientConfig].
|
||||
typedef TokenClientCallbackFn = void Function(TokenResponse response);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.oauth2.hasGrantedAllScopes
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#google.accounts.oauth2.hasGrantedAllScopes
|
||||
*/
|
||||
|
||||
/// Checks if the user granted **all** the specified scopes.
|
||||
@JS()
|
||||
external HasGrantedScopesFn get hasGrantedAllScopes;
|
||||
|
||||
/*
|
||||
// Method: google.accounts.oauth2.hasGrantedAnyScopes
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#google.accounts.oauth2.hasGrantedAnyScopes
|
||||
*/
|
||||
|
||||
/// Checks if the user granted **any** of the specified scopes.
|
||||
@JS()
|
||||
external HasGrantedScopesFn get hasGrantedAnyScopes;
|
||||
|
||||
/// The signature for functions that check if any/all scopes have been granted.
|
||||
///
|
||||
/// Used by [hasGrantedAllScopes] and [hasGrantedAnyScope].
|
||||
typedef HasGrantedScopesFn = bool Function(
|
||||
TokenResponse tokenResponse,
|
||||
String firstScope, [
|
||||
String? scope2,
|
||||
String? scope3,
|
||||
String? scope4,
|
||||
String? scope5,
|
||||
String? scope6,
|
||||
String? scope7,
|
||||
String? scope8,
|
||||
String? scope9,
|
||||
String? scope10,
|
||||
]);
|
||||
|
||||
/*
|
||||
// Method: google.accounts.oauth2.revoke
|
||||
// https://developers.google.com/identity/oauth2/web/reference/js-reference#google.accounts.oauth2.revoke
|
||||
*/
|
||||
|
||||
/// The [revokeToken] method revokes all of the scopes that the user granted to
|
||||
/// the app. A valid access token is required to revoke the permission.
|
||||
///
|
||||
/// The `done` callback is called once the revoke action is done.
|
||||
@JS('revoke')
|
||||
external RevokeTokenFn get revokeToken;
|
||||
|
||||
/// The signature of the [revokeToken] function.
|
||||
///
|
||||
/// The (optional) [done] parameter must be manually wrapped in [allowInterop]
|
||||
/// before being passed to the [revokeToken] function.
|
||||
typedef RevokeTokenFn = void Function(
|
||||
String accessToken, [
|
||||
RevokeTokenDoneFn? done,
|
||||
]);
|
||||
|
||||
/// The signature of the `done` function for [revokeToken].
|
||||
///
|
||||
/// Work in progress here: b/248628502
|
||||
typedef RevokeTokenDoneFn = void Function(String jsonError);
|
@ -0,0 +1,26 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// 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 'package:js/js.dart';
|
||||
|
||||
import 'shared.dart';
|
||||
|
||||
/*
|
||||
// Library load callback: onGoogleLibraryLoad
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#onGoogleLibraryLoad
|
||||
*/
|
||||
|
||||
/// Method called after the Sign In With Google JavaScript library is loaded.
|
||||
///
|
||||
/// The [callback] parameter must be manually wrapped in [allowInterop]
|
||||
/// before being set to the [onGoogleLibraryLoad] property.
|
||||
@JS()
|
||||
@staticInterop
|
||||
external set onGoogleLibraryLoad(VoidFn callback);
|
@ -0,0 +1,215 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/// Attempts to retrieve an enum value from [haystack] if [needle] is not null.
|
||||
T? maybeEnum<T extends Enum>(String? needle, List<T> haystack) {
|
||||
if (needle == null) {
|
||||
return null;
|
||||
}
|
||||
return haystack.byName(needle);
|
||||
}
|
||||
|
||||
/// The type of several functions from the library, that don't receive
|
||||
/// parameters nor return anything.
|
||||
typedef VoidFn = void Function();
|
||||
|
||||
/*
|
||||
// Enum: UX Mode
|
||||
// https://developers.google.com/identity/gsi/web/reference/js-reference#ux_mode
|
||||
// Used both by `oauth2.initCodeClient` and `id.initialize`.
|
||||
*/
|
||||
|
||||
/// Use this enum to set the UX flow used by the Sign In With Google button.
|
||||
/// The default value is [popup].
|
||||
///
|
||||
/// This attribute has no impact on the OneTap UX.
|
||||
enum UxMode {
|
||||
/// Performs sign-in UX flow in a pop-up window.
|
||||
popup('popup'),
|
||||
|
||||
/// Performs sign-in UX flow by a full page redirection.
|
||||
redirect('redirect');
|
||||
|
||||
///
|
||||
const UxMode(String uxMode) : _uxMode = uxMode;
|
||||
final String _uxMode;
|
||||
|
||||
@override
|
||||
String toString() => _uxMode;
|
||||
}
|
||||
|
||||
/// Changes the text of the title and messages in the One Tap prompt.
|
||||
enum OneTapContext {
|
||||
/// "Sign in with Google"
|
||||
signin('signin'),
|
||||
|
||||
/// "Sign up with Google"
|
||||
signup('signup'),
|
||||
|
||||
/// "Use with Google"
|
||||
use('use');
|
||||
|
||||
///
|
||||
const OneTapContext(String context) : _context = context;
|
||||
final String _context;
|
||||
|
||||
@override
|
||||
String toString() => _context;
|
||||
}
|
||||
|
||||
/// The detailed reason why the OneTap UI isn't displayed.
|
||||
enum MomentNotDisplayedReason {
|
||||
/// Browser not supported.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/supported-browsers
|
||||
browser_not_supported('browser_not_supported'),
|
||||
|
||||
/// Invalid Client.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
|
||||
invalid_client('invalid_client'),
|
||||
|
||||
/// Missing client_id.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
|
||||
missing_client_id('missing_client_id'),
|
||||
|
||||
/// The user has opted out, or they aren't signed in to a Google account.
|
||||
///
|
||||
/// https://developers.google.com/identity/gsi/web/guides/features
|
||||
opt_out_or_no_session('opt_out_or_no_session'),
|
||||
|
||||
/// Google One Tap can only be displayed in HTTPS domains.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
|
||||
secure_http_required('secure_http_required'),
|
||||
|
||||
/// The user has previously closed the OneTap card.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/features#exponential_cooldown
|
||||
suppressed_by_user('suppressed_by_user'),
|
||||
|
||||
/// The current `origin` is not associated with the Client ID.
|
||||
///
|
||||
/// See https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid
|
||||
unregistered_origin('unregistered_origin'),
|
||||
|
||||
/// Unknown reason
|
||||
unknown_reason('unknown_reason');
|
||||
|
||||
///
|
||||
const MomentNotDisplayedReason(String reason) : _reason = reason;
|
||||
final String _reason;
|
||||
|
||||
@override
|
||||
String toString() => _reason;
|
||||
}
|
||||
|
||||
/// The detailed reason for the skipped moment.
|
||||
enum MomentSkippedReason {
|
||||
/// auto_cancel
|
||||
auto_cancel('auto_cancel'),
|
||||
|
||||
/// user_cancel
|
||||
user_cancel('user_cancel'),
|
||||
|
||||
/// tap_outside
|
||||
tap_outside('tap_outside'),
|
||||
|
||||
/// issuing_failed
|
||||
issuing_failed('issuing_failed');
|
||||
|
||||
///
|
||||
const MomentSkippedReason(String reason) : _reason = reason;
|
||||
final String _reason;
|
||||
|
||||
@override
|
||||
String toString() => _reason;
|
||||
}
|
||||
|
||||
/// The detailed reason for the dismissal.
|
||||
enum MomentDismissedReason {
|
||||
/// credential_returned
|
||||
credential_returned('credential_returned'),
|
||||
|
||||
/// cancel_called
|
||||
cancel_called('cancel_called'),
|
||||
|
||||
/// flow_restarted
|
||||
flow_restarted('flow_restarted');
|
||||
|
||||
///
|
||||
const MomentDismissedReason(String reason) : _reason = reason;
|
||||
final String _reason;
|
||||
|
||||
@override
|
||||
String toString() => _reason;
|
||||
}
|
||||
|
||||
/// The moment type.
|
||||
enum MomentType {
|
||||
/// Display moment
|
||||
display('display'),
|
||||
|
||||
/// Skipped moment
|
||||
skipped('skipped'),
|
||||
|
||||
/// Dismissed moment
|
||||
dismissed('dismissed');
|
||||
|
||||
///
|
||||
const MomentType(String type) : _type = type;
|
||||
final String _type;
|
||||
|
||||
@override
|
||||
String toString() => _type;
|
||||
}
|
||||
|
||||
/// Represents how a credential was selected.
|
||||
enum CredentialSelectBy {
|
||||
/// Automatic sign-in of a user with an existing session who had previously
|
||||
/// granted consent to share credentials.
|
||||
auto('auto'),
|
||||
|
||||
/// A user with an existing session who had previously granted consent
|
||||
/// pressed the One Tap 'Continue as' button to share credentials.
|
||||
user('user'),
|
||||
|
||||
/// A user with an existing session pressed the One Tap 'Continue as' button
|
||||
/// to grant consent and share credentials. Applies only to Chrome v75 and
|
||||
/// higher.
|
||||
user_1tap('user_1tap'),
|
||||
|
||||
/// A user without an existing session pressed the One Tap 'Continue as'
|
||||
/// button to select an account and then pressed the Confirm button in a
|
||||
/// pop-up window to grant consent and share credentials. Applies to
|
||||
/// non-Chromium based browsers.
|
||||
user_2tap('user_2tap'),
|
||||
|
||||
/// A user with an existing session who previously granted consent pressed
|
||||
/// the Sign In With Google button and selected a Google Account from
|
||||
/// 'Choose an Account' to share credentials.
|
||||
btn('btn'),
|
||||
|
||||
/// A user with an existing session pressed the Sign In With Google button
|
||||
/// and pressed the Confirm button to grant consent and share credentials.
|
||||
btn_confirm('btn_confirm'),
|
||||
|
||||
/// A user without an existing session who previously granted consent
|
||||
/// pressed the Sign In With Google button to select a Google Account and
|
||||
/// share credentials.
|
||||
btn_add_session('btn_add_session'),
|
||||
|
||||
/// A user without an existing session first pressed the Sign In With Google
|
||||
/// button to select a Google Account and then pressed the Confirm button to
|
||||
/// consent and share credentials.
|
||||
btn_confirm_add_session('btn_confirm_add_session');
|
||||
|
||||
///
|
||||
const CredentialSelectBy(String selectBy) : _selectBy = selectBy;
|
||||
final String _selectBy;
|
||||
|
||||
@override
|
||||
String toString() => _selectBy;
|
||||
}
|
67
packages/google_identity_services_web/lib/src/js_loader.dart
Normal file
67
packages/google_identity_services_web/lib/src/js_loader.dart
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:js/js.dart' show allowInterop;
|
||||
|
||||
import 'js_interop/dom.dart';
|
||||
import 'js_interop/load_callback.dart';
|
||||
|
||||
// The URL from which the script should be downloaded.
|
||||
const String _url = 'https://accounts.google.com/gsi/client';
|
||||
|
||||
// The default TrustedPolicy name that will be used to inject the script.
|
||||
const String _defaultTrustedPolicyName = 'gis-dart';
|
||||
|
||||
/// Loads the GIS SDK for web, using Trusted Types API when available.
|
||||
Future<void> loadWebSdk({
|
||||
DomHtmlElement? target,
|
||||
String trustedTypePolicyName = _defaultTrustedPolicyName,
|
||||
}) {
|
||||
final Completer<void> completer = Completer<void>();
|
||||
onGoogleLibraryLoad = allowInterop(() => completer.complete());
|
||||
|
||||
// If TrustedTypes are available, prepare a trusted URL.
|
||||
DomTrustedScriptUrl? trustedUrl;
|
||||
if (trustedTypes != null) {
|
||||
console.debug(
|
||||
'TrustedTypes available. Creating policy:',
|
||||
trustedTypePolicyName,
|
||||
);
|
||||
final DomTrustedTypePolicyFactory factory = trustedTypes!;
|
||||
try {
|
||||
final DomTrustedTypePolicy policy = factory.createPolicy(
|
||||
trustedTypePolicyName,
|
||||
DomTrustedTypePolicyOptions(
|
||||
createScriptURL: allowInterop((String url) => _url),
|
||||
));
|
||||
trustedUrl = policy.createScriptURL(_url);
|
||||
} catch (e) {
|
||||
throw TrustedTypesException(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
final DomHtmlScriptElement script =
|
||||
document.createElement('script') as DomHtmlScriptElement
|
||||
..src = trustedUrl ?? _url
|
||||
..async = true
|
||||
..defer = true;
|
||||
|
||||
(target ?? document.head).appendChild(script);
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
/// Exception thrown if the Trusted Types feature is supported, enabled, and it
|
||||
/// has prevented this loader from injecting the JS SDK.
|
||||
class TrustedTypesException implements Exception {
|
||||
///
|
||||
TrustedTypesException(this.message);
|
||||
|
||||
/// The message of the exception
|
||||
final String message;
|
||||
@override
|
||||
String toString() => 'TrustedTypesException: $message';
|
||||
}
|
16
packages/google_identity_services_web/pubspec.yaml
Normal file
16
packages/google_identity_services_web/pubspec.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
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.1.0
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
js: ^0.6.4
|
||||
meta: ^1.3.0
|
||||
|
||||
dev_dependencies:
|
||||
path: ^1.8.1
|
||||
test: ^1.21.1
|
3
packages/google_identity_services_web/test/README.md
Normal file
3
packages/google_identity_services_web/test/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Tests
|
||||
|
||||
Use `dart run tool/run_tests.dart` to run tests in this package.
|
@ -0,0 +1,66 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@TestOn('browser') // Uses package:js
|
||||
|
||||
import 'package:google_identity_services_web/loader.dart';
|
||||
import 'package:google_identity_services_web/src/js_interop/dom.dart' as dom;
|
||||
import 'package:google_identity_services_web/src/js_loader.dart';
|
||||
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// NOTE: This file needs to be separated from the others because Content
|
||||
// Security Policies can never be *relaxed* once set.
|
||||
//
|
||||
// In order to not introduce a dependency in the order of the tests, we split
|
||||
// them in different files, depending on the strictness of their CSP:
|
||||
//
|
||||
// * js_loader_test.dart : default TT configuration (not enforced)
|
||||
// * js_loader_tt_custom_test.dart : TT are customized, but allowed
|
||||
// * js_loader_tt_forbidden_test.dart: TT are completely disallowed
|
||||
|
||||
void main() {
|
||||
group('loadWebSdk (no TrustedTypes)', () {
|
||||
final dom.DomHtmlElement target = dom.document.createElement('div');
|
||||
|
||||
test('Injects script into desired target', () async {
|
||||
loadWebSdk(target: target);
|
||||
|
||||
// Target now should have a child that is a script element
|
||||
final Object children = js_util.getProperty<Object>(target, 'children');
|
||||
final Object injected = js_util.callMethod<Object>(
|
||||
children,
|
||||
'item',
|
||||
<Object>[0],
|
||||
);
|
||||
expect(injected, isA<dom.DomHtmlScriptElement>());
|
||||
|
||||
final dom.DomHtmlScriptElement script =
|
||||
injected as dom.DomHtmlScriptElement;
|
||||
expect(js_util.getProperty<bool>(script, 'defer'), isTrue);
|
||||
expect(js_util.getProperty<bool>(script, 'async'), isTrue);
|
||||
expect(
|
||||
js_util.getProperty<String>(script, 'src'),
|
||||
'https://accounts.google.com/gsi/client',
|
||||
);
|
||||
});
|
||||
|
||||
test('Completes when the script loads', () async {
|
||||
final Future<void> loadFuture = loadWebSdk(target: target);
|
||||
|
||||
Future<void>.delayed(const Duration(milliseconds: 100), () {
|
||||
// Simulate the library calling `window.onGoogleLibraryLoad`.
|
||||
js_util.callMethod<void>(
|
||||
js_util.globalThis,
|
||||
'onGoogleLibraryLoad',
|
||||
<Object>[],
|
||||
);
|
||||
});
|
||||
|
||||
await expectLater(loadFuture, completes);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@TestOn('browser') // Uses package:js
|
||||
|
||||
import 'package:google_identity_services_web/loader.dart';
|
||||
import 'package:google_identity_services_web/src/js_interop/dom.dart' as dom;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'tools.dart';
|
||||
|
||||
// NOTE: This file needs to be separated from the others because Content
|
||||
// Security Policies can never be *relaxed* once set.
|
||||
//
|
||||
// In order to not introduce a dependency in the order of the tests, we split
|
||||
// them in different files, depending on the strictness of their CSP:
|
||||
//
|
||||
// * js_loader_test.dart : default TT configuration (not enforced)
|
||||
// * js_loader_tt_custom_test.dart : TT are customized, but allowed
|
||||
// * js_loader_tt_forbidden_test.dart: TT are completely disallowed
|
||||
|
||||
void main() {
|
||||
group('loadWebSdk (TrustedTypes configured)', () {
|
||||
final dom.DomHtmlElement target = dom.document.createElement('div');
|
||||
injectMetaTag(<String, String>{
|
||||
'http-equiv': 'Content-Security-Policy',
|
||||
'content': "trusted-types my-custom-policy-name 'allow-duplicates';",
|
||||
});
|
||||
|
||||
test('Wrong policy name: Fail with TrustedTypesException', () {
|
||||
expect(() {
|
||||
loadWebSdk(target: target);
|
||||
}, throwsA(isA<TrustedTypesException>()));
|
||||
});
|
||||
|
||||
test('Correct policy name: Completes', () {
|
||||
final Future<void> done = loadWebSdk(
|
||||
target: target,
|
||||
trustedTypePolicyName: 'my-custom-policy-name',
|
||||
);
|
||||
|
||||
expect(done, isA<Future<void>>());
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@TestOn('browser') // Uses package:js
|
||||
|
||||
import 'package:google_identity_services_web/loader.dart';
|
||||
import 'package:google_identity_services_web/src/js_interop/dom.dart' as dom;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'tools.dart';
|
||||
|
||||
// NOTE: This file needs to be separated from the others because Content
|
||||
// Security Policies can never be *relaxed* once set.
|
||||
//
|
||||
// In order to not introduce a dependency in the order of the tests, we split
|
||||
// them in different files, depending on the strictness of their CSP:
|
||||
//
|
||||
// * js_loader_test.dart : default TT configuration (not enforced)
|
||||
// * js_loader_tt_custom_test.dart : TT are customized, but allowed
|
||||
// * js_loader_tt_forbidden_test.dart: TT are completely disallowed
|
||||
|
||||
void main() {
|
||||
group('loadWebSdk (TrustedTypes forbidden)', () {
|
||||
final dom.DomHtmlElement target = dom.document.createElement('div');
|
||||
injectMetaTag(<String, String>{
|
||||
'http-equiv': 'Content-Security-Policy',
|
||||
'content': "trusted-types 'none';",
|
||||
});
|
||||
|
||||
test('Fail with TrustedTypesException', () {
|
||||
expect(() {
|
||||
loadWebSdk(target: target);
|
||||
}, throwsA(isA<TrustedTypesException>()));
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
@TestOn('vm')
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
test('Tell the user where to find the real tests', () {
|
||||
print('---');
|
||||
print('This package uses `dart test -p chrome` for its tests.');
|
||||
print('See `README.md` for more info.');
|
||||
print('---');
|
||||
});
|
||||
}
|
19
packages/google_identity_services_web/test/tools.dart
Normal file
19
packages/google_identity_services_web/test/tools.dart
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:google_identity_services_web/src/js_interop/dom.dart' as dom;
|
||||
import 'package:js/js_util.dart' as js_util;
|
||||
|
||||
/// Injects a `<meta>` tag with the provided [attributes] into the [dom.document].
|
||||
void injectMetaTag(Map<String, String> attributes) {
|
||||
final dom.DomHtmlElement meta = dom.document.createElement('meta');
|
||||
for (final MapEntry<String, String> attribute in attributes.entries) {
|
||||
js_util.callMethod(
|
||||
meta,
|
||||
'setAttribute',
|
||||
<String>[attribute.key, attribute.value],
|
||||
);
|
||||
}
|
||||
dom.document.head.appendChild(meta);
|
||||
}
|
49
packages/google_identity_services_web/tool/run_tests.dart
Normal file
49
packages/google_identity_services_web/tool/run_tests.dart
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Runs `dart test -p chrome` in the root of the google_identity_services_web package.
|
||||
//
|
||||
// Called from the custom-tests CI action.
|
||||
//
|
||||
// usage: dart run tool/run_tests.dart
|
||||
// (needs a `chrome` executable in $PATH, or a tweak to dart_test.yaml)
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
final Directory workingDir =
|
||||
Directory(p.dirname(Platform.script.path)).parent;
|
||||
|
||||
final int status = await _runProcess(
|
||||
'dart',
|
||||
<String>[
|
||||
'test',
|
||||
'-p',
|
||||
'chrome',
|
||||
],
|
||||
workingDirectory: workingDir.path,
|
||||
);
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
Future<Process> _streamOutput(Future<Process> processFuture) async {
|
||||
final Process process = await processFuture;
|
||||
stdout.addStream(process.stdout);
|
||||
stderr.addStream(process.stderr);
|
||||
return process;
|
||||
}
|
||||
|
||||
Future<int> _runProcess(
|
||||
String command,
|
||||
List<String> arguments, {
|
||||
String? workingDirectory,
|
||||
}) async {
|
||||
final Process process = await _streamOutput(Process.start(
|
||||
command,
|
||||
arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
));
|
||||
return process.exitCode;
|
||||
}
|
9
script/configs/linux_only_custom_test.yaml
Normal file
9
script/configs/linux_only_custom_test.yaml
Normal file
@ -0,0 +1,9 @@
|
||||
# Packages that only support `custom-test` in linux, because that's
|
||||
# the only place where we install Chrome.
|
||||
#
|
||||
# This file is used to "--exclude" these packages from the relevant
|
||||
# mac/windows CI test runs.
|
||||
|
||||
- cross_file
|
||||
- google_identity_services_web
|
||||
|
Reference in New Issue
Block a user