From 489c913f4eb78dfe27d0cdbfa8df77add544705e Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Thu, 21 Oct 2021 16:58:03 -0700 Subject: [PATCH 1/7] [google_sign_in] remove the commented out code in tests (#4442) --- .../google_sign_in/google_sign_in/test/google_sign_in_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/google_sign_in/google_sign_in/test/google_sign_in_test.dart b/packages/google_sign_in/google_sign_in/test/google_sign_in_test.dart index 76bc2d600541..0a019a2ffae5 100644 --- a/packages/google_sign_in/google_sign_in/test/google_sign_in_test.dart +++ b/packages/google_sign_in/google_sign_in/test/google_sign_in_test.dart @@ -351,8 +351,6 @@ void main() { expect(auth.accessToken, '456'); expect(auth.idToken, '123'); - // fix deprecated_member_use_from_same_package - // expect(auth.serverAuthCode, '789'); expect( log, [ From 4b6b6b24c7a5c635d256c6556f63fbe0b755a825 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 21 Oct 2021 17:17:18 -0700 Subject: [PATCH 2/7] Use OpenJDK 11 in CI jobs (#4419) --- .ci/Dockerfile | 4 ---- .../connectivity/example/android/app/build.gradle | 6 +++--- .../android/app/gradle/wrapper/gradle-wrapper.properties | 5 ----- .../connectivity/connectivity/example/android/build.gradle | 2 +- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- .../video_player/example/android/app/build.gradle | 6 +++--- .../video_player/video_player/example/android/build.gradle | 2 +- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- 8 files changed, 10 insertions(+), 19 deletions(-) delete mode 100644 packages/connectivity/connectivity/example/android/app/gradle/wrapper/gradle-wrapper.properties diff --git a/.ci/Dockerfile b/.ci/Dockerfile index a3deb6948d90..60f82eb005ed 100644 --- a/.ci/Dockerfile +++ b/.ci/Dockerfile @@ -5,10 +5,6 @@ FROM cirrusci/flutter:2.2.2 RUN apt-get update -y -# Required by Roboeletric and the Android SDK. -RUN apt-get install -y openjdk-8-jdk -ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 - RUN apt-get install -y --no-install-recommends gnupg # Add repo for gcloud sdk and install it diff --git a/packages/connectivity/connectivity/example/android/app/build.gradle b/packages/connectivity/connectivity/example/android/app/build.gradle index 64f3d0626bf4..99e360558af8 100644 --- a/packages/connectivity/connectivity/example/android/app/build.gradle +++ b/packages/connectivity/connectivity/example/android/app/build.gradle @@ -52,9 +52,9 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13' + testImplementation 'org.robolectric:robolectric:4.4' + testImplementation 'org.mockito:mockito-core:3.5.13' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - testImplementation 'org.robolectric:robolectric:3.8' - testImplementation 'org.mockito:mockito-core:3.5.13' } diff --git a/packages/connectivity/connectivity/example/android/app/gradle/wrapper/gradle-wrapper.properties b/packages/connectivity/connectivity/example/android/app/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9a4163a4f5ee..000000000000 --- a/packages/connectivity/connectivity/example/android/app/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/packages/connectivity/connectivity/example/android/build.gradle b/packages/connectivity/connectivity/example/android/build.gradle index 456d020f6e2c..c21bff8e0a2f 100644 --- a/packages/connectivity/connectivity/example/android/build.gradle +++ b/packages/connectivity/connectivity/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:7.0.1' } } diff --git a/packages/connectivity/connectivity/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/connectivity/connectivity/example/android/gradle/wrapper/gradle-wrapper.properties index 01a286e96a21..297f2fec363f 100644 --- a/packages/connectivity/connectivity/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/connectivity/connectivity/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip diff --git a/packages/video_player/video_player/example/android/app/build.gradle b/packages/video_player/video_player/example/android/app/build.gradle index 0d1d5031ef4f..5f1f3afa6352 100644 --- a/packages/video_player/video_player/example/android/app/build.gradle +++ b/packages/video_player/video_player/example/android/app/build.gradle @@ -58,9 +58,9 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13' + testImplementation 'org.robolectric:robolectric:4.4' + testImplementation 'org.mockito:mockito-core:3.5.13' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - testImplementation 'org.robolectric:robolectric:3.8' - testImplementation 'org.mockito:mockito-core:3.5.13' } diff --git a/packages/video_player/video_player/example/android/build.gradle b/packages/video_player/video_player/example/android/build.gradle index 456d020f6e2c..c21bff8e0a2f 100644 --- a/packages/video_player/video_player/example/android/build.gradle +++ b/packages/video_player/video_player/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:7.0.1' } } diff --git a/packages/video_player/video_player/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/video_player/video_player/example/android/gradle/wrapper/gradle-wrapper.properties index 296b146b7318..b8793d3c0d69 100644 --- a/packages/video_player/video_player/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/video_player/video_player/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip From 94b836eca3654e22c73efc0a9b6946b484013c28 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Mon, 25 Oct 2021 11:29:07 -0400 Subject: [PATCH 3/7] [flutter_plugin_tools] Fix pubspec-check on Windows (#4428) The repository check always failed when run on Windows, because the relative path generated to check the end of the URL was using local filesystem style for separators, but URLs always use POSIX separators. --- script/tool/CHANGELOG.md | 1 + .../tool/lib/src/pubspec_check_command.dart | 2 +- .../tool/test/pubspec_check_command_test.dart | 437 ++++++++++-------- 3 files changed, 247 insertions(+), 193 deletions(-) diff --git a/script/tool/CHANGELOG.md b/script/tool/CHANGELOG.md index bb4ca2390d78..89bc7759b962 100644 --- a/script/tool/CHANGELOG.md +++ b/script/tool/CHANGELOG.md @@ -14,6 +14,7 @@ - `pubspec-check` now checks that the description is of the pub-recommended length. - Fix `license-check` when run on Windows with line ending conversion enabled. +- Fixed `pubspec-check` on Windows. ## 0.7.1 diff --git a/script/tool/lib/src/pubspec_check_command.dart b/script/tool/lib/src/pubspec_check_command.dart index b99f5af68c45..04c3848a7dec 100644 --- a/script/tool/lib/src/pubspec_check_command.dart +++ b/script/tool/lib/src/pubspec_check_command.dart @@ -177,7 +177,7 @@ class PubspecCheckCommand extends PackageLoopingCommand { errorMessages.add('Missing "repository"'); } else { final String relativePackagePath = - path.relative(package.path, from: packagesDir.parent.path); + getRelativePosixPath(package.directory, from: packagesDir.parent); if (!pubspec.repository!.path.endsWith(relativePackagePath)) { errorMessages .add('The "repository" link should end with the package path.'); diff --git a/script/tool/test/pubspec_check_command_test.dart b/script/tool/test/pubspec_check_command_test.dart index d09dcebce4af..ba943903b6c5 100644 --- a/script/tool/test/pubspec_check_command_test.dart +++ b/script/tool/test/pubspec_check_command_test.dart @@ -12,62 +12,43 @@ import 'package:test/test.dart'; import 'mocks.dart'; import 'util.dart'; -void main() { - group('test pubspec_check_command', () { - late CommandRunner runner; - late RecordingProcessRunner processRunner; - late FileSystem fileSystem; - late MockPlatform mockPlatform; - late Directory packagesDir; - - setUp(() { - fileSystem = MemoryFileSystem(); - mockPlatform = MockPlatform(); - packagesDir = fileSystem.currentDirectory.childDirectory('packages'); - createPackagesDirectory(parentDir: packagesDir.parent); - processRunner = RecordingProcessRunner(); - final PubspecCheckCommand command = PubspecCheckCommand( - packagesDir, - processRunner: processRunner, - platform: mockPlatform, - ); - - runner = CommandRunner( - 'pubspec_check_command', 'Test for pubspec_check_command'); - runner.addCommand(command); - }); - - /// Returns the top section of a pubspec.yaml for a package named [name], - /// for either a flutter/packages or flutter/plugins package depending on - /// the values of [isPlugin]. - /// - /// By default it will create a header that includes all of the expected - /// values, elements can be changed via arguments to create incorrect - /// entries. - /// - /// If [includeRepository] is true, by default the path in the link will - /// be "packages/[name]"; a different "packages"-relative path can be - /// provided with [repositoryPackagesDirRelativePath]. - String headerSection( - String name, { - bool isPlugin = false, - bool includeRepository = true, - String? repositoryPackagesDirRelativePath, - bool includeHomepage = false, - bool includeIssueTracker = true, - bool publishable = true, - String? description, - }) { - final String repositoryPath = repositoryPackagesDirRelativePath ?? name; - final String repoLink = 'https://github.com/flutter/' - '${isPlugin ? 'plugins' : 'packages'}/tree/master/' - 'packages/$repositoryPath'; - final String issueTrackerLink = - 'https://github.com/flutter/flutter/issues?' - 'q=is%3Aissue+is%3Aopen+label%3A%22p%3A+$name%22'; - description ??= 'A test package for validating that the pubspec.yaml ' - 'follows repo best practices.'; - return ''' +/// Returns the top section of a pubspec.yaml for a package named [name], +/// for either a flutter/packages or flutter/plugins package depending on +/// the values of [isPlugin]. +/// +/// By default it will create a header that includes all of the expected +/// values, elements can be changed via arguments to create incorrect +/// entries. +/// +/// If [includeRepository] is true, by default the path in the link will +/// be "packages/[name]"; a different "packages"-relative path can be +/// provided with [repositoryPackagesDirRelativePath]. +String _headerSection( + String name, { + bool isPlugin = false, + bool includeRepository = true, + String? repositoryPackagesDirRelativePath, + bool includeHomepage = false, + bool includeIssueTracker = true, + bool publishable = true, + String? description, +}) { + final String repositoryPath = repositoryPackagesDirRelativePath ?? name; + final List repoLinkPathComponents = [ + 'flutter', + if (isPlugin) 'plugins' else 'packages', + 'tree', + 'master', + 'packages', + repositoryPath, + ]; + final String repoLink = + 'https://github.com/' + repoLinkPathComponents.join('/'); + final String issueTrackerLink = 'https://github.com/flutter/flutter/issues?' + 'q=is%3Aissue+is%3Aopen+label%3A%22p%3A+$name%22'; + description ??= 'A test package for validating that the pubspec.yaml ' + 'follows repo best practices.'; + return ''' name: $name description: $description ${includeRepository ? 'repository: $repoLink' : ''} @@ -76,64 +57,89 @@ ${includeIssueTracker ? 'issue_tracker: $issueTrackerLink' : ''} version: 1.0.0 ${publishable ? '' : 'publish_to: \'none\''} '''; - } +} - String environmentSection() { - return ''' +String _environmentSection() { + return ''' environment: sdk: ">=2.12.0 <3.0.0" flutter: ">=2.0.0" '''; - } +} - String flutterSection({ - bool isPlugin = false, - String? implementedPackage, - }) { - final String pluginEntry = ''' +String _flutterSection({ + bool isPlugin = false, + String? implementedPackage, +}) { + final String pluginEntry = ''' plugin: ${implementedPackage == null ? '' : ' implements: $implementedPackage'} platforms: '''; - return ''' + return ''' flutter: ${isPlugin ? pluginEntry : ''} '''; - } +} - String dependenciesSection() { - return ''' +String _dependenciesSection() { + return ''' dependencies: flutter: sdk: flutter '''; - } +} - String devDependenciesSection() { - return ''' +String _devDependenciesSection() { + return ''' dev_dependencies: flutter_test: sdk: flutter '''; - } +} - String falseSecretsSection() { - return ''' +String _falseSecretsSection() { + return ''' false_secrets: - /lib/main.dart '''; - } +} + +void main() { + group('test pubspec_check_command', () { + late CommandRunner runner; + late RecordingProcessRunner processRunner; + late FileSystem fileSystem; + late MockPlatform mockPlatform; + late Directory packagesDir; + + setUp(() { + fileSystem = MemoryFileSystem(); + mockPlatform = MockPlatform(); + packagesDir = fileSystem.currentDirectory.childDirectory('packages'); + createPackagesDirectory(parentDir: packagesDir.parent); + processRunner = RecordingProcessRunner(); + final PubspecCheckCommand command = PubspecCheckCommand( + packagesDir, + processRunner: processRunner, + platform: mockPlatform, + ); + + runner = CommandRunner( + 'pubspec_check_command', 'Test for pubspec_check_command'); + runner.addCommand(command); + }); test('passes for a plugin following conventions', () async { final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} -${falseSecretsSection()} +${_headerSection('plugin', isPlugin: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} +${_falseSecretsSection()} '''); final List output = await runCapturingPrint(runner, [ @@ -154,12 +160,12 @@ ${falseSecretsSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin')} -${environmentSection()} -${dependenciesSection()} -${devDependenciesSection()} -${flutterSection()} -${falseSecretsSection()} +${_headerSection('plugin')} +${_environmentSection()} +${_dependenciesSection()} +${_devDependenciesSection()} +${_flutterSection()} +${_falseSecretsSection()} '''); final List output = await runCapturingPrint(runner, [ @@ -181,9 +187,9 @@ ${falseSecretsSection()} packageDirectory.createSync(recursive: true); packageDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('package')} -${environmentSection()} -${dependenciesSection()} +${_headerSection('package')} +${_environmentSection()} +${_dependenciesSection()} '''); final List output = await runCapturingPrint(runner, [ @@ -203,11 +209,11 @@ ${dependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, includeHomepage: true)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, includeHomepage: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -230,11 +236,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, includeRepository: false)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, includeRepository: false)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -256,11 +262,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, includeHomepage: true, includeRepository: false)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, includeHomepage: true, includeRepository: false)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -283,11 +289,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, repositoryPackagesDirRelativePath: 'different_plugin')} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, repositoryPackagesDirRelativePath: 'different_plugin')} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -309,11 +315,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, includeIssueTracker: false)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, includeIssueTracker: false)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -336,11 +342,11 @@ ${devDependenciesSection()} createFakePlugin('a_plugin', packagesDir.childDirectory('a_plugin')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, description: 'Too short')} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, description: 'Too short')} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -365,11 +371,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, description: 'Too short')} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, description: 'Too short')} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -397,11 +403,11 @@ ${devDependenciesSection()} 'the core description so that search results are more useful and the ' 'package does not lose pub points.'; pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true, description: description)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true, description: description)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -424,11 +430,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} -${environmentSection()} +${_headerSection('plugin', isPlugin: true)} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} +${_environmentSection()} '''); Error? commandError; @@ -451,11 +457,11 @@ ${environmentSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${flutterSection(isPlugin: true)} -${environmentSection()} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true)} +${_flutterSection(isPlugin: true)} +${_environmentSection()} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -478,11 +484,11 @@ ${devDependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${devDependenciesSection()} -${dependenciesSection()} +${_headerSection('plugin', isPlugin: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_devDependenciesSection()} +${_dependenciesSection()} '''); Error? commandError; @@ -505,11 +511,11 @@ ${dependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${environmentSection()} -${devDependenciesSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} +${_headerSection('plugin', isPlugin: true)} +${_environmentSection()} +${_devDependenciesSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} '''); Error? commandError; @@ -532,12 +538,12 @@ ${dependenciesSection()} final Directory pluginDirectory = createFakePlugin('plugin', packagesDir); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin', isPlugin: true)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${falseSecretsSection()} -${devDependenciesSection()} +${_headerSection('plugin', isPlugin: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_falseSecretsSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -562,11 +568,11 @@ ${devDependenciesSection()} 'plugin_a_foo', packagesDir.childDirectory('plugin_a')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin_a_foo', isPlugin: true)} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin_a_foo', isPlugin: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -590,11 +596,11 @@ ${devDependenciesSection()} 'plugin_a_foo', packagesDir.childDirectory('plugin_a')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin_a_foo', isPlugin: true)} -${environmentSection()} -${flutterSection(isPlugin: true, implementedPackage: 'plugin_a_foo')} -${dependenciesSection()} -${devDependenciesSection()} +${_headerSection('plugin_a_foo', isPlugin: true)} +${_environmentSection()} +${_flutterSection(isPlugin: true, implementedPackage: 'plugin_a_foo')} +${_dependenciesSection()} +${_devDependenciesSection()} '''); Error? commandError; @@ -618,15 +624,15 @@ ${devDependenciesSection()} 'plugin_a_foo', packagesDir.childDirectory('plugin_a')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection( +${_headerSection( 'plugin_a_foo', isPlugin: true, repositoryPackagesDirRelativePath: 'plugin_a/plugin_a_foo', )} -${environmentSection()} -${flutterSection(isPlugin: true, implementedPackage: 'plugin_a')} -${dependenciesSection()} -${devDependenciesSection()} +${_environmentSection()} +${_flutterSection(isPlugin: true, implementedPackage: 'plugin_a')} +${_dependenciesSection()} +${_devDependenciesSection()} '''); final List output = @@ -646,15 +652,15 @@ ${devDependenciesSection()} createFakePlugin('plugin_a', packagesDir.childDirectory('plugin_a')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection( +${_headerSection( 'plugin_a', isPlugin: true, repositoryPackagesDirRelativePath: 'plugin_a/plugin_a', )} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); final List output = @@ -676,16 +682,16 @@ ${devDependenciesSection()} packagesDir.childDirectory('plugin_a')); pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection( +${_headerSection( 'plugin_a_platform_interface', isPlugin: true, repositoryPackagesDirRelativePath: 'plugin_a/plugin_a_platform_interface', )} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); final List output = @@ -707,11 +713,11 @@ ${devDependenciesSection()} // Environment section is in the wrong location. // Missing 'implements'. pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection('plugin_a_foo', isPlugin: true, publishable: false)} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} -${environmentSection()} +${_headerSection('plugin_a_foo', isPlugin: true, publishable: false)} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} +${_environmentSection()} '''); Error? commandError; @@ -737,17 +743,17 @@ ${environmentSection()} // Missing metadata that is only useful for published packages, such as // repository and issue tracker. pluginDirectory.childFile('pubspec.yaml').writeAsStringSync(''' -${headerSection( +${_headerSection( 'plugin', isPlugin: true, publishable: false, includeRepository: false, includeIssueTracker: false, )} -${environmentSection()} -${flutterSection(isPlugin: true)} -${dependenciesSection()} -${devDependenciesSection()} +${_environmentSection()} +${_flutterSection(isPlugin: true)} +${_dependenciesSection()} +${_devDependenciesSection()} '''); final List output = @@ -762,4 +768,51 @@ ${devDependenciesSection()} ); }); }); + + group('test pubspec_check_command on Windows', () { + late CommandRunner runner; + late RecordingProcessRunner processRunner; + late FileSystem fileSystem; + late MockPlatform mockPlatform; + late Directory packagesDir; + + setUp(() { + fileSystem = MemoryFileSystem(style: FileSystemStyle.windows); + mockPlatform = MockPlatform(isWindows: true); + packagesDir = fileSystem.currentDirectory.childDirectory('packages'); + createPackagesDirectory(parentDir: packagesDir.parent); + processRunner = RecordingProcessRunner(); + final PubspecCheckCommand command = PubspecCheckCommand( + packagesDir, + processRunner: processRunner, + platform: mockPlatform, + ); + + runner = CommandRunner( + 'pubspec_check_command', 'Test for pubspec_check_command'); + runner.addCommand(command); + }); + + test('repository check works', () async { + final Directory packageDirectory = + createFakePackage('package', packagesDir); + + packageDirectory.childFile('pubspec.yaml').writeAsStringSync(''' +${_headerSection('package')} +${_environmentSection()} +${_dependenciesSection()} +'''); + + final List output = + await runCapturingPrint(runner, ['pubspec-check']); + + expect( + output, + containsAllInOrder([ + contains('Running for package...'), + contains('No issues found!'), + ]), + ); + }); + }); } From 9d63517bdcf9b2be805d8ec9c4d218441c1de1e7 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Tue, 26 Oct 2021 11:27:04 -0700 Subject: [PATCH 4/7] upgraded usage of BinaryMessenger (#4451) Co-authored-by: David Iglesias Teixeira --- .cirrus.yml | 4 + ci/stable_conditional.dart | 67 +++ .../MethodCallHandlerImplTest.java | 28 +- .../plugins/camera/DartMessengerTest.java | 21 +- .../quickactions/QuickActionsTest.java | 22 +- .../MethodCallHandlerImplTest.java | 28 +- .../url_launcher_web_test.mocks.dart | 540 +++++++++--------- .../url_launcher_web/example/pubspec.yaml | 2 +- 8 files changed, 443 insertions(+), 269 deletions(-) create mode 100644 ci/stable_conditional.dart diff --git a/.cirrus.yml b/.cirrus.yml index da354c5a9b22..9776d9a2ab31 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -197,6 +197,10 @@ task: - export CIRRUS_CHANGE_MESSAGE="" - export CIRRUS_COMMIT_MESSAGE="" - ./script/tool_runner.sh lint-android # must come after build-examples + stable_channel_conditional_script: + - if [[ "$CHANNEL" == "stable" ]]; then + - dart ./ci/stable_conditional.dart + - fi native_unit_test_script: # Unsetting CIRRUS_CHANGE_MESSAGE and CIRRUS_COMMIT_MESSAGE as they # might include non-ASCII characters which makes Gradle crash. diff --git a/ci/stable_conditional.dart b/ci/stable_conditional.dart new file mode 100644 index 000000000000..76643532bc9d --- /dev/null +++ b/ci/stable_conditional.dart @@ -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. +// +// stable_conditional.dart +// +// Performs simple find and replace operations for conditional compilation +// before executing stable channel tests. +// +// Example input: +// int main() { +// // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE +// printf("hello world\n"); +// // FLUTTER_STABLE_CONDITIONAL_ELSE +// // printf("goodbye world\n"); +// // FLUTTER_STABLE_CONDITIONAL_ENDIF +// } +// +// Example output: +// int main() { +// printf("goodbye world\n"); +// } + +import 'dart:convert' show LineSplitter; +import 'dart:io' show FileSystemEntity, File; + +final List _filesToProcess = [ + 'packages/android_intent/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java', + 'packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java', + 'packages/quick_actions/quick_actions/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java', + 'packages/url_launcher/url_launcher/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java', +]; + +final RegExp _replacer = RegExp( + r'^\s*// FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE(.*?)^\s*// FLUTTER_STABLE_CONDITIONAL_ELSE(.*?)^\s*// FLUTTER_STABLE_CONDITIONAL_ENDIF', + multiLine: true, + dotAll: true); +final RegExp _commentRemover = RegExp(r'^(\s*)\/\/\s*(.*)'); +const String _newline = '\n'; + +void _process(FileSystemEntity entity) { + const LineSplitter splitter = LineSplitter(); + final String text = File(entity.path).readAsStringSync(); + String replaced = ''; + int index = 0; + for (final RegExpMatch match in _replacer.allMatches(text)) { + replaced += text.substring(index, match.start); + for (final String line in splitter.convert(match.group(2)!)) { + final RegExpMatch? commentRemoverMatch = _commentRemover.firstMatch(line); + if (commentRemoverMatch != null) { + replaced += commentRemoverMatch.group(1)! + + commentRemoverMatch.group(2)! + + _newline; + } + } + index = match.end; + } + if (replaced.isNotEmpty) { + replaced += text.substring(index, text.length); + File(entity.path).writeAsStringSync(replaced); + print('modified: ${entity.path}'); + } +} + +void main(List args) { + _filesToProcess.map((String path) => File(path)).forEach(_process); +} diff --git a/packages/android_intent/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java b/packages/android_intent/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java index 0ea03a0690f1..012cc9be9711 100644 --- a/packages/android_intent/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java +++ b/packages/android_intent/android/src/test/java/io/flutter/plugins/androidintent/MethodCallHandlerImplTest.java @@ -55,7 +55,11 @@ public void startListening_registersChannel() { methodCallHandler.startListening(messenger); verify(messenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class), eq(null)); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -67,9 +71,15 @@ public void startListening_unregistersExistingChannel() { methodCallHandler.startListening(secondMessenger); // Unregisters the first and then registers the second. - verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null, null); verify(secondMessenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class), eq(null)); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // verify(secondMessenger, times(1)) + // .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -79,7 +89,11 @@ public void stopListening_unregistersExistingChannel() { methodCallHandler.stopListening(); - verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null, null); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -88,7 +102,11 @@ public void stopListening_doesNothingWhenUnset() { methodCallHandler.stopListening(); - verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null, null); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test diff --git a/packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java b/packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java index 0a2fc43d03cb..1ce04d6cc104 100644 --- a/packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java +++ b/packages/camera/camera/android/src/test/java/io/flutter/plugins/camera/DartMessengerTest.java @@ -12,6 +12,7 @@ import android.os.Handler; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import io.flutter.embedding.engine.systemchannels.PlatformChannel; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; @@ -31,6 +32,15 @@ public class DartMessengerTest { private static class FakeBinaryMessenger implements BinaryMessenger { private final List sentMessages = new ArrayList<>(); + // TODO(aaclarke): Remove when https://github.com/flutter/engine/pull/29147 is on stable. + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + @Override + public BinaryMessenger.TaskQueue makeBackgroundTaskQueue() { + return null; + } + // FLUTTER_STABLE_CONDITIONAL_ELSE + // FLUTTER_STABLE_CONDITIONAL_ENDIF + @Override public void send(@NonNull String channel, ByteBuffer message) { sentMessages.add(message); @@ -41,8 +51,17 @@ public void send(@NonNull String channel, ByteBuffer message, BinaryReply callba send(channel, message); } + // TODO(aaclarke): Remove when https://github.com/flutter/engine/pull/29147 is on stable. + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE @Override - public void setMessageHandler(@NonNull String channel, BinaryMessageHandler handler) {} + public void setMessageHandler( + @NonNull String channel, + BinaryMessageHandler handler, + @Nullable BinaryMessenger.TaskQueue taskQueue) {} + // FLUTTER_STABLE_CONDITIONAL_ELSE + // @Override + // public void setMessageHandler(@NonNull String channel, BinaryMessageHandler handler) {} + // FLUTTER_STABLE_CONDITIONAL_ENDIF List getMessages() { return new ArrayList<>(sentMessages); diff --git a/packages/quick_actions/quick_actions/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java b/packages/quick_actions/quick_actions/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java index 208a119efafe..2b6fb495f7c4 100644 --- a/packages/quick_actions/quick_actions/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java +++ b/packages/quick_actions/quick_actions/android/src/test/java/io/flutter/plugins/quickactions/QuickActionsTest.java @@ -33,6 +33,15 @@ public class QuickActionsTest { private static class TestBinaryMessenger implements BinaryMessenger { public MethodCall lastMethodCall; + // TODO(aaclarke): Remove when https://github.com/flutter/engine/pull/29147 is on stable. + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + @Override + public BinaryMessenger.TaskQueue makeBackgroundTaskQueue() { + return null; + } + // FLUTTER_STABLE_CONDITIONAL_ELSE + // FLUTTER_STABLE_CONDITIONAL_ENDIF + @Override public void send(@NonNull String channel, @Nullable ByteBuffer message) { send(channel, message, null); @@ -49,10 +58,21 @@ public void send( } } + // TODO(aaclarke): Remove when https://github.com/flutter/engine/pull/29147 is on stable. + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE @Override - public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler) { + public void setMessageHandler( + @NonNull String channel, + @Nullable BinaryMessageHandler handler, + @Nullable BinaryMessenger.TaskQueue taskQueue) { // Do nothing. } + // FLUTTER_STABLE_CONDITIONAL_ELSE + // @Override + // public void setMessageHandler( + // @NonNull String channel, + // @Nullable BinaryMessageHandler handler) {} + // FLUTTER_STABLE_CONDITIONAL_ENDIF } static final int SUPPORTED_BUILD = 25; diff --git a/packages/url_launcher/url_launcher/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java b/packages/url_launcher/url_launcher/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java index 5e0811399ac6..6b544c7611c5 100644 --- a/packages/url_launcher/url_launcher/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java +++ b/packages/url_launcher/url_launcher/android/src/test/java/io/flutter/plugins/urllauncher/MethodCallHandlerImplTest.java @@ -44,7 +44,11 @@ public void startListening_registersChannel() { methodCallHandler.startListening(messenger); verify(messenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class), eq(null)); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -56,9 +60,15 @@ public void startListening_unregistersExistingChannel() { methodCallHandler.startListening(secondMessenger); // Unregisters the first and then registers the second. - verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null, null); verify(secondMessenger, times(1)) - .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class), eq(null)); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(firstMessenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // verify(secondMessenger, times(1)) + // .setMessageHandler(eq(CHANNEL_NAME), any(BinaryMessageHandler.class)); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -68,7 +78,11 @@ public void stopListening_unregistersExistingChannel() { methodCallHandler.stopListening(); - verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null, null); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(messenger, times(1)).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test @@ -77,7 +91,11 @@ public void stopListening_doesNothingWhenUnset() { methodCallHandler.stopListening(); - verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_IF_NOT_STABLE + verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null, null); + // FLUTTER_STABLE_CONDITIONAL_ELSE + // verify(messenger, never()).setMessageHandler(CHANNEL_NAME, null); + // FLUTTER_STABLE_CONDITIONAL_ENDIF } @Test diff --git a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart index 9cd0196f51db..24d694ffa0cc 100644 --- a/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart +++ b/packages/url_launcher/url_launcher_web/example/integration_test/url_launcher_web_test.mocks.dart @@ -1,57 +1,54 @@ -// 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. - -// Mocks generated by Mockito 5.0.2 from annotations +// Mocks generated by Mockito 5.0.16 from annotations // in regular_integration_tests/integration_test/url_launcher_web_test.dart. // Do not manually edit this file. -import 'dart:async' as _i4; +import 'dart:async' as _i3; import 'dart:html' as _i2; -import 'dart:math' as _i5; -import 'dart:web_sql' as _i3; +import 'dart:math' as _i4; import 'package:mockito/mockito.dart' as _i1; +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types -class _FakeDocument extends _i1.Fake implements _i2.Document {} - -class _FakeLocation extends _i1.Fake implements _i2.Location {} +class _FakeDocument_0 extends _i1.Fake implements _i2.Document {} -class _FakeConsole extends _i1.Fake implements _i2.Console {} +class _FakeLocation_1 extends _i1.Fake implements _i2.Location {} -class _FakeHistory extends _i1.Fake implements _i2.History {} +class _FakeConsole_2 extends _i1.Fake implements _i2.Console {} -class _FakeStorage extends _i1.Fake implements _i2.Storage {} +class _FakeHistory_3 extends _i1.Fake implements _i2.History {} -class _FakeNavigator extends _i1.Fake implements _i2.Navigator {} +class _FakeStorage_4 extends _i1.Fake implements _i2.Storage {} -class _FakePerformance extends _i1.Fake implements _i2.Performance {} +class _FakeNavigator_5 extends _i1.Fake implements _i2.Navigator {} -class _FakeEvents extends _i1.Fake implements _i2.Events {} +class _FakePerformance_6 extends _i1.Fake implements _i2.Performance {} -class _FakeType extends _i1.Fake implements Type {} +class _FakeEvents_7 extends _i1.Fake implements _i2.Events {} -class _FakeWindowBase extends _i1.Fake implements _i2.WindowBase {} +class _FakeWindowBase_8 extends _i1.Fake implements _i2.WindowBase {} -class _FakeFileSystem extends _i1.Fake implements _i2.FileSystem {} +class _FakeFileSystem_9 extends _i1.Fake implements _i2.FileSystem {} -class _FakeStylePropertyMapReadonly extends _i1.Fake +class _FakeStylePropertyMapReadonly_10 extends _i1.Fake implements _i2.StylePropertyMapReadonly {} -class _FakeMediaQueryList extends _i1.Fake implements _i2.MediaQueryList {} - -class _FakeEntry extends _i1.Fake implements _i2.Entry {} +class _FakeMediaQueryList_11 extends _i1.Fake implements _i2.MediaQueryList {} -class _FakeSqlDatabase extends _i1.Fake implements _i3.SqlDatabase {} +class _FakeEntry_12 extends _i1.Fake implements _i2.Entry {} -class _FakeGeolocation extends _i1.Fake implements _i2.Geolocation {} +class _FakeGeolocation_13 extends _i1.Fake implements _i2.Geolocation {} -class _FakeMediaStream extends _i1.Fake implements _i2.MediaStream {} +class _FakeMediaStream_14 extends _i1.Fake implements _i2.MediaStream {} -class _FakeRelatedApplication extends _i1.Fake +class _FakeRelatedApplication_15 extends _i1.Fake implements _i2.RelatedApplication {} /// A class which mocks [Window]. @@ -63,37 +60,52 @@ class MockWindow extends _i1.Mock implements _i2.Window { } @override - _i4.Future get animationFrame => + _i3.Future get animationFrame => (super.noSuchMethod(Invocation.getter(#animationFrame), - returnValue: Future.value(0)) as _i4.Future); + returnValue: Future.value(0)) as _i3.Future); @override _i2.Document get document => (super.noSuchMethod(Invocation.getter(#document), - returnValue: _FakeDocument()) as _i2.Document); + returnValue: _FakeDocument_0()) as _i2.Document); @override _i2.Location get location => (super.noSuchMethod(Invocation.getter(#location), - returnValue: _FakeLocation()) as _i2.Location); + returnValue: _FakeLocation_1()) as _i2.Location); @override set location(_i2.LocationBase? value) => super.noSuchMethod(Invocation.setter(#location, value), returnValueForMissingStub: null); @override _i2.Console get console => (super.noSuchMethod(Invocation.getter(#console), - returnValue: _FakeConsole()) as _i2.Console); + returnValue: _FakeConsole_2()) as _i2.Console); + @override + set defaultStatus(String? value) => + super.noSuchMethod(Invocation.setter(#defaultStatus, value), + returnValueForMissingStub: null); + @override + set defaultstatus(String? value) => + super.noSuchMethod(Invocation.setter(#defaultstatus, value), + returnValueForMissingStub: null); @override num get devicePixelRatio => (super.noSuchMethod(Invocation.getter(#devicePixelRatio), returnValue: 0) as num); @override _i2.History get history => (super.noSuchMethod(Invocation.getter(#history), - returnValue: _FakeHistory()) as _i2.History); + returnValue: _FakeHistory_3()) as _i2.History); @override _i2.Storage get localStorage => (super.noSuchMethod(Invocation.getter(#localStorage), - returnValue: _FakeStorage()) as _i2.Storage); + returnValue: _FakeStorage_4()) as _i2.Storage); + @override + set name(String? value) => super.noSuchMethod(Invocation.setter(#name, value), + returnValueForMissingStub: null); @override _i2.Navigator get navigator => (super.noSuchMethod(Invocation.getter(#navigator), - returnValue: _FakeNavigator()) as _i2.Navigator); + returnValue: _FakeNavigator_5()) as _i2.Navigator); + @override + set opener(_i2.WindowBase? value) => + super.noSuchMethod(Invocation.setter(#opener, value), + returnValueForMissingStub: null); @override int get outerHeight => (super.noSuchMethod(Invocation.getter(#outerHeight), returnValue: 0) @@ -105,353 +117,357 @@ class MockWindow extends _i1.Mock implements _i2.Window { @override _i2.Performance get performance => (super.noSuchMethod(Invocation.getter(#performance), - returnValue: _FakePerformance()) as _i2.Performance); + returnValue: _FakePerformance_6()) as _i2.Performance); @override _i2.Storage get sessionStorage => (super.noSuchMethod(Invocation.getter(#sessionStorage), - returnValue: _FakeStorage()) as _i2.Storage); + returnValue: _FakeStorage_4()) as _i2.Storage); @override - _i4.Stream<_i2.Event> get onContentLoaded => + set status(String? value) => + super.noSuchMethod(Invocation.setter(#status, value), + returnValueForMissingStub: null); + @override + _i3.Stream<_i2.Event> get onContentLoaded => (super.noSuchMethod(Invocation.getter(#onContentLoaded), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onAbort => + _i3.Stream<_i2.Event> get onAbort => (super.noSuchMethod(Invocation.getter(#onAbort), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onBlur => + _i3.Stream<_i2.Event> get onBlur => (super.noSuchMethod(Invocation.getter(#onBlur), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onCanPlay => + _i3.Stream<_i2.Event> get onCanPlay => (super.noSuchMethod(Invocation.getter(#onCanPlay), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onCanPlayThrough => + _i3.Stream<_i2.Event> get onCanPlayThrough => (super.noSuchMethod(Invocation.getter(#onCanPlayThrough), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onChange => + _i3.Stream<_i2.Event> get onChange => (super.noSuchMethod(Invocation.getter(#onChange), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.MouseEvent> get onClick => + _i3.Stream<_i2.MouseEvent> get onClick => (super.noSuchMethod(Invocation.getter(#onClick), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onContextMenu => + _i3.Stream<_i2.MouseEvent> get onContextMenu => (super.noSuchMethod(Invocation.getter(#onContextMenu), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.Event> get onDoubleClick => + _i3.Stream<_i2.Event> get onDoubleClick => (super.noSuchMethod(Invocation.getter(#onDoubleClick), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.DeviceMotionEvent> get onDeviceMotion => + _i3.Stream<_i2.DeviceMotionEvent> get onDeviceMotion => (super.noSuchMethod(Invocation.getter(#onDeviceMotion), returnValue: Stream<_i2.DeviceMotionEvent>.empty()) - as _i4.Stream<_i2.DeviceMotionEvent>); + as _i3.Stream<_i2.DeviceMotionEvent>); @override - _i4.Stream<_i2.DeviceOrientationEvent> get onDeviceOrientation => + _i3.Stream<_i2.DeviceOrientationEvent> get onDeviceOrientation => (super.noSuchMethod(Invocation.getter(#onDeviceOrientation), returnValue: Stream<_i2.DeviceOrientationEvent>.empty()) - as _i4.Stream<_i2.DeviceOrientationEvent>); + as _i3.Stream<_i2.DeviceOrientationEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDrag => + _i3.Stream<_i2.MouseEvent> get onDrag => (super.noSuchMethod(Invocation.getter(#onDrag), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDragEnd => + _i3.Stream<_i2.MouseEvent> get onDragEnd => (super.noSuchMethod(Invocation.getter(#onDragEnd), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDragEnter => + _i3.Stream<_i2.MouseEvent> get onDragEnter => (super.noSuchMethod(Invocation.getter(#onDragEnter), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDragLeave => + _i3.Stream<_i2.MouseEvent> get onDragLeave => (super.noSuchMethod(Invocation.getter(#onDragLeave), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDragOver => + _i3.Stream<_i2.MouseEvent> get onDragOver => (super.noSuchMethod(Invocation.getter(#onDragOver), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDragStart => + _i3.Stream<_i2.MouseEvent> get onDragStart => (super.noSuchMethod(Invocation.getter(#onDragStart), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onDrop => + _i3.Stream<_i2.MouseEvent> get onDrop => (super.noSuchMethod(Invocation.getter(#onDrop), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.Event> get onDurationChange => + _i3.Stream<_i2.Event> get onDurationChange => (super.noSuchMethod(Invocation.getter(#onDurationChange), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onEmptied => + _i3.Stream<_i2.Event> get onEmptied => (super.noSuchMethod(Invocation.getter(#onEmptied), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onEnded => + _i3.Stream<_i2.Event> get onEnded => (super.noSuchMethod(Invocation.getter(#onEnded), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onError => + _i3.Stream<_i2.Event> get onError => (super.noSuchMethod(Invocation.getter(#onError), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onFocus => + _i3.Stream<_i2.Event> get onFocus => (super.noSuchMethod(Invocation.getter(#onFocus), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onHashChange => + _i3.Stream<_i2.Event> get onHashChange => (super.noSuchMethod(Invocation.getter(#onHashChange), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onInput => + _i3.Stream<_i2.Event> get onInput => (super.noSuchMethod(Invocation.getter(#onInput), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onInvalid => + _i3.Stream<_i2.Event> get onInvalid => (super.noSuchMethod(Invocation.getter(#onInvalid), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.KeyboardEvent> get onKeyDown => + _i3.Stream<_i2.KeyboardEvent> get onKeyDown => (super.noSuchMethod(Invocation.getter(#onKeyDown), returnValue: Stream<_i2.KeyboardEvent>.empty()) - as _i4.Stream<_i2.KeyboardEvent>); + as _i3.Stream<_i2.KeyboardEvent>); @override - _i4.Stream<_i2.KeyboardEvent> get onKeyPress => + _i3.Stream<_i2.KeyboardEvent> get onKeyPress => (super.noSuchMethod(Invocation.getter(#onKeyPress), returnValue: Stream<_i2.KeyboardEvent>.empty()) - as _i4.Stream<_i2.KeyboardEvent>); + as _i3.Stream<_i2.KeyboardEvent>); @override - _i4.Stream<_i2.KeyboardEvent> get onKeyUp => + _i3.Stream<_i2.KeyboardEvent> get onKeyUp => (super.noSuchMethod(Invocation.getter(#onKeyUp), returnValue: Stream<_i2.KeyboardEvent>.empty()) - as _i4.Stream<_i2.KeyboardEvent>); + as _i3.Stream<_i2.KeyboardEvent>); @override - _i4.Stream<_i2.Event> get onLoad => + _i3.Stream<_i2.Event> get onLoad => (super.noSuchMethod(Invocation.getter(#onLoad), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onLoadedData => + _i3.Stream<_i2.Event> get onLoadedData => (super.noSuchMethod(Invocation.getter(#onLoadedData), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onLoadedMetadata => + _i3.Stream<_i2.Event> get onLoadedMetadata => (super.noSuchMethod(Invocation.getter(#onLoadedMetadata), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onLoadStart => + _i3.Stream<_i2.Event> get onLoadStart => (super.noSuchMethod(Invocation.getter(#onLoadStart), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.MessageEvent> get onMessage => + _i3.Stream<_i2.MessageEvent> get onMessage => (super.noSuchMethod(Invocation.getter(#onMessage), returnValue: Stream<_i2.MessageEvent>.empty()) - as _i4.Stream<_i2.MessageEvent>); + as _i3.Stream<_i2.MessageEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseDown => + _i3.Stream<_i2.MouseEvent> get onMouseDown => (super.noSuchMethod(Invocation.getter(#onMouseDown), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseEnter => + _i3.Stream<_i2.MouseEvent> get onMouseEnter => (super.noSuchMethod(Invocation.getter(#onMouseEnter), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseLeave => + _i3.Stream<_i2.MouseEvent> get onMouseLeave => (super.noSuchMethod(Invocation.getter(#onMouseLeave), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseMove => + _i3.Stream<_i2.MouseEvent> get onMouseMove => (super.noSuchMethod(Invocation.getter(#onMouseMove), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseOut => + _i3.Stream<_i2.MouseEvent> get onMouseOut => (super.noSuchMethod(Invocation.getter(#onMouseOut), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseOver => + _i3.Stream<_i2.MouseEvent> get onMouseOver => (super.noSuchMethod(Invocation.getter(#onMouseOver), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.MouseEvent> get onMouseUp => + _i3.Stream<_i2.MouseEvent> get onMouseUp => (super.noSuchMethod(Invocation.getter(#onMouseUp), returnValue: Stream<_i2.MouseEvent>.empty()) - as _i4.Stream<_i2.MouseEvent>); + as _i3.Stream<_i2.MouseEvent>); @override - _i4.Stream<_i2.WheelEvent> get onMouseWheel => + _i3.Stream<_i2.WheelEvent> get onMouseWheel => (super.noSuchMethod(Invocation.getter(#onMouseWheel), returnValue: Stream<_i2.WheelEvent>.empty()) - as _i4.Stream<_i2.WheelEvent>); + as _i3.Stream<_i2.WheelEvent>); @override - _i4.Stream<_i2.Event> get onOffline => + _i3.Stream<_i2.Event> get onOffline => (super.noSuchMethod(Invocation.getter(#onOffline), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onOnline => + _i3.Stream<_i2.Event> get onOnline => (super.noSuchMethod(Invocation.getter(#onOnline), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onPageHide => + _i3.Stream<_i2.Event> get onPageHide => (super.noSuchMethod(Invocation.getter(#onPageHide), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onPageShow => + _i3.Stream<_i2.Event> get onPageShow => (super.noSuchMethod(Invocation.getter(#onPageShow), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onPause => + _i3.Stream<_i2.Event> get onPause => (super.noSuchMethod(Invocation.getter(#onPause), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onPlay => + _i3.Stream<_i2.Event> get onPlay => (super.noSuchMethod(Invocation.getter(#onPlay), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onPlaying => + _i3.Stream<_i2.Event> get onPlaying => (super.noSuchMethod(Invocation.getter(#onPlaying), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.PopStateEvent> get onPopState => + _i3.Stream<_i2.PopStateEvent> get onPopState => (super.noSuchMethod(Invocation.getter(#onPopState), returnValue: Stream<_i2.PopStateEvent>.empty()) - as _i4.Stream<_i2.PopStateEvent>); + as _i3.Stream<_i2.PopStateEvent>); @override - _i4.Stream<_i2.Event> get onProgress => + _i3.Stream<_i2.Event> get onProgress => (super.noSuchMethod(Invocation.getter(#onProgress), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onRateChange => + _i3.Stream<_i2.Event> get onRateChange => (super.noSuchMethod(Invocation.getter(#onRateChange), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onReset => + _i3.Stream<_i2.Event> get onReset => (super.noSuchMethod(Invocation.getter(#onReset), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onResize => + _i3.Stream<_i2.Event> get onResize => (super.noSuchMethod(Invocation.getter(#onResize), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onScroll => + _i3.Stream<_i2.Event> get onScroll => (super.noSuchMethod(Invocation.getter(#onScroll), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onSearch => + _i3.Stream<_i2.Event> get onSearch => (super.noSuchMethod(Invocation.getter(#onSearch), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onSeeked => + _i3.Stream<_i2.Event> get onSeeked => (super.noSuchMethod(Invocation.getter(#onSeeked), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onSeeking => + _i3.Stream<_i2.Event> get onSeeking => (super.noSuchMethod(Invocation.getter(#onSeeking), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onSelect => + _i3.Stream<_i2.Event> get onSelect => (super.noSuchMethod(Invocation.getter(#onSelect), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onStalled => + _i3.Stream<_i2.Event> get onStalled => (super.noSuchMethod(Invocation.getter(#onStalled), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.StorageEvent> get onStorage => + _i3.Stream<_i2.StorageEvent> get onStorage => (super.noSuchMethod(Invocation.getter(#onStorage), returnValue: Stream<_i2.StorageEvent>.empty()) - as _i4.Stream<_i2.StorageEvent>); + as _i3.Stream<_i2.StorageEvent>); @override - _i4.Stream<_i2.Event> get onSubmit => + _i3.Stream<_i2.Event> get onSubmit => (super.noSuchMethod(Invocation.getter(#onSubmit), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onSuspend => + _i3.Stream<_i2.Event> get onSuspend => (super.noSuchMethod(Invocation.getter(#onSuspend), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onTimeUpdate => + _i3.Stream<_i2.Event> get onTimeUpdate => (super.noSuchMethod(Invocation.getter(#onTimeUpdate), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.TouchEvent> get onTouchCancel => + _i3.Stream<_i2.TouchEvent> get onTouchCancel => (super.noSuchMethod(Invocation.getter(#onTouchCancel), returnValue: Stream<_i2.TouchEvent>.empty()) - as _i4.Stream<_i2.TouchEvent>); + as _i3.Stream<_i2.TouchEvent>); @override - _i4.Stream<_i2.TouchEvent> get onTouchEnd => + _i3.Stream<_i2.TouchEvent> get onTouchEnd => (super.noSuchMethod(Invocation.getter(#onTouchEnd), returnValue: Stream<_i2.TouchEvent>.empty()) - as _i4.Stream<_i2.TouchEvent>); + as _i3.Stream<_i2.TouchEvent>); @override - _i4.Stream<_i2.TouchEvent> get onTouchMove => + _i3.Stream<_i2.TouchEvent> get onTouchMove => (super.noSuchMethod(Invocation.getter(#onTouchMove), returnValue: Stream<_i2.TouchEvent>.empty()) - as _i4.Stream<_i2.TouchEvent>); + as _i3.Stream<_i2.TouchEvent>); @override - _i4.Stream<_i2.TouchEvent> get onTouchStart => + _i3.Stream<_i2.TouchEvent> get onTouchStart => (super.noSuchMethod(Invocation.getter(#onTouchStart), returnValue: Stream<_i2.TouchEvent>.empty()) - as _i4.Stream<_i2.TouchEvent>); + as _i3.Stream<_i2.TouchEvent>); @override - _i4.Stream<_i2.TransitionEvent> get onTransitionEnd => + _i3.Stream<_i2.TransitionEvent> get onTransitionEnd => (super.noSuchMethod(Invocation.getter(#onTransitionEnd), returnValue: Stream<_i2.TransitionEvent>.empty()) - as _i4.Stream<_i2.TransitionEvent>); + as _i3.Stream<_i2.TransitionEvent>); @override - _i4.Stream<_i2.Event> get onUnload => + _i3.Stream<_i2.Event> get onUnload => (super.noSuchMethod(Invocation.getter(#onUnload), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onVolumeChange => + _i3.Stream<_i2.Event> get onVolumeChange => (super.noSuchMethod(Invocation.getter(#onVolumeChange), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.Event> get onWaiting => + _i3.Stream<_i2.Event> get onWaiting => (super.noSuchMethod(Invocation.getter(#onWaiting), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.AnimationEvent> get onAnimationEnd => + _i3.Stream<_i2.AnimationEvent> get onAnimationEnd => (super.noSuchMethod(Invocation.getter(#onAnimationEnd), returnValue: Stream<_i2.AnimationEvent>.empty()) - as _i4.Stream<_i2.AnimationEvent>); + as _i3.Stream<_i2.AnimationEvent>); @override - _i4.Stream<_i2.AnimationEvent> get onAnimationIteration => + _i3.Stream<_i2.AnimationEvent> get onAnimationIteration => (super.noSuchMethod(Invocation.getter(#onAnimationIteration), returnValue: Stream<_i2.AnimationEvent>.empty()) - as _i4.Stream<_i2.AnimationEvent>); + as _i3.Stream<_i2.AnimationEvent>); @override - _i4.Stream<_i2.AnimationEvent> get onAnimationStart => + _i3.Stream<_i2.AnimationEvent> get onAnimationStart => (super.noSuchMethod(Invocation.getter(#onAnimationStart), returnValue: Stream<_i2.AnimationEvent>.empty()) - as _i4.Stream<_i2.AnimationEvent>); + as _i3.Stream<_i2.AnimationEvent>); @override - _i4.Stream<_i2.Event> get onBeforeUnload => + _i3.Stream<_i2.Event> get onBeforeUnload => (super.noSuchMethod(Invocation.getter(#onBeforeUnload), - returnValue: Stream<_i2.Event>.empty()) as _i4.Stream<_i2.Event>); + returnValue: Stream<_i2.Event>.empty()) as _i3.Stream<_i2.Event>); @override - _i4.Stream<_i2.WheelEvent> get onWheel => + _i3.Stream<_i2.WheelEvent> get onWheel => (super.noSuchMethod(Invocation.getter(#onWheel), returnValue: Stream<_i2.WheelEvent>.empty()) - as _i4.Stream<_i2.WheelEvent>); + as _i3.Stream<_i2.WheelEvent>); @override int get pageXOffset => (super.noSuchMethod(Invocation.getter(#pageXOffset), returnValue: 0) @@ -468,18 +484,12 @@ class MockWindow extends _i1.Mock implements _i2.Window { (super.noSuchMethod(Invocation.getter(#scrollY), returnValue: 0) as int); @override _i2.Events get on => - (super.noSuchMethod(Invocation.getter(#on), returnValue: _FakeEvents()) + (super.noSuchMethod(Invocation.getter(#on), returnValue: _FakeEvents_7()) as _i2.Events); @override - int get hashCode => - (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); - @override - Type get runtimeType => (super.noSuchMethod(Invocation.getter(#runtimeType), - returnValue: _FakeType()) as Type); - @override _i2.WindowBase open(String? url, String? name, [String? options]) => (super.noSuchMethod(Invocation.method(#open, [url, name, options]), - returnValue: _FakeWindowBase()) as _i2.WindowBase); + returnValue: _FakeWindowBase_8()) as _i2.WindowBase); @override int requestAnimationFrame(_i2.FrameRequestCallback? callback) => (super.noSuchMethod(Invocation.method(#requestAnimationFrame, [callback]), @@ -489,25 +499,32 @@ class MockWindow extends _i1.Mock implements _i2.Window { super.noSuchMethod(Invocation.method(#cancelAnimationFrame, [id]), returnValueForMissingStub: null); @override - _i4.Future<_i2.FileSystem> requestFileSystem(int? size, + _i3.Future<_i2.FileSystem> requestFileSystem(int? size, {bool? persistent = false}) => (super.noSuchMethod( Invocation.method( #requestFileSystem, [size], {#persistent: persistent}), - returnValue: Future.value(_FakeFileSystem())) - as _i4.Future<_i2.FileSystem>); + returnValue: Future<_i2.FileSystem>.value(_FakeFileSystem_9())) + as _i3.Future<_i2.FileSystem>); + @override + void alert([String? message]) => + super.noSuchMethod(Invocation.method(#alert, [message]), + returnValueForMissingStub: null); @override void cancelIdleCallback(int? handle) => super.noSuchMethod(Invocation.method(#cancelIdleCallback, [handle]), returnValueForMissingStub: null); @override + void close() => super.noSuchMethod(Invocation.method(#close, []), + returnValueForMissingStub: null); + @override bool confirm([String? message]) => (super.noSuchMethod(Invocation.method(#confirm, [message]), returnValue: false) as bool); @override - _i4.Future fetch(dynamic input, [Map? init]) => + _i3.Future fetch(dynamic input, [Map? init]) => (super.noSuchMethod(Invocation.method(#fetch, [input, init]), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override bool find(String? string, bool? caseSensitive, bool? backwards, bool? wrap, bool? wholeWord, bool? searchInFrames, bool? showDialog) => @@ -527,7 +544,7 @@ class MockWindow extends _i1.Mock implements _i2.Window { _i2.Element? element, String? pseudoElement) => (super.noSuchMethod( Invocation.method(#getComputedStyleMap, [element, pseudoElement]), - returnValue: _FakeStylePropertyMapReadonly()) + returnValue: _FakeStylePropertyMapReadonly_10()) as _i2.StylePropertyMapReadonly); @override List<_i2.CssRule> getMatchedCssRules( @@ -538,7 +555,7 @@ class MockWindow extends _i1.Mock implements _i2.Window { @override _i2.MediaQueryList matchMedia(String? query) => (super.noSuchMethod(Invocation.method(#matchMedia, [query]), - returnValue: _FakeMediaQueryList()) as _i2.MediaQueryList); + returnValue: _FakeMediaQueryList_11()) as _i2.MediaQueryList); @override void moveBy(int? x, int? y) => super.noSuchMethod(Invocation.method(#moveBy, [x, y]), @@ -550,6 +567,9 @@ class MockWindow extends _i1.Mock implements _i2.Window { Invocation.method(#postMessage, [message, targetOrigin, transfer]), returnValueForMissingStub: null); @override + void print() => super.noSuchMethod(Invocation.method(#print, []), + returnValueForMissingStub: null); + @override int requestIdleCallback(_i2.IdleRequestCallback? callback, [Map? options]) => (super.noSuchMethod( @@ -564,9 +584,37 @@ class MockWindow extends _i1.Mock implements _i2.Window { super.noSuchMethod(Invocation.method(#resizeTo, [x, y]), returnValueForMissingStub: null); @override - _i4.Future<_i2.Entry> resolveLocalFileSystemUrl(String? url) => + void scroll( + [dynamic options_OR_x, + dynamic y, + Map? scrollOptions]) => + super.noSuchMethod( + Invocation.method(#scroll, [options_OR_x, y, scrollOptions]), + returnValueForMissingStub: null); + @override + void scrollBy( + [dynamic options_OR_x, + dynamic y, + Map? scrollOptions]) => + super.noSuchMethod( + Invocation.method(#scrollBy, [options_OR_x, y, scrollOptions]), + returnValueForMissingStub: null); + @override + void scrollTo( + [dynamic options_OR_x, + dynamic y, + Map? scrollOptions]) => + super.noSuchMethod( + Invocation.method(#scrollTo, [options_OR_x, y, scrollOptions]), + returnValueForMissingStub: null); + @override + void stop() => super.noSuchMethod(Invocation.method(#stop, []), + returnValueForMissingStub: null); + @override + _i3.Future<_i2.Entry> resolveLocalFileSystemUrl(String? url) => (super.noSuchMethod(Invocation.method(#resolveLocalFileSystemUrl, [url]), - returnValue: Future.value(_FakeEntry())) as _i4.Future<_i2.Entry>); + returnValue: Future<_i2.Entry>.value(_FakeEntry_12())) + as _i3.Future<_i2.Entry>); @override String atob(String? atob) => (super.noSuchMethod(Invocation.method(#atob, [atob]), returnValue: '') @@ -576,18 +624,10 @@ class MockWindow extends _i1.Mock implements _i2.Window { (super.noSuchMethod(Invocation.method(#btoa, [btoa]), returnValue: '') as String); @override - void moveTo(_i5.Point? p) => + void moveTo(_i4.Point? p) => super.noSuchMethod(Invocation.method(#moveTo, [p]), returnValueForMissingStub: null); @override - _i3.SqlDatabase openDatabase(String? name, String? version, - String? displayName, int? estimatedSize, - [_i2.DatabaseCallback? creationCallback]) => - (super.noSuchMethod( - Invocation.method(#openDatabase, - [name, version, displayName, estimatedSize, creationCallback]), - returnValue: _FakeSqlDatabase()) as _i3.SqlDatabase); - @override void addEventListener(String? type, _i2.EventListener? listener, [bool? useCapture]) => super.noSuchMethod( @@ -604,13 +644,7 @@ class MockWindow extends _i1.Mock implements _i2.Window { (super.noSuchMethod(Invocation.method(#dispatchEvent, [event]), returnValue: false) as bool); @override - bool operator ==(Object? other) => - (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) - as bool); - @override - String toString() => - (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') - as String); + String toString() => super.toString(); } /// A class which mocks [Navigator]. @@ -628,7 +662,7 @@ class MockNavigator extends _i1.Mock implements _i2.Navigator { @override _i2.Geolocation get geolocation => (super.noSuchMethod(Invocation.getter(#geolocation), - returnValue: _FakeGeolocation()) as _i2.Geolocation); + returnValue: _FakeGeolocation_13()) as _i2.Geolocation); @override String get vendor => (super.noSuchMethod(Invocation.getter(#vendor), returnValue: '') @@ -658,69 +692,63 @@ class MockNavigator extends _i1.Mock implements _i2.Navigator { (super.noSuchMethod(Invocation.getter(#userAgent), returnValue: '') as String); @override - int get hashCode => - (super.noSuchMethod(Invocation.getter(#hashCode), returnValue: 0) as int); - @override - Type get runtimeType => (super.noSuchMethod(Invocation.getter(#runtimeType), - returnValue: _FakeType()) as Type); - @override List<_i2.Gamepad?> getGamepads() => (super.noSuchMethod(Invocation.method(#getGamepads, []), returnValue: <_i2.Gamepad?>[]) as List<_i2.Gamepad?>); @override - _i4.Future<_i2.MediaStream> getUserMedia( + _i3.Future<_i2.MediaStream> getUserMedia( {dynamic audio = false, dynamic video = false}) => (super.noSuchMethod( Invocation.method(#getUserMedia, [], {#audio: audio, #video: video}), returnValue: - Future.value(_FakeMediaStream())) as _i4.Future<_i2.MediaStream>); + Future<_i2.MediaStream>.value(_FakeMediaStream_14())) as _i3 + .Future<_i2.MediaStream>); @override - _i4.Future getBattery() => + void cancelKeyboardLock() => + super.noSuchMethod(Invocation.method(#cancelKeyboardLock, []), + returnValueForMissingStub: null); + @override + _i3.Future getBattery() => (super.noSuchMethod(Invocation.method(#getBattery, []), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override - _i4.Future<_i2.RelatedApplication> getInstalledRelatedApps() => + _i3.Future<_i2.RelatedApplication> getInstalledRelatedApps() => (super.noSuchMethod(Invocation.method(#getInstalledRelatedApps, []), - returnValue: Future.value(_FakeRelatedApplication())) - as _i4.Future<_i2.RelatedApplication>); + returnValue: Future<_i2.RelatedApplication>.value( + _FakeRelatedApplication_15())) + as _i3.Future<_i2.RelatedApplication>); @override - _i4.Future getVRDisplays() => + _i3.Future getVRDisplays() => (super.noSuchMethod(Invocation.method(#getVRDisplays, []), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override void registerProtocolHandler(String? scheme, String? url, String? title) => super.noSuchMethod( Invocation.method(#registerProtocolHandler, [scheme, url, title]), returnValueForMissingStub: null); @override - _i4.Future requestKeyboardLock([List? keyCodes]) => + _i3.Future requestKeyboardLock([List? keyCodes]) => (super.noSuchMethod(Invocation.method(#requestKeyboardLock, [keyCodes]), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override - _i4.Future requestMidiAccess([Map? options]) => + _i3.Future requestMidiAccess([Map? options]) => (super.noSuchMethod(Invocation.method(#requestMidiAccess, [options]), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override - _i4.Future requestMediaKeySystemAccess(String? keySystem, + _i3.Future requestMediaKeySystemAccess(String? keySystem, List>? supportedConfigurations) => (super.noSuchMethod( Invocation.method(#requestMediaKeySystemAccess, [keySystem, supportedConfigurations]), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override bool sendBeacon(String? url, Object? data) => (super.noSuchMethod(Invocation.method(#sendBeacon, [url, data]), returnValue: false) as bool); @override - _i4.Future share([Map? data]) => + _i3.Future share([Map? data]) => (super.noSuchMethod(Invocation.method(#share, [data]), - returnValue: Future.value(null)) as _i4.Future); + returnValue: Future.value()) as _i3.Future); @override - bool operator ==(Object? other) => - (super.noSuchMethod(Invocation.method(#==, [other]), returnValue: false) - as bool); - @override - String toString() => - (super.noSuchMethod(Invocation.method(#toString, []), returnValue: '') - as String); + String toString() => super.toString(); } diff --git a/packages/url_launcher/url_launcher_web/example/pubspec.yaml b/packages/url_launcher/url_launcher_web/example/pubspec.yaml index 7c00c33550a8..872bc8873b5c 100644 --- a/packages/url_launcher/url_launcher_web/example/pubspec.yaml +++ b/packages/url_launcher/url_launcher_web/example/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: sdk: flutter dev_dependencies: - build_runner: ^1.10.0 + build_runner: ^2.1.1 mockito: ^5.0.0 url_launcher_web: path: ../ From 97c2483be0d67d2a89c5f2d9792c8d3f41c9b917 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Tue, 26 Oct 2021 13:52:31 -0700 Subject: [PATCH 5/7] Implement Android WebView api with pigeon (Dart portion) (#4435) --- .../generatePigeons.sh | 8 + .../lib/src/android_webview.dart | 648 +++++++ .../lib/src/android_webview.pigeon.dart | 1601 +++++++++++++++++ .../lib/src/android_webview_api_impls.dart | 622 +++++++ .../lib/src/instance_manager.dart | 52 + .../pigeons/android_webview.dart | 181 ++ .../webview_flutter_android/pubspec.yaml | 1 + .../test/android_webview.pigeon.dart | 1000 ++++++++++ .../test/android_webview_test.dart | 373 ++++ .../test/instance_manager_test.dart | 35 + 10 files changed, 4521 insertions(+) create mode 100755 packages/webview_flutter/webview_flutter_android/generatePigeons.sh create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart create mode 100644 packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart create mode 100644 packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart create mode 100644 packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart create mode 100644 packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart create mode 100644 packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh new file mode 100755 index 000000000000..d866473636cc --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -0,0 +1,8 @@ +# 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. + +flutter pub run pigeon \ +--input pigeons/android_webview.dart \ +--dart_out lib/src/android_webview.pigeon.dart \ +--dart_test_out test/android_webview.pigeon.dart diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart new file mode 100644 index 000000000000..1ddd6f3d9f0f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -0,0 +1,648 @@ +// 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:flutter/foundation.dart'; +import 'package:flutter/widgets.dart' show AndroidViewSurface; + +import 'android_webview_api_impls.dart'; + +// TODO(bparrishMines): This can be removed once pigeon supports null values: https://github.com/flutter/flutter/issues/59118 +// Workaround to represent null Strings since pigeon doesn't support null +// values. +const String _nullStringIdentifier = ''; + +/// An Android View that displays web pages. +/// +/// **Basic usage** +/// In most cases, we recommend using a standard web browser, like Chrome, to +/// deliver content to the user. To learn more about web browsers, read the +/// guide on invoking a browser with +/// [url_launcher](https://pub.dev/packages/url_launcher). +/// +/// WebView objects allow you to display web content as part of your widget +/// layout, but lack some of the features of fully-developed browsers. A WebView +/// is useful when you need increased control over the UI and advanced +/// configuration options that will allow you to embed web pages in a +/// specially-designed environment for your app. +/// +/// To learn more about WebView and alternatives for serving web content, read +/// the documentation on +/// [Web-based content](https://developer.android.com/guide/webapps). +class WebView { + /// Constructs a new WebView. + WebView({this.useHybridComposition = false}) { + api.createFromInstance(this); + } + + /// Pigeon Host Api implementation for [WebView]. + @visibleForTesting + static WebViewHostApiImpl api = WebViewHostApiImpl(); + + WebViewClient? _currentWebViewClient; + DownloadListener? _currentDownloadListener; + WebChromeClient? _currentWebChromeClient; + Set _javaScriptChannels = {}; + + /// Whether the [WebView] will be rendered with an [AndroidViewSurface]. + /// + /// This implementation uses hybrid composition to render the WebView Widget. + /// This comes at the cost of some performance on Android versions below 10. + /// See + /// https://flutter.dev/docs/development/platform-integration/platform-views#performance + /// for more information. + /// + /// Defaults to false. + final bool useHybridComposition; + + /// The [WebSettings] object used to control the settings for this WebView. + late final WebSettings settings = WebSettings(this); + + /// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. + /// + /// This flag can be enabled in order to facilitate debugging of web layouts + /// and JavaScript code running inside WebViews. Please refer to [WebView] + /// documentation for the debugging guide. The default is false. + static Future setWebContentsDebuggingEnabled(bool enabled) { + return api.setWebContentsDebuggingEnabled(enabled); + } + + /// Loads the given URL with additional HTTP headers, specified as a map from name to value. + /// + /// Note that if this map contains any of the headers that are set by default + /// by this WebView, such as those controlling caching, accept types or the + /// User-Agent, their values may be overridden by this WebView's defaults. + /// + /// Also see compatibility note on [evaluateJavascript]. + Future loadUrl(String url, Map headers) { + return api.loadUrlFromInstance(this, url, headers); + } + + /// Gets the URL for the current page. + /// + /// This is not always the same as the URL passed to + /// [WebViewClient.onPageStarted] because although the load for that URL has + /// begun, the current page may not have changed. + /// + /// Returns null if no page has been loaded. + Future getUrl() async { + final String result = await api.getUrlFromInstance(this); + if (result == _nullStringIdentifier) return null; + return result; + } + + /// Whether this WebView has a back history item. + Future canGoBack() { + return api.canGoBackFromInstance(this); + } + + /// Whether this WebView has a forward history item. + Future canGoForward() { + return api.canGoForwardFromInstance(this); + } + + /// Goes back in the history of this WebView. + Future goBack() { + return api.goBackFromInstance(this); + } + + /// Goes forward in the history of this WebView. + Future goForward() { + return api.goForwardFromInstance(this); + } + + /// Reloads the current URL. + Future reload() { + return api.reloadFromInstance(this); + } + + /// Clears the resource cache. + /// + /// Note that the cache is per-application, so this will clear the cache for + /// all WebViews used. + Future clearCache(bool includeDiskFiles) { + return api.clearCacheFromInstance(this, includeDiskFiles); + } + + // TODO(bparrishMines): Update documentation once addJavascriptInterface is added. + /// Asynchronously evaluates JavaScript in the context of the currently displayed page. + /// + /// If non-null, the returned value will be any result returned from that + /// execution. + /// + /// Compatibility note. Applications targeting Android versions N or later, + /// JavaScript state from an empty WebView is no longer persisted across + /// navigations like [loadUrl]. For example, global variables and functions + /// defined before calling [loadUrl]) will not exist in the loaded page. + Future evaluateJavascript(String javascriptString) async { + final String result = await api.evaluateJavascriptFromInstance( + this, + javascriptString, + ); + if (result == _nullStringIdentifier) return null; + return result; + } + + // TODO(bparrishMines): Update documentation when WebViewClient.onReceivedTitle is added. + /// Gets the title for the current page. + /// + /// Returns null if no page has been loaded. + Future getTitle() async { + final String result = await api.getTitleFromInstance(this); + if (result == _nullStringIdentifier) return null; + return result; + } + + // TODO(bparrishMines): Update documentation when onScrollChanged is added. + /// Set the scrolled position of your view. + Future scrollTo(int x, int y) { + return api.scrollToFromInstance(this, x, y); + } + + // TODO(bparrishMines): Update documentation when onScrollChanged is added. + /// Move the scrolled position of your view. + Future scrollBy(int x, int y) { + return api.scrollByFromInstance(this, x, y); + } + + /// Return the scrolled left position of this view. + /// + /// This is the left edge of the displayed part of your view. You do not + /// need to draw any pixels farther left, since those are outside of the frame + /// of your view on screen. + Future getScrollX() { + return api.getScrollXFromInstance(this); + } + + /// Return the scrolled top position of this view. + /// + /// This is the top edge of the displayed part of your view. You do not need + /// to draw any pixels above it, since those are outside of the frame of your + /// view on screen. + Future getScrollY() { + return api.getScrollYFromInstance(this); + } + + /// Sets the [WebViewClient] that will receive various notifications and requests. + /// + /// This will replace the current handler. + Future setWebViewClient(WebViewClient webViewClient) { + final WebViewClient? currentWebViewClient = _currentWebViewClient; + + if (webViewClient == currentWebViewClient) { + return Future.value(); + } + + if (currentWebViewClient != null) { + WebViewClient.api.disposeFromInstance(currentWebViewClient); + } + + WebViewClient.api.createFromInstance(webViewClient); + _currentWebViewClient = webViewClient; + return api.setWebViewClientFromInstance(this, webViewClient); + } + + /// Injects the supplied [JavascriptChannel] into this WebView. + /// + /// The object is injected into all frames of the web page, including all the + /// iframes, using the supplied name. This allows the object's methods to + /// be accessed from JavaScript. + /// + /// Note that injected objects will not appear in JavaScript until the page is + /// next (re)loaded. JavaScript should be enabled before injecting the object. + /// For example: + /// + /// ```dart + /// webview.settings.setJavaScriptEnabled(true); + /// webView.addJavascriptChannel(JavScriptChannel("injectedObject")); + /// webView.loadUrl("about:blank", {}); + /// webView.loadUrl("javascript:injectedObject.postMessage("Hello, World!")", {}); + /// ``` + /// + /// **Important** + /// * Because the object is exposed to all the frames, any frame could obtain + /// the object name and call methods on it. There is no way to tell the + /// calling frame's origin from the app side, so the app must not assume that + /// the caller is trustworthy unless the app can guarantee that no third party + /// content is ever loaded into the WebView even inside an iframe. + Future addJavaScriptChannel(JavaScriptChannel javaScriptChannel) { + JavaScriptChannel.api.createFromInstance(javaScriptChannel); + _javaScriptChannels.add(javaScriptChannel); + return api.addJavaScriptChannelFromInstance(this, javaScriptChannel); + } + + /// Removes a previously injected [JavaScriptChannel] from this WebView. + /// + /// Note that the removal will not be reflected in JavaScript until the page + /// is next (re)loaded. See [addJavaScriptChannel]. + Future removeJavaScriptChannel(JavaScriptChannel javaScriptChannel) { + _javaScriptChannels.remove(javaScriptChannel); + api.removeJavaScriptChannelFromInstance(this, javaScriptChannel); + return JavaScriptChannel.api.disposeFromInstance(javaScriptChannel); + } + + /// Registers the interface to be used when content can not be handled by the rendering engine, and should be downloaded instead. + /// + /// This will replace the current handler. + Future setDownloadListener(DownloadListener listener) { + final DownloadListener? currentDownloadListener = _currentDownloadListener; + + if (listener == currentDownloadListener) { + return Future.value(); + } + + if (currentDownloadListener != null) { + DownloadListener.api.disposeFromInstance(currentDownloadListener); + } + + DownloadListener.api.createFromInstance(listener); + _currentDownloadListener = listener; + return api.setDownloadListenerFromInstance(this, listener); + } + + /// Sets the chrome handler. + /// + /// This is an implementation of [WebChromeClient] for use in handling + /// JavaScript dialogs, favicons, titles, and the progress. This will replace + /// the current handler. + Future setWebChromeClient(WebChromeClient client) { + final WebChromeClient? currentWebChromeClient = _currentWebChromeClient; + + if (client == currentWebChromeClient) { + return Future.value(); + } + + if (currentWebChromeClient != null) { + WebChromeClient.api.disposeFromInstance(currentWebChromeClient); + } + + final WebViewClient? currentWebViewClient = _currentWebViewClient; + assert( + currentWebViewClient != null, + "Can't set a WebChromeClient without setting a WebViewClient first.", + ); + + WebChromeClient.api.createFromInstance(client, currentWebViewClient!); + _currentWebChromeClient = client; + return api.setWebChromeClientFromInstance(this, client); + } +} + +/// Manages settings state for a [WebView]. +/// +/// When a WebView is first created, it obtains a set of default settings. These +/// default settings will be returned from any getter call. A WebSettings object +/// obtained from [WebView.settings] is tied to the life of the WebView. If a +/// WebView has been destroyed, any method call on [WebSettings] will throw an +/// Exception. +class WebSettings { + /// Constructs a [WebSettings]. + /// + /// This constructor is only used for testing. An instance should be obtained + /// with [WebView.settings]. + @visibleForTesting + WebSettings(WebView webView) { + api.createFromInstance(this, webView); + } + + /// Pigeon Host Api implementation for [WebSettings]. + @visibleForTesting + static WebSettingsHostApiImpl api = WebSettingsHostApiImpl(); + + /// Sets whether the DOM storage API is enabled. + /// + /// The default value is false. + Future setDomStorageEnabled(bool flag) { + return api.setDomStorageEnabledFromInstance(this, flag); + } + + /// Tells JavaScript to open windows automatically. + /// + /// This applies to the JavaScript function `window.open()`. The default is + /// false. + Future setJavaScriptCanOpenWindowsAutomatically(bool flag) { + return api.setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + this, + flag, + ); + } + + // TODO(bparrishMines): Update documentation when WebChromeClient.onCreateWindow is added. + /// Sets whether the WebView should supports multiple windows. + /// + /// The default is false. + Future setSupportMultipleWindows(bool support) { + return api.setSupportZoomFromInstance(this, support); + } + + /// Tells the WebView to enable JavaScript execution. + /// + /// The default is false. + Future setJavaScriptEnabled(bool flag) { + return api.setJavaScriptEnabledFromInstance(this, flag); + } + + /// Sets the WebView's user-agent string. + /// + /// If the string is empty, the system default value will be used. Note that + /// starting from KITKAT Android version, changing the user-agent while + /// loading a web page causes WebView to initiate loading once again. + Future setUserAgentString(String userAgentString) { + return api.setUserAgentStringFromInstance(this, userAgentString); + } + + /// Sets whether the WebView requires a user gesture to play media. + /// + /// The default is true. + Future setMediaPlaybackRequiresUserGesture(bool require) { + return api.setMediaPlaybackRequiresUserGestureFromInstance(this, require); + } + + // TODO(bparrishMines): Update documentation when WebView.zoomIn and WebView.zoomOut are added. + /// Sets whether the WebView should support zooming using its on-screen zoom controls and gestures. + /// + /// The particular zoom mechanisms that should be used can be set with + /// [setBuiltInZoomControls]. + /// + /// The default is true. + Future setSupportZoom(bool support) { + return api.setSupportZoomFromInstance(this, support); + } + + /// Sets whether the WebView loads pages in overview mode, that is, zooms out the content to fit on screen by width. + /// + /// This setting is taken into account when the content width is greater than + /// the width of the WebView control, for example, when [setUseWideViewPort] + /// is enabled. + /// + /// The default is false. + Future setLoadWithOverviewMode(bool overview) { + return api.setLoadWithOverviewModeFromInstance(this, overview); + } + + /// Sets whether the WebView should enable support for the "viewport" HTML meta tag or should use a wide viewport. + /// + /// When the value of the setting is false, the layout width is always set to + /// the width of the WebView control in device-independent (CSS) pixels. When + /// the value is true and the page contains the viewport meta tag, the value + /// of the width specified in the tag is used. If the page does not contain + /// the tag or does not provide a width, then a wide viewport will be used. + Future setUseWideViewPort(bool use) { + return api.setUseWideViewPortFromInstance(this, use); + } + + // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. + /// Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. + /// + /// See [setBuiltInZoomControls]. The default is true. However, on-screen zoom + /// controls are deprecated in Android so it's recommended to set this to + /// false. + Future setDisplayZoomControls(bool enabled) { + return api.setDisplayZoomControlsFromInstance(this, enabled); + } + + // TODO(bparrishMines): Update documentation when ZoomButtonsController is added. + /// Sets whether the WebView should use its built-in zoom mechanisms. + /// + /// The built-in zoom mechanisms comprise on-screen zoom controls, which are + /// displayed over the WebView's content, and the use of a pinch gesture to + /// control zooming. Whether or not these on-screen controls are displayed can + /// be set with [setDisplayZoomControls]. The default is false. + /// + /// The built-in mechanisms are the only currently supported zoom mechanisms, + /// so it is recommended that this setting is always enabled. However, + /// on-screen zoom controls are deprecated in Android so it's recommended to + /// disable [setDisplayZoomControls]. + Future setBuiltInZoomControls(bool enabled) { + return api.setBuiltInZoomControlsFromInstance(this, enabled); + } +} + +/// Exposes a channel to receive calls from javaScript. +/// +/// See [WebView.addJavaScriptChannel]. +abstract class JavaScriptChannel { + /// Constructs a [JavaScriptChannel]. + JavaScriptChannel(this.channelName); + + /// Pigeon Host Api implementation for [JavaScriptChannel]. + @visibleForTesting + static JavaScriptChannelHostApiImpl api = JavaScriptChannelHostApiImpl(); + + /// Used to identify this object to receive messages from javaScript. + final String channelName; + + /// Callback method when javaScript calls `postMessage` on the object instance passed. + void postMessage(String message) {} +} + +/// Receive various notifications and requests for [WebView]. +abstract class WebViewClient { + /// Constructs a [WebViewClient]. + WebViewClient({this.shouldOverrideUrlLoading = true}); + + /// User authentication failed on server. + static const int errorAuthentication = 0xfffffffc; + + /// Malformed URL. + static const int errorBadUrl = 0xfffffff4; + + /// Failed to connect to the server. + static const int errorConnect = 0xfffffffa; + + /// Failed to perform SSL handshake. + static const int errorFailedSslHandshake = 0xfffffff5; + + /// Generic file error. + static const int errorFile = 0xfffffff3; + + /// File not found. + static const int errorFileNotFound = 0xfffffff2; + + /// Server or proxy hostname lookup failed. + static const int errorHostLookup = 0xfffffffe; + + /// Failed to read or write to the server. + static const int errorIO = 0xfffffff9; + + /// User authentication failed on proxy. + static const int errorProxyAuthentication = 0xfffffffb; + + /// Too many redirects. + static const int errorRedirectLoop = 0xfffffff7; + + /// Connection timed out. + static const int errorTimeout = 0xfffffff8; + + /// Too many requests during this load. + static const int errorTooManyRequests = 0xfffffff1; + + /// Generic error. + static const int errorUnknown = 0xffffffff; + + /// Resource load was canceled by Safe Browsing. + static const int errorUnsafeResource = 0xfffffff0; + + /// Unsupported authentication scheme (not basic or digest). + static const int errorUnsupportedAuthScheme = 0xfffffffd; + + /// Unsupported URI scheme. + static const int errorUnsupportedScheme = 0xfffffff6; + + /// Pigeon Host Api implementation for [WebViewClient]. + @visibleForTesting + static WebViewClientHostApiImpl api = WebViewClientHostApiImpl(); + + /// Whether loading a url should be overridden. + /// + /// In Java, `shouldOverrideUrlLoading()` and `shouldOverrideRequestLoading()` + /// callbacks must synchronously return a boolean. This sets the default + /// return value. + /// + /// Setting [shouldOverrideUrlLoading] to true causes the current [WebView] to + /// abort loading the URL, while returning false causes the [WebView] to + /// continue loading the URL as usual. [requestLoading] or [urlLoading] will + /// still be called either way. + /// + /// Defaults to true. + final bool shouldOverrideUrlLoading; + + /// Notify the host application that a page has started loading. + /// + /// This method is called once for each main frame load so a page with iframes + /// or framesets will call onPageStarted one time for the main frame. This + /// also means that [onPageStarted] will not be called when the contents of an + /// embedded frame changes, i.e. clicking a link whose target is an iframe, it + /// will also not be called for fragment navigations (navigations to + /// #fragment_id). + void onPageStarted(WebView webView, String url) {} + + // TODO(bparrishMines): Update documentation when WebView.postVisualStateCallback is added. + /// Notify the host application that a page has finished loading. + /// + /// This method is called only for main frame. Receiving an [onPageFinished] + /// callback does not guarantee that the next frame drawn by WebView will + /// reflect the state of the DOM at this point. + void onPageFinished(WebView webView, String url) {} + + /// Report web resource loading error to the host application. + /// + /// These errors usually indicate inability to connect to the server. Note + /// that unlike the deprecated version of the callback, the new version will + /// be called for any resource (iframe, image, etc.), not just for the main + /// page. Thus, it is recommended to perform minimum required work in this + /// callback. + void onReceivedRequestError( + WebView webView, + WebResourceRequest request, + WebResourceError error, + ) {} + + /// Report an error to the host application. + /// + /// These errors are unrecoverable (i.e. the main resource is unavailable). + /// The errorCode parameter corresponds to one of the error* constants. + @Deprecated('Only called on Android version < 23.') + void onReceivedError( + WebView webView, + int errorCode, + String description, + String failingUrl, + ) {} + + // TODO(bparrishMines): Update documentation once synchronous url handling is supported. + /// When a URL is about to be loaded in the current [WebView]. + /// + /// If a [WebViewClient] is not provided, by default [WebView] will ask + /// Activity Manager to choose the proper handler for the URL. If a + /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true + /// causes the current [WebView] to abort loading the URL, while returning + /// false causes the [WebView] to continue loading the URL as usual. + void requestLoading(WebView webView, WebResourceRequest request) {} + + // TODO(bparrishMines): Update documentation once synchronous url handling is supported. + /// When a URL is about to be loaded in the current [WebView]. + /// + /// If a [WebViewClient] is not provided, by default [WebView] will ask + /// Activity Manager to choose the proper handler for the URL. If a + /// [WebViewClient] is provided, setting [shouldOverrideUrlLoading] to true + /// causes the current [WebView] to abort loading the URL, while returning + /// false causes the [WebView] to continue loading the URL as usual. + void urlLoading(WebView webView, String url) {} +} + +/// The interface to be used when content can not be handled by the rendering engine for [WebView], and should be downloaded instead. +abstract class DownloadListener { + /// Pigeon Host Api implementation for [DownloadListener]. + @visibleForTesting + static DownloadListenerHostApiImpl api = DownloadListenerHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + void onDownloadStart( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ); +} + +/// Handles JavaScript dialogs, favicons, titles, and the progress for [WebView]. +abstract class WebChromeClient { + /// Pigeon Host Api implementation for [WebChromeClient]. + @visibleForTesting + static WebChromeClientHostApiImpl api = WebChromeClientHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + void onProgressChanged(WebView webView, int progress); +} + +/// Encompasses parameters to the [WebViewClient.requestLoading] method. +class WebResourceRequest { + /// Constructs a [WebResourceRequest]. + WebResourceRequest({ + required this.url, + required this.isForMainFrame, + required this.isRedirect, + required this.hasGesture, + required this.method, + required this.requestHeaders, + }); + + /// Gets the URL for which the resource request was made. + final String url; + + /// Gets whether the request was made in order to fetch the main frame's document. + final isForMainFrame; + + /// Gets whether the request was a result of a server-side redirect. + /// + /// Only supported on Android version >= 24. + final bool? isRedirect; + + /// Gets whether a gesture (such as a click) was associated with the request. + final bool hasGesture; + + /// Gets the method associated with the request, for example "GET". + final String method; + + /// Gets the headers associated with the request. + final Map requestHeaders; +} + +/// Encapsulates information about errors occurred during loading of web resources. +/// +/// See [WebViewClient.onReceivedRequestError]. +class WebResourceError { + /// Constructs a [WebResourceError]. + WebResourceError({ + required this.errorCode, + required this.description, + }); + + /// The integer code of the error (e.g. [WebViewClient.errorAuthentication]. + final int errorCode; + + /// Describes the error. + final String description; +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart new file mode 100644 index 000000000000..81ec7c7bf80e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.pigeon.dart @@ -0,0 +1,1601 @@ +// 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. + +// Autogenerated from Pigeon (v1.0.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; + +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; + +class WebResourceRequestData { + String? url; + bool? isForMainFrame; + bool? isRedirect; + bool? hasGesture; + String? method; + Map? requestHeaders; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['url'] = url; + pigeonMap['isForMainFrame'] = isForMainFrame; + pigeonMap['isRedirect'] = isRedirect; + pigeonMap['hasGesture'] = hasGesture; + pigeonMap['method'] = method; + pigeonMap['requestHeaders'] = requestHeaders; + return pigeonMap; + } + + static WebResourceRequestData decode(Object message) { + final Map pigeonMap = message as Map; + return WebResourceRequestData() + ..url = pigeonMap['url'] as String? + ..isForMainFrame = pigeonMap['isForMainFrame'] as bool? + ..isRedirect = pigeonMap['isRedirect'] as bool? + ..hasGesture = pigeonMap['hasGesture'] as bool? + ..method = pigeonMap['method'] as String? + ..requestHeaders = (pigeonMap['requestHeaders'] as Map?) + ?.cast(); + } +} + +class WebResourceErrorData { + int? errorCode; + String? description; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['errorCode'] = errorCode; + pigeonMap['description'] = description; + return pigeonMap; + } + + static WebResourceErrorData decode(Object message) { + final Map pigeonMap = message as Map; + return WebResourceErrorData() + ..errorCode = pigeonMap['errorCode'] as int? + ..description = pigeonMap['description'] as String?; + } +} + +class _WebViewHostApiCodec extends StandardMessageCodec { + const _WebViewHostApiCodec(); +} + +class WebViewHostApi { + /// Constructor for [WebViewHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebViewHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebViewHostApiCodec(); + + Future create(int arg_instanceId, bool arg_useHybridComposition) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_useHybridComposition]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future loadUrl(int arg_instanceId, String arg_url, + Map arg_headers) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.loadUrl', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_url, arg_headers]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future getUrl(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getUrl', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future canGoBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoBack', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as bool?)!; + } + } + + Future canGoForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoForward', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as bool?)!; + } + } + + Future goBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goBack', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future goForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goForward', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future reload(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.reload', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future clearCache(int arg_instanceId, bool arg_includeDiskFiles) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.clearCache', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_includeDiskFiles]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future evaluateJavascript( + int arg_instanceId, String arg_javascriptString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.evaluateJavascript', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_javascriptString]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future getTitle(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getTitle', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future scrollTo(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollTo', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_x, arg_y]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future scrollBy(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollBy', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_x, arg_y]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future getScrollX(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollX', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as int?)!; + } + } + + Future getScrollY(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollY', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as int?)!; + } + } + + Future setWebContentsDebuggingEnabled(bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setWebViewClient( + int arg_instanceId, int arg_webViewClientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebViewClient', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_webViewClientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future addJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future removeJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDownloadListener( + int arg_instanceId, int arg_listenerInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setDownloadListener', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_listenerInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setWebChromeClient( + int arg_instanceId, int arg_clientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebChromeClient', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_clientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebSettingsHostApiCodec extends StandardMessageCodec { + const _WebSettingsHostApiCodec(); +} + +class WebSettingsHostApi { + /// Constructor for [WebSettingsHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebSettingsHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebSettingsHostApiCodec(); + + Future create(int arg_instanceId, int arg_webViewInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_webViewInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDomStorageEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setJavaScriptCanOpenWindowsAutomatically( + int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setSupportMultipleWindows( + int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_support]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setJavaScriptEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_flag]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setUserAgentString( + int arg_instanceId, String arg_userAgentString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_userAgentString]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setMediaPlaybackRequiresUserGesture( + int arg_instanceId, bool arg_require) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_require]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setSupportZoom(int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_support]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setLoadWithOverviewMode( + int arg_instanceId, bool arg_overview) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_overview]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setUseWideViewPort(int arg_instanceId, bool arg_use) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_use]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setDisplayZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future setBuiltInZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_enabled]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _JavaScriptChannelHostApiCodec extends StandardMessageCodec { + const _JavaScriptChannelHostApiCodec(); +} + +class JavaScriptChannelHostApi { + /// Constructor for [JavaScriptChannelHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + JavaScriptChannelHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _JavaScriptChannelHostApiCodec(); + + Future create(int arg_instanceId, String arg_channelName) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_channelName]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _JavaScriptChannelFlutterApiCodec extends StandardMessageCodec { + const _JavaScriptChannelFlutterApiCodec(); +} + +abstract class JavaScriptChannelFlutterApi { + static const MessageCodec codec = + _JavaScriptChannelFlutterApiCodec(); + + void postMessage(int instanceId, String message); + static void setup(JavaScriptChannelFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null, expected non-null int.'); + final String? arg_message = args[1] as String?; + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage was null, expected non-null String.'); + api.postMessage(arg_instanceId!, arg_message!); + return; + }); + } + } + } +} + +class _WebViewClientHostApiCodec extends StandardMessageCodec { + const _WebViewClientHostApiCodec(); +} + +class WebViewClientHostApi { + /// Constructor for [WebViewClientHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebViewClientHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebViewClientHostApiCodec(); + + Future create( + int arg_instanceId, bool arg_shouldOverrideUrlLoading) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_shouldOverrideUrlLoading]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebViewClientFlutterApiCodec extends StandardMessageCodec { + const _WebViewClientFlutterApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is WebResourceErrorData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else if (value is WebResourceRequestData) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); + } else if (value is WebResourceRequestData) { + buffer.putUint8(130); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return WebResourceErrorData.decode(readValue(buffer)!); + + case 129: + return WebResourceRequestData.decode(readValue(buffer)!); + + case 130: + return WebResourceRequestData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class WebViewClientFlutterApi { + static const MessageCodec codec = _WebViewClientFlutterApiCodec(); + + void onPageStarted(int instanceId, int webViewInstanceId, String url); + void onPageFinished(int instanceId, int webViewInstanceId, String url); + void onReceivedRequestError(int instanceId, int webViewInstanceId, + WebResourceRequestData request, WebResourceErrorData error); + void onReceivedError(int instanceId, int webViewInstanceId, int errorCode, + String description, String failingUrl); + void requestLoading( + int instanceId, int webViewInstanceId, WebResourceRequestData request); + void urlLoading(int instanceId, int webViewInstanceId, String url); + static void setup(WebViewClientFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted was null, expected non-null String.'); + api.onPageStarted(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished was null, expected non-null String.'); + api.onPageFinished(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null int.'); + final WebResourceRequestData? arg_request = + args[2] as WebResourceRequestData?; + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null WebResourceRequestData.'); + final WebResourceErrorData? arg_error = + args[3] as WebResourceErrorData?; + assert(arg_error != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null WebResourceErrorData.'); + api.onReceivedRequestError(arg_instanceId!, arg_webViewInstanceId!, + arg_request!, arg_error!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final int? arg_errorCode = args[2] as int?; + assert(arg_errorCode != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null int.'); + final String? arg_description = args[3] as String?; + assert(arg_description != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null String.'); + final String? arg_failingUrl = args[4] as String?; + assert(arg_failingUrl != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError was null, expected non-null String.'); + api.onReceivedError(arg_instanceId!, arg_webViewInstanceId!, + arg_errorCode!, arg_description!, arg_failingUrl!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null int.'); + final WebResourceRequestData? arg_request = + args[2] as WebResourceRequestData?; + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading was null, expected non-null WebResourceRequestData.'); + api.requestLoading( + arg_instanceId!, arg_webViewInstanceId!, arg_request!); + return; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null int.'); + final String? arg_url = args[2] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading was null, expected non-null String.'); + api.urlLoading(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + } +} + +class _DownloadListenerHostApiCodec extends StandardMessageCodec { + const _DownloadListenerHostApiCodec(); +} + +class DownloadListenerHostApi { + /// Constructor for [DownloadListenerHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + DownloadListenerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _DownloadListenerHostApiCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _DownloadListenerFlutterApiCodec extends StandardMessageCodec { + const _DownloadListenerFlutterApiCodec(); +} + +abstract class DownloadListenerFlutterApi { + static const MessageCodec codec = _DownloadListenerFlutterApiCodec(); + + void onDownloadStart(int instanceId, String url, String userAgent, + String contentDisposition, String mimetype, int contentLength); + static void setup(DownloadListenerFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null int.'); + final String? arg_url = args[1] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_userAgent = args[2] as String?; + assert(arg_userAgent != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_contentDisposition = args[3] as String?; + assert(arg_contentDisposition != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final String? arg_mimetype = args[4] as String?; + assert(arg_mimetype != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null String.'); + final int? arg_contentLength = args[5] as int?; + assert(arg_contentLength != null, + 'Argument for dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null int.'); + api.onDownloadStart(arg_instanceId!, arg_url!, arg_userAgent!, + arg_contentDisposition!, arg_mimetype!, arg_contentLength!); + return; + }); + } + } + } +} + +class _WebChromeClientHostApiCodec extends StandardMessageCodec { + const _WebChromeClientHostApiCodec(); +} + +class WebChromeClientHostApi { + /// Constructor for [WebChromeClientHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + WebChromeClientHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _WebChromeClientHostApiCodec(); + + Future create( + int arg_instanceId, int arg_webViewClientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_instanceId, arg_webViewClientInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } + + Future dispose(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WebChromeClientFlutterApiCodec extends StandardMessageCodec { + const _WebChromeClientFlutterApiCodec(); +} + +abstract class WebChromeClientFlutterApi { + static const MessageCodec codec = _WebChromeClientFlutterApiCodec(); + + void onProgressChanged(int instanceId, int webViewInstanceId, int progress); + static void setup(WebChromeClientFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged', + codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + final int? arg_progress = args[2] as int?; + assert(arg_progress != null, + 'Argument for dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + api.onProgressChanged( + arg_instanceId!, arg_webViewInstanceId!, arg_progress!); + return; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart new file mode 100644 index 000000000000..f909e49bd802 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -0,0 +1,622 @@ +// 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:flutter/services.dart'; + +import 'android_webview.dart'; +import 'android_webview.pigeon.dart'; +import 'instance_manager.dart'; + +/// Host api implementation for [WebView]. +class WebViewHostApiImpl extends WebViewHostApi { + /// Constructs a [WebViewHostApiImpl]. + WebViewHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebView instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.useHybridComposition); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebView instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future loadUrlFromInstance( + WebView instance, + String url, + Map headers, + ) { + return loadUrl(instanceManager.getInstanceId(instance)!, url, headers); + } + + /// Helper method to convert instances ids to objects. + Future getUrlFromInstance(WebView instance) { + return getUrl(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoBackFromInstance(WebView instance) { + return canGoBack(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoForwardFromInstance(WebView instance) { + return canGoForward(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goBackFromInstance(WebView instance) { + return goBack(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goForwardFromInstance(WebView instance) { + return goForward(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future reloadFromInstance(WebView instance) { + return reload(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future clearCacheFromInstance(WebView instance, bool includeDiskFiles) { + return clearCache( + instanceManager.getInstanceId(instance)!, + includeDiskFiles, + ); + } + + /// Helper method to convert instances ids to objects. + Future evaluateJavascriptFromInstance( + WebView instance, + String javascriptString, + ) { + return evaluateJavascript( + instanceManager.getInstanceId(instance)!, javascriptString); + } + + /// Helper method to convert instances ids to objects. + Future getTitleFromInstance(WebView instance) { + return getTitle(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future scrollToFromInstance(WebView instance, int x, int y) { + return scrollTo(instanceManager.getInstanceId(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future scrollByFromInstance(WebView instance, int x, int y) { + return scrollBy(instanceManager.getInstanceId(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future getScrollXFromInstance(WebView instance) { + return getScrollX(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future getScrollYFromInstance(WebView instance) { + return getScrollY(instanceManager.getInstanceId(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future setWebViewClientFromInstance( + WebView instance, + WebViewClient webViewClient, + ) { + return setWebViewClient( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(webViewClient)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future addJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return addJavaScriptChannel( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future removeJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return removeJavaScriptChannel( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future setDownloadListenerFromInstance( + WebView instance, + DownloadListener listener, + ) { + return setDownloadListener( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(listener)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future setWebChromeClientFromInstance( + WebView instance, + WebChromeClient client, + ) { + return setWebChromeClient( + instanceManager.getInstanceId(instance)!, + instanceManager.getInstanceId(client)!, + ); + } +} + +/// Host api implementation for [WebSettings]. +class WebSettingsHostApiImpl extends WebSettingsHostApi { + /// Constructs a [WebSettingsHostApiImpl]. + WebSettingsHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebSettings instance, WebView webView) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create( + instanceId, + instanceManager.getInstanceId(webView)!, + ); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebSettings instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future setDomStorageEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setDomStorageEnabled(instanceManager.getInstanceId(instance)!, flag); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptCanOpenWindowsAutomatically( + instanceManager.getInstanceId(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportMultipleWindowsFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportMultipleWindows( + instanceManager.getInstanceId(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptCanOpenWindowsAutomatically( + instanceManager.getInstanceId(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUserAgentStringFromInstance( + WebSettings instance, + String userAgentString, + ) { + return setUserAgentString( + instanceManager.getInstanceId(instance)!, + userAgentString, + ); + } + + /// Helper method to convert instances ids to objects. + Future setMediaPlaybackRequiresUserGestureFromInstance( + WebSettings instance, + bool require, + ) { + return setMediaPlaybackRequiresUserGesture( + instanceManager.getInstanceId(instance)!, + require, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportZoomFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportZoom(instanceManager.getInstanceId(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setLoadWithOverviewModeFromInstance( + WebSettings instance, + bool overview, + ) { + return setLoadWithOverviewMode( + instanceManager.getInstanceId(instance)!, + overview, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUseWideViewPortFromInstance( + WebSettings instance, + bool use, + ) { + return setUseWideViewPort(instanceManager.getInstanceId(instance)!, use); + } + + /// Helper method to convert instances ids to objects. + Future setDisplayZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setDisplayZoomControls( + instanceManager.getInstanceId(instance)!, + enabled, + ); + } + + /// Helper method to convert instances ids to objects. + Future setBuiltInZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setBuiltInZoomControls( + instanceManager.getInstanceId(instance)!, + enabled, + ); + } +} + +/// Host api implementation for [JavaScriptChannel]. +class JavaScriptChannelHostApiImpl extends JavaScriptChannelHostApi { + /// Constructs a [JavaScriptChannelHostApiImpl]. + JavaScriptChannelHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(JavaScriptChannel instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.channelName); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(JavaScriptChannel instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [JavaScriptChannel]. +class JavaScriptChannelFlutterApiImpl extends JavaScriptChannelFlutterApi { + /// Constructs a [JavaScriptChannelFlutterApiImpl]. + JavaScriptChannelHostApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void postMessage(int instanceId, String message) { + final JavaScriptChannel instance = + instanceManager.getInstance(instanceId) as JavaScriptChannel; + instance.postMessage(message); + } +} + +/// Host api implementation for [WebViewClient]. +class WebViewClientHostApiImpl extends WebViewClientHostApi { + /// Constructs a [WebViewClientHostApiImpl]. + WebViewClientHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebViewClient instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instance.shouldOverrideUrlLoading); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebViewClient instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [WebViewClient]. +class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { + /// Constructs a [WebViewClientFlutterApiImpl]. + WebViewClientFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onPageFinished(int instanceId, int webViewInstanceId, String url) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onPageFinished( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } + + @override + void onPageStarted(int instanceId, int webViewInstanceId, String url) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onPageStarted( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } + + @override + void onReceivedError( + int instanceId, + int webViewInstanceId, + int errorCode, + String description, + String failingUrl, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + // ignore: deprecated_member_use_from_same_package + instance.onReceivedError( + instanceManager.getInstance(webViewInstanceId) as WebView, + errorCode, + description, + failingUrl, + ); + } + + @override + void onReceivedRequestError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceErrorData error, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.onReceivedRequestError( + instanceManager.getInstance(webViewInstanceId) as WebView, + WebResourceRequest( + url: request.url!, + isForMainFrame: request.isForMainFrame!, + isRedirect: request.isRedirect, + hasGesture: request.hasGesture!, + method: request.method!, + requestHeaders: request.requestHeaders!.cast(), + ), + WebResourceError( + errorCode: error.errorCode!, + description: error.description!, + ), + ); + } + + @override + void requestLoading( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.requestLoading( + instanceManager.getInstance(webViewInstanceId) as WebView, + WebResourceRequest( + url: request.url!, + isForMainFrame: request.isForMainFrame!, + isRedirect: request.isRedirect, + hasGesture: request.hasGesture!, + method: request.method!, + requestHeaders: request.requestHeaders!.cast(), + ), + ); + } + + @override + void urlLoading( + int instanceId, + int webViewInstanceId, + String url, + ) { + final WebViewClient instance = + instanceManager.getInstance(instanceId) as WebViewClient; + instance.urlLoading( + instanceManager.getInstance(webViewInstanceId) as WebView, + url, + ); + } +} + +/// Host api implementation for [DownloadListener]. +class DownloadListenerHostApiImpl extends DownloadListenerHostApi { + /// Constructs a [DownloadListenerHostApiImpl]. + DownloadListenerHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(DownloadListener instance) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(DownloadListener instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [DownloadListener]. +class DownloadListenerFlutterApiImpl extends DownloadListenerFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + DownloadListenerFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onDownloadStart( + int instanceId, + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + final DownloadListener instance = + instanceManager.getInstance(instanceId) as DownloadListener; + instance.onDownloadStart( + url, + userAgent, + contentDisposition, + mimetype, + contentLength, + ); + } +} + +/// Host api implementation for [DownloadListener]. +class WebChromeClientHostApiImpl extends WebChromeClientHostApi { + /// Constructs a [WebChromeClientHostApiImpl]. + WebChromeClientHostApiImpl({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : super(binaryMessenger: binaryMessenger) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance( + WebChromeClient instance, + WebViewClient webViewClient, + ) async { + final int? instanceId = instanceManager.tryAddInstance(instance); + if (instanceId != null) { + return create(instanceId, instanceManager.getInstanceId(webViewClient)!); + } + } + + /// Helper method to convert instances ids to objects. + Future disposeFromInstance(WebChromeClient instance) async { + final int? instanceId = instanceManager.removeInstance(instance); + if (instanceId != null) { + return dispose(instanceId); + } + } +} + +/// Flutter api implementation for [DownloadListener]. +class WebChromeClientFlutterApiImpl extends WebChromeClientFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + WebChromeClientFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with java objects. + late final InstanceManager instanceManager; + + @override + void onProgressChanged(int instanceId, int webViewInstanceId, int progress) { + final WebChromeClient instance = + instanceManager.getInstance(instanceId) as WebChromeClient; + instance.onProgressChanged( + instanceManager.getInstance(webViewInstanceId) as WebView, + progress, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart b/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart new file mode 100644 index 000000000000..94d8bc3253eb --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/lib/src/instance_manager.dart @@ -0,0 +1,52 @@ +// 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. + +/// Maintains instances stored to communicate with java objects. +class InstanceManager { + Map _instanceIdsToInstances = {}; + Map _instancesToInstanceIds = {}; + + int _nextInstanceId = 0; + + /// Global instance of [InstanceManager]. + static final InstanceManager instance = InstanceManager(); + + /// Attempt to add a new instance. + /// + /// Returns new if [instance] has already been added. Otherwise, it is added + /// with a new instance id. + int? tryAddInstance(Object instance) { + if (_instancesToInstanceIds.containsKey(instance)) { + return null; + } + + final int instanceId = _nextInstanceId++; + _instancesToInstanceIds[instance] = instanceId; + _instanceIdsToInstances[instanceId] = instance; + return instanceId; + } + + /// Remove the instance from the manager. + /// + /// Returns null if the instance is removed. Otherwise, return the instanceId + /// of the removed instance. + int? removeInstance(Object instance) { + final int? instanceId = _instancesToInstanceIds[instance]; + if (instanceId != null) { + _instancesToInstanceIds.remove(instance); + _instanceIdsToInstances.remove(instanceId); + } + return instanceId; + } + + /// Retrieve the Object paired with instanceId. + Object? getInstance(int instanceId) { + return _instanceIdsToInstances[instanceId]; + } + + /// Retrieve the instanceId paired with instance. + int? getInstanceId(Object instance) { + return _instancesToInstanceIds[instance]; + } +} diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart new file mode 100644 index 000000000000..1877c1b91feb --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -0,0 +1,181 @@ +// 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:pigeon/pigeon.dart'; + +class WebResourceRequestData { + String? url; + bool? isForMainFrame; + bool? isRedirect; + bool? hasGesture; + String? method; + Map? requestHeaders; +} + +class WebResourceErrorData { + int? errorCode; + String? description; +} + +@HostApi(dartHostTestHandler: 'TestWebViewHostApi') +abstract class WebViewHostApi { + void create(int instanceId, bool useHybridComposition); + + void dispose(int instanceId); + + void loadUrl( + int instanceId, + String url, + Map headers, + ); + + String getUrl(int instanceId); + + bool canGoBack(int instanceId); + + bool canGoForward(int instanceId); + + void goBack(int instanceId); + + void goForward(int instanceId); + + void reload(int instanceId); + + void clearCache(int instanceId, bool includeDiskFiles); + + @async + String evaluateJavascript( + int instanceId, + String javascriptString, + ); + + String getTitle(int instanceId); + + void scrollTo(int instanceId, int x, int y); + + void scrollBy(int instanceId, int x, int y); + + int getScrollX(int instanceId); + + int getScrollY(int instanceId); + + void setWebContentsDebuggingEnabled(bool enabled); + + void setWebViewClient(int instanceId, int webViewClientInstanceId); + + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + + void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + + void setDownloadListener(int instanceId, int listenerInstanceId); + + void setWebChromeClient(int instanceId, int clientInstanceId); +} + +@HostApi(dartHostTestHandler: 'TestWebSettingsHostApi') +abstract class WebSettingsHostApi { + void create(int instanceId, int webViewInstanceId); + + void dispose(int instanceId); + + void setDomStorageEnabled(int instanceId, bool flag); + + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag); + + void setSupportMultipleWindows(int instanceId, bool support); + + void setJavaScriptEnabled(int instanceId, bool flag); + + void setUserAgentString(int instanceId, String userAgentString); + + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require); + + void setSupportZoom(int instanceId, bool support); + + void setLoadWithOverviewMode(int instanceId, bool overview); + + void setUseWideViewPort(int instanceId, bool use); + + void setDisplayZoomControls(int instanceId, bool enabled); + + void setBuiltInZoomControls(int instanceId, bool enabled); +} + +@HostApi(dartHostTestHandler: 'TestJavaScriptChannelHostApi') +abstract class JavaScriptChannelHostApi { + void create(int instanceId, String channelName); + + void dispose(int instanceId); +} + +@FlutterApi() +abstract class JavaScriptChannelFlutterApi { + void postMessage(int instanceId, String message); +} + +@HostApi(dartHostTestHandler: 'TestWebViewClientHostApi') +abstract class WebViewClientHostApi { + void create(int instanceId, bool shouldOverrideUrlLoading); + + void dispose(int instanceId); +} + +@FlutterApi() +abstract class WebViewClientFlutterApi { + void onPageStarted(int instanceId, int webViewInstanceId, String url); + + void onPageFinished(int instanceId, int webViewInstanceId, String url); + + void onReceivedRequestError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceErrorData error, + ); + + void onReceivedError( + int instanceId, + int webViewInstanceId, + int errorCode, + String description, + String failingUrl, + ); + + void requestLoading( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + ); + + void urlLoading(int instanceId, int webViewInstanceId, String url); +} + +@HostApi(dartHostTestHandler: 'TestDownloadListenerHostApi') +abstract class DownloadListenerHostApi { + void create(int instanceId); + void dispose(int instanceId); +} + +@FlutterApi() +abstract class DownloadListenerFlutterApi { + void onDownloadStart( + int instanceId, + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ); +} + +@HostApi(dartHostTestHandler: 'TestWebChromeClientHostApi') +abstract class WebChromeClientHostApi { + void create(int instanceId, int webViewClientInstanceId); + void dispose(int instanceId); +} + +@FlutterApi() +abstract class WebChromeClientFlutterApi { + void onProgressChanged(int instanceId, int webViewInstanceId, int progress); +} diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 36f186087c08..04511e670d4c 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -27,5 +27,6 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter + pigeon: 1.0.7 pedantic: ^1.10.0 diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart new file mode 100644 index 000000000000..70aa53ca2610 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview.pigeon.dart @@ -0,0 +1,1000 @@ +// 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. + +// Autogenerated from Pigeon (v1.0.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, avoid_relative_lib_imports +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../lib/src/android_webview.pigeon.dart'; + +class _TestWebViewHostApiCodec extends StandardMessageCodec { + const _TestWebViewHostApiCodec(); +} + +abstract class TestWebViewHostApi { + static const MessageCodec codec = _TestWebViewHostApiCodec(); + + void create(int instanceId, bool useHybridComposition); + void dispose(int instanceId); + void loadUrl(int instanceId, String url, Map headers); + String getUrl(int instanceId); + bool canGoBack(int instanceId); + bool canGoForward(int instanceId); + void goBack(int instanceId); + void goForward(int instanceId); + void reload(int instanceId); + void clearCache(int instanceId, bool includeDiskFiles); + Future evaluateJavascript(int instanceId, String javascriptString); + String getTitle(int instanceId); + void scrollTo(int instanceId, int x, int y); + void scrollBy(int instanceId, int x, int y); + int getScrollX(int instanceId); + int getScrollY(int instanceId); + void setWebContentsDebuggingEnabled(bool enabled); + void setWebViewClient(int instanceId, int webViewClientInstanceId); + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + void removeJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId); + void setDownloadListener(int instanceId, int listenerInstanceId); + void setWebChromeClient(int instanceId, int clientInstanceId); + static void setup(TestWebViewHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null int.'); + final bool? arg_useHybridComposition = args[1] as bool?; + assert(arg_useHybridComposition != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.create was null, expected non-null bool.'); + api.create(arg_instanceId!, arg_useHybridComposition!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.loadUrl', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null int.'); + final String? arg_url = args[1] as String?; + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null String.'); + final Map? arg_headers = + args[2] as Map?; + assert(arg_headers != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.loadUrl was null, expected non-null Map.'); + api.loadUrl(arg_instanceId!, arg_url!, arg_headers!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getUrl', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getUrl was null, expected non-null int.'); + final String output = api.getUrl(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoBack', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoBack was null, expected non-null int.'); + final bool output = api.canGoBack(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.canGoForward', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.canGoForward was null, expected non-null int.'); + final bool output = api.canGoForward(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goBack', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goBack was null, expected non-null int.'); + api.goBack(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.goForward', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.goForward was null, expected non-null int.'); + api.goForward(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.reload', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.reload was null, expected non-null int.'); + api.reload(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.clearCache', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null int.'); + final bool? arg_includeDiskFiles = args[1] as bool?; + assert(arg_includeDiskFiles != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.clearCache was null, expected non-null bool.'); + api.clearCache(arg_instanceId!, arg_includeDiskFiles!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.evaluateJavascript', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null int.'); + final String? arg_javascriptString = args[1] as String?; + assert(arg_javascriptString != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.evaluateJavascript was null, expected non-null String.'); + final String output = await api.evaluateJavascript( + arg_instanceId!, arg_javascriptString!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getTitle', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getTitle was null, expected non-null int.'); + final String output = api.getTitle(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollTo', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + final int? arg_x = args[1] as int?; + assert(arg_x != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + final int? arg_y = args[2] as int?; + assert(arg_y != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollTo was null, expected non-null int.'); + api.scrollTo(arg_instanceId!, arg_x!, arg_y!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.scrollBy', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + final int? arg_x = args[1] as int?; + assert(arg_x != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + final int? arg_y = args[2] as int?; + assert(arg_y != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.scrollBy was null, expected non-null int.'); + api.scrollBy(arg_instanceId!, arg_x!, arg_y!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollX', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollX was null, expected non-null int.'); + final int output = api.getScrollX(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.getScrollY', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.getScrollY was null, expected non-null int.'); + final int output = api.getScrollY(arg_instanceId!); + return {'result': output}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null.'); + final List args = (message as List?)!; + final bool? arg_enabled = args[0] as bool?; + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled was null, expected non-null bool.'); + api.setWebContentsDebuggingEnabled(arg_enabled!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebViewClient', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + final int? arg_webViewClientInstanceId = args[1] as int?; + assert(arg_webViewClientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebViewClient was null, expected non-null int.'); + api.setWebViewClient(arg_instanceId!, arg_webViewClientInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + final int? arg_javaScriptChannelInstanceId = args[1] as int?; + assert(arg_javaScriptChannelInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel was null, expected non-null int.'); + api.addJavaScriptChannel( + arg_instanceId!, arg_javaScriptChannelInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + final int? arg_javaScriptChannelInstanceId = args[1] as int?; + assert(arg_javaScriptChannelInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel was null, expected non-null int.'); + api.removeJavaScriptChannel( + arg_instanceId!, arg_javaScriptChannelInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setDownloadListener', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + final int? arg_listenerInstanceId = args[1] as int?; + assert(arg_listenerInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setDownloadListener was null, expected non-null int.'); + api.setDownloadListener(arg_instanceId!, arg_listenerInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.setWebChromeClient', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null, expected non-null int.'); + final int? arg_clientInstanceId = args[1] as int?; + assert(arg_clientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.setWebChromeClient was null, expected non-null int.'); + api.setWebChromeClient(arg_instanceId!, arg_clientInstanceId!); + return {}; + }); + } + } + } +} + +class _TestWebSettingsHostApiCodec extends StandardMessageCodec { + const _TestWebSettingsHostApiCodec(); +} + +abstract class TestWebSettingsHostApi { + static const MessageCodec codec = _TestWebSettingsHostApiCodec(); + + void create(int instanceId, int webViewInstanceId); + void dispose(int instanceId); + void setDomStorageEnabled(int instanceId, bool flag); + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag); + void setSupportMultipleWindows(int instanceId, bool support); + void setJavaScriptEnabled(int instanceId, bool flag); + void setUserAgentString(int instanceId, String userAgentString); + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require); + void setSupportZoom(int instanceId, bool support); + void setLoadWithOverviewMode(int instanceId, bool overview); + void setUseWideViewPort(int instanceId, bool use); + void setDisplayZoomControls(int instanceId, bool enabled); + void setBuiltInZoomControls(int instanceId, bool enabled); + static void setup(TestWebSettingsHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + final int? arg_webViewInstanceId = args[1] as int?; + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!, arg_webViewInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled was null, expected non-null bool.'); + api.setDomStorageEnabled(arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically was null, expected non-null bool.'); + api.setJavaScriptCanOpenWindowsAutomatically( + arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null int.'); + final bool? arg_support = args[1] as bool?; + assert(arg_support != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows was null, expected non-null bool.'); + api.setSupportMultipleWindows(arg_instanceId!, arg_support!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null int.'); + final bool? arg_flag = args[1] as bool?; + assert(arg_flag != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled was null, expected non-null bool.'); + api.setJavaScriptEnabled(arg_instanceId!, arg_flag!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null int.'); + final String? arg_userAgentString = args[1] as String?; + assert(arg_userAgentString != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString was null, expected non-null String.'); + api.setUserAgentString(arg_instanceId!, arg_userAgentString!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null int.'); + final bool? arg_require = args[1] as bool?; + assert(arg_require != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture was null, expected non-null bool.'); + api.setMediaPlaybackRequiresUserGesture( + arg_instanceId!, arg_require!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null int.'); + final bool? arg_support = args[1] as bool?; + assert(arg_support != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom was null, expected non-null bool.'); + api.setSupportZoom(arg_instanceId!, arg_support!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null int.'); + final bool? arg_overview = args[1] as bool?; + assert(arg_overview != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode was null, expected non-null bool.'); + api.setLoadWithOverviewMode(arg_instanceId!, arg_overview!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null int.'); + final bool? arg_use = args[1] as bool?; + assert(arg_use != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort was null, expected non-null bool.'); + api.setUseWideViewPort(arg_instanceId!, arg_use!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null int.'); + final bool? arg_enabled = args[1] as bool?; + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls was null, expected non-null bool.'); + api.setDisplayZoomControls(arg_instanceId!, arg_enabled!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls', + codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null int.'); + final bool? arg_enabled = args[1] as bool?; + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls was null, expected non-null bool.'); + api.setBuiltInZoomControls(arg_instanceId!, arg_enabled!); + return {}; + }); + } + } + } +} + +class _TestJavaScriptChannelHostApiCodec extends StandardMessageCodec { + const _TestJavaScriptChannelHostApiCodec(); +} + +abstract class TestJavaScriptChannelHostApi { + static const MessageCodec codec = + _TestJavaScriptChannelHostApiCodec(); + + void create(int instanceId, String channelName); + void dispose(int instanceId); + static void setup(TestJavaScriptChannelHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null int.'); + final String? arg_channelName = args[1] as String?; + assert(arg_channelName != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.create was null, expected non-null String.'); + api.create(arg_instanceId!, arg_channelName!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.JavaScriptChannelHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.JavaScriptChannelHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} + +class _TestWebViewClientHostApiCodec extends StandardMessageCodec { + const _TestWebViewClientHostApiCodec(); +} + +abstract class TestWebViewClientHostApi { + static const MessageCodec codec = _TestWebViewClientHostApiCodec(); + + void create(int instanceId, bool shouldOverrideUrlLoading); + void dispose(int instanceId); + static void setup(TestWebViewClientHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null int.'); + final bool? arg_shouldOverrideUrlLoading = args[1] as bool?; + assert(arg_shouldOverrideUrlLoading != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.create was null, expected non-null bool.'); + api.create(arg_instanceId!, arg_shouldOverrideUrlLoading!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewClientHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebViewClientHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} + +class _TestDownloadListenerHostApiCodec extends StandardMessageCodec { + const _TestDownloadListenerHostApiCodec(); +} + +abstract class TestDownloadListenerHostApi { + static const MessageCodec codec = + _TestDownloadListenerHostApiCodec(); + + void create(int instanceId); + void dispose(int instanceId); + static void setup(TestDownloadListenerHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.DownloadListenerHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.DownloadListenerHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} + +class _TestWebChromeClientHostApiCodec extends StandardMessageCodec { + const _TestWebChromeClientHostApiCodec(); +} + +abstract class TestWebChromeClientHostApi { + static const MessageCodec codec = _TestWebChromeClientHostApiCodec(); + + void create(int instanceId, int webViewClientInstanceId); + void dispose(int instanceId); + static void setup(TestWebChromeClientHostApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.create', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null, expected non-null int.'); + final int? arg_webViewClientInstanceId = args[1] as int?; + assert(arg_webViewClientInstanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.create was null, expected non-null int.'); + api.create(arg_instanceId!, arg_webViewClientInstanceId!); + return {}; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebChromeClientHostApi.dispose', codec); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = args[0] as int?; + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebChromeClientHostApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return {}; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart new file mode 100644 index 000000000000..462670abdb83 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -0,0 +1,373 @@ +// 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:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_android/src/android_webview.dart'; +import 'package:webview_flutter_android/src/android_webview_api_impls.dart'; +import 'package:webview_flutter_android/src/instance_manager.dart'; + +import 'android_webview.pigeon.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('Android WebView', () { + group('$WebView', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + }); + + setUp(() { + WebView.api = WebViewHostApiImpl(instanceManager: InstanceManager()); + }); + + test('create', () { + final WebView webView = WebView(); + expect(WebView.api.instanceManager.getInstanceId(webView), isNotNull); + }); + }); + + group('$WebSettings', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebSettingsHostApi.setup(TestWebSettingsHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + WebSettings.api = WebSettingsHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final WebSettings webSettings = WebSettings(webView); + expect( + WebSettings.api.instanceManager.getInstanceId(webSettings), + isNotNull, + ); + }); + }); + + group('$JavaScriptChannel', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestJavaScriptChannelHostApi.setup(TestJavaScriptChannelHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + JavaScriptChannel.api = JavaScriptChannelHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final JavaScriptChannel channel = TestJavaScriptChannel('myChannel'); + + webView.addJavaScriptChannel(channel); + expect( + JavaScriptChannel.api.instanceManager.getInstanceId(channel), + isNotNull, + ); + + webView.removeJavaScriptChannel(channel); + expect( + JavaScriptChannel.api.instanceManager.getInstanceId(channel), + isNull, + ); + }); + }); + + group('$WebViewClient', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebViewClientHostApi.setup(TestWebViewClientHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + WebViewClient.api = WebViewClientHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final WebViewClient webViewClient1 = TestWebViewClient(); + final WebViewClient webViewClient2 = TestWebViewClient(); + + webView.setWebViewClient(webViewClient1); + expect( + WebViewClient.api.instanceManager.getInstanceId(webViewClient1), + isNotNull, + ); + + webView.setWebViewClient(webViewClient2); + expect( + WebViewClient.api.instanceManager.getInstanceId(webViewClient1), + isNull, + ); + }); + }); + + group('$DownloadListener', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestDownloadListenerHostApi.setup(TestDownloadListenerHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + DownloadListener.api = DownloadListenerHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + final DownloadListener downloadListener1 = TestDownloadListener(); + final DownloadListener downloadListener2 = TestDownloadListener(); + + webView.setDownloadListener(downloadListener1); + expect( + DownloadListener.api.instanceManager.getInstanceId(downloadListener1), + isNotNull, + ); + + webView.setDownloadListener(downloadListener2); + expect( + DownloadListener.api.instanceManager.getInstanceId(downloadListener1), + isNull, + ); + }); + }); + + group('$WebChromeClient', () { + setUpAll(() { + TestWebViewHostApi.setup(TestWebViewHostApiImpl()); + TestWebViewClientHostApi.setup(TestWebViewClientHostApiImpl()); + TestWebChromeClientHostApi.setup(TestWebChromeClientHostApiImpl()); + }); + + setUp(() { + final InstanceManager instanceManager = InstanceManager(); + WebView.api = WebViewHostApiImpl(instanceManager: instanceManager); + WebViewClient.api = WebViewClientHostApiImpl( + instanceManager: instanceManager, + ); + WebChromeClient.api = WebChromeClientHostApiImpl( + instanceManager: instanceManager, + ); + }); + + test('create', () { + final WebView webView = WebView(); + webView.setWebViewClient(TestWebViewClient()); + + final WebChromeClient webChromeClient1 = TestWebChromeClient(); + final WebChromeClient webChromeClient2 = TestWebChromeClient(); + + webView.setWebChromeClient(webChromeClient1); + expect( + WebChromeClient.api.instanceManager.getInstanceId(webChromeClient1), + isNotNull, + ); + + webView.setWebChromeClient(webChromeClient2); + expect( + WebChromeClient.api.instanceManager.getInstanceId(webChromeClient1), + isNull, + ); + }); + }); + }); +} + +class TestJavaScriptChannel extends JavaScriptChannel { + TestJavaScriptChannel(String channelName) : super(channelName); + + @override + void postMessage(String message) {} +} + +class TestWebViewClient extends WebViewClient {} + +class TestDownloadListener extends DownloadListener { + @override + void onDownloadStart( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) {} +} + +class TestWebChromeClient extends WebChromeClient { + @override + void onProgressChanged(WebView webView, int progress) {} +} + +class TestWebViewHostApiImpl extends TestWebViewHostApi { + @override + void addJavaScriptChannel(int instanceId, int javaScriptChannelInstanceId) {} + + @override + bool canGoBack(int instanceId) { + throw UnimplementedError(); + } + + @override + bool canGoForward(int instanceId) { + throw UnimplementedError(); + } + + @override + void clearCache(int instanceId, bool includeDiskFiles) {} + + @override + void create(int instanceId, bool useHybridComposition) {} + + @override + void dispose(int instanceId) {} + + @override + Future evaluateJavascript(int instanceId, String javascriptString) { + throw UnimplementedError(); + } + + @override + int getScrollX(int instanceId) { + throw UnimplementedError(); + } + + @override + int getScrollY(int instanceId) { + throw UnimplementedError(); + } + + @override + String getTitle(int instanceId) { + throw UnimplementedError(); + } + + @override + String getUrl(int instanceId) { + throw UnimplementedError(); + } + + @override + void goBack(int instanceId) {} + + @override + void goForward(int instanceId) {} + + @override + void loadUrl(int instanceId, String url, Map headers) {} + + @override + void reload(int instanceId) {} + + @override + void removeJavaScriptChannel( + int instanceId, int javaScriptChannelInstanceId) {} + + @override + void scrollBy(int instanceId, int x, int y) {} + + @override + void scrollTo(int instanceId, int x, int y) {} + + @override + void setDownloadListener(int instanceId, int listenerInstanceId) {} + + @override + void setWebContentsDebuggingEnabled(bool enabled) {} + + @override + void setWebViewClient(int instanceId, int webViewClientInstanceId) {} + + @override + void setWebChromeClient(int instanceId, int clientInstanceId) {} +} + +class TestWebSettingsHostApiImpl extends TestWebSettingsHostApi { + @override + void create(int instanceId, int webViewInstanceId) {} + + @override + void dispose(int instanceId) {} + + @override + void setBuiltInZoomControls(int instanceId, bool enabled) {} + + @override + void setDisplayZoomControls(int instanceId, bool enabled) {} + + @override + void setDomStorageEnabled(int instanceId, bool flag) {} + + @override + void setJavaScriptCanOpenWindowsAutomatically(int instanceId, bool flag) {} + + @override + void setJavaScriptEnabled(int instanceId, bool flag) {} + + @override + void setLoadWithOverviewMode(int instanceId, bool overview) {} + + @override + void setMediaPlaybackRequiresUserGesture(int instanceId, bool require) {} + + @override + void setSupportMultipleWindows(int instanceId, bool support) {} + + @override + void setSupportZoom(int instanceId, bool support) {} + + @override + void setUseWideViewPort(int instanceId, bool use) {} + + @override + void setUserAgentString(int instanceId, String userAgentString) {} +} + +class TestJavaScriptChannelHostApiImpl extends TestJavaScriptChannelHostApi { + @override + void create(int instanceId, String channelName) {} + + @override + void dispose(int instanceId) {} +} + +class TestWebViewClientHostApiImpl extends TestWebViewClientHostApi { + @override + void create(int instanceId, bool shouldOverrideUrlLoading) {} + + @override + void dispose(int instanceId) {} +} + +class TestDownloadListenerHostApiImpl extends TestDownloadListenerHostApi { + @override + void create(int instanceId) {} + + @override + void dispose(int instanceId) {} +} + +class TestWebChromeClientHostApiImpl extends TestWebChromeClientHostApi { + @override + void create(int instanceId, int webViewClientInstanceId) {} + + @override + void dispose(int instanceId) {} +} diff --git a/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart b/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart new file mode 100644 index 000000000000..fd020fc362c8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/test/instance_manager_test.dart @@ -0,0 +1,35 @@ +// 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:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_android/src/instance_manager.dart'; + +void main() { + group('$InstanceManager', () { + late InstanceManager testInstanceManager; + + setUp(() { + testInstanceManager = InstanceManager(); + }); + + test('tryAddInstance', () { + final Object object = Object(); + + expect(testInstanceManager.tryAddInstance(object), 0); + expect(testInstanceManager.getInstanceId(object), 0); + expect(testInstanceManager.getInstance(0), object); + expect(testInstanceManager.tryAddInstance(object), null); + }); + + test('removeInstance', () { + final Object object = Object(); + testInstanceManager.tryAddInstance(object); + + expect(testInstanceManager.removeInstance(object), 0); + expect(testInstanceManager.getInstanceId(object), null); + expect(testInstanceManager.getInstance(0), null); + expect(testInstanceManager.removeInstance(object), null); + }); + }); +} From 0d330943941a7ba943305063f1733340a916deca Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 26 Oct 2021 20:49:31 -0700 Subject: [PATCH 6/7] [in_app_purchase] Update to the latest pkg:json_serializable (#4434) - Remove unneeded class now that enum helpers can be generated without one - Code reorganization - Remove superflous JsonKey values --- .../in_app_purchase/build.yaml | 7 - .../in_app_purchase_android/CHANGELOG.md | 6 + .../in_app_purchase_android/build.yaml | 3 +- .../billing_client_wrapper.dart | 92 ++++++++++- .../billing_client_wrapper.g.dart | 43 ++++++ .../enum_converters.dart | 143 ------------------ .../enum_converters.g.dart | 94 ------------ .../purchase_wrapper.dart | 40 ++++- .../purchase_wrapper.g.dart | 49 +----- .../sku_details_wrapper.dart | 4 +- .../sku_details_wrapper.g.dart | 35 ----- .../types/google_play_purchase_details.dart | 1 - .../in_app_purchase_android/pubspec.yaml | 8 +- .../billing_client_wrapper_test.dart | 5 +- .../purchase_wrapper_test.dart | 1 - .../sku_details_wrapper_test.dart | 3 +- ...rchase_android_platform_addition_test.dart | 1 - ...in_app_purchase_android_platform_test.dart | 1 - .../in_app_purchase_ios/CHANGELOG.md | 4 + .../in_app_purchase_ios/build.yaml | 3 +- .../store_kit_wrappers/enum_converters.dart | 6 +- .../store_kit_wrappers/enum_converters.g.dart | 40 +---- .../sk_payment_queue_wrapper.dart | 3 +- .../sk_payment_queue_wrapper.g.dart | 6 - .../sk_payment_transaction_wrappers.dart | 8 +- .../sk_product_wrapper.g.dart | 45 ------ .../sk_storefront_wrapper.dart | 2 +- .../in_app_purchase_ios/pubspec.yaml | 6 +- 28 files changed, 216 insertions(+), 443 deletions(-) delete mode 100644 packages/in_app_purchase/in_app_purchase/build.yaml create mode 100644 packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.g.dart delete mode 100644 packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.dart delete mode 100644 packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.g.dart diff --git a/packages/in_app_purchase/in_app_purchase/build.yaml b/packages/in_app_purchase/in_app_purchase/build.yaml deleted file mode 100644 index e15cf14b85fd..000000000000 --- a/packages/in_app_purchase/in_app_purchase/build.yaml +++ /dev/null @@ -1,7 +0,0 @@ -targets: - $default: - builders: - json_serializable: - options: - any_map: true - create_to_json: true diff --git a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md index a01eb9f8b70a..c504bd76cdc5 100644 --- a/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_android/CHANGELOG.md @@ -1,6 +1,12 @@ +## 0.1.6 + +* Require Dart SDK >= 2.14. +* Update `json_annotation` dependency to `^4.3.0`. + ## 0.1.5+1 * Fix a broken link in the README. + ## 0.1.5 * Introduced the `SkuDetailsWrapper.introductoryPriceAmountMicros` field of the correct type (`int`) and deprecated the `SkuDetailsWrapper.introductoryPriceMicros` field. diff --git a/packages/in_app_purchase/in_app_purchase_android/build.yaml b/packages/in_app_purchase/in_app_purchase_android/build.yaml index e15cf14b85fd..651a557fc1ca 100644 --- a/packages/in_app_purchase/in_app_purchase_android/build.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/build.yaml @@ -1,7 +1,8 @@ +# See https://pub.dev/packages/build_config targets: $default: builders: json_serializable: options: any_map: true - create_to_json: true + create_to_json: false diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart index 4393d1d72eaf..0e7024a59aaa 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.dart @@ -3,14 +3,17 @@ // found in the LICENSE file. import 'dart:async'; -import 'package:flutter/services.dart'; + import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:json_annotation/json_annotation.dart'; + import '../../billing_client_wrappers.dart'; import '../channel.dart'; import 'purchase_wrapper.dart'; import 'sku_details_wrapper.dart'; -import 'enum_converters.dart'; + +part 'billing_client_wrapper.g.dart'; /// Method identifier for the OnPurchaseUpdated method channel method. @visibleForTesting @@ -364,6 +367,7 @@ typedef void OnBillingServiceDisconnected(); /// [`BillingClient.BillingResponse`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponse). /// See the `BillingResponse` docs for more explanation of the different /// constants. +@JsonEnum(alwaysCreate: true) enum BillingResponse { // WARNING: Changes to this class need to be reflected in our generated code. // Run `flutter packages pub run build_runner watch` to rebuild and watch for @@ -418,11 +422,32 @@ enum BillingResponse { itemNotOwned, } +/// Serializer for [BillingResponse]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@BillingResponseConverter()`. +class BillingResponseConverter implements JsonConverter { + /// Default const constructor. + const BillingResponseConverter(); + + @override + BillingResponse fromJson(int? json) { + if (json == null) { + return BillingResponse.error; + } + return $enumDecode(_$BillingResponseEnumMap, json); + } + + @override + int toJson(BillingResponse object) => _$BillingResponseEnumMap[object]!; +} + /// Enum representing potential [SkuDetailsWrapper.type]s. /// /// Wraps /// [`BillingClient.SkuType`](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.SkuType) /// See the linked documentation for an explanation of the different constants. +@JsonEnum(alwaysCreate: true) enum SkuType { // WARNING: Changes to this class need to be reflected in our generated code. // Run `flutter packages pub run build_runner watch` to rebuild and watch for @@ -437,6 +462,26 @@ enum SkuType { subs, } +/// Serializer for [SkuType]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@SkuTypeConverter()`. +class SkuTypeConverter implements JsonConverter { + /// Default const constructor. + const SkuTypeConverter(); + + @override + SkuType fromJson(String? json) { + if (json == null) { + return SkuType.inapp; + } + return $enumDecode(_$SkuTypeEnumMap, json); + } + + @override + String toJson(SkuType object) => _$SkuTypeEnumMap[object]!; +} + /// Enum representing the proration mode. /// /// When upgrading or downgrading a subscription, set this mode to provide details @@ -444,6 +489,7 @@ enum SkuType { /// /// Wraps [`BillingFlowParams.ProrationMode`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.ProrationMode) /// See the linked documentation for an explanation of the different constants. +@JsonEnum(alwaysCreate: true) enum ProrationMode { // WARNING: Changes to this class need to be reflected in our generated code. // Run `flutter packages pub run build_runner watch` to rebuild and watch for @@ -477,7 +523,28 @@ enum ProrationMode { deferred, } +/// Serializer for [ProrationMode]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@ProrationModeConverter()`. +class ProrationModeConverter implements JsonConverter { + /// Default const constructor. + const ProrationModeConverter(); + + @override + ProrationMode fromJson(int? json) { + if (json == null) { + return ProrationMode.unknownSubscriptionUpgradeDowngradePolicy; + } + return $enumDecode(_$ProrationModeEnumMap, json); + } + + @override + int toJson(ProrationMode object) => _$ProrationModeEnumMap[object]!; +} + /// Features/capabilities supported by [BillingClient.isFeatureSupported()](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.FeatureType). +@JsonEnum(alwaysCreate: true) enum BillingClientFeature { // WARNING: Changes to this class need to be reflected in our generated code. // Run `flutter packages pub run build_runner watch` to rebuild and watch for @@ -504,3 +571,24 @@ enum BillingClientFeature { @JsonValue('subscriptionsUpdate') subscriptionsUpdate } + +/// Serializer for [BillingClientFeature]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@BillingClientFeatureConverter()`. +class BillingClientFeatureConverter + implements JsonConverter { + /// Default const constructor. + const BillingClientFeatureConverter(); + + @override + BillingClientFeature fromJson(String json) { + return $enumDecode( + _$BillingClientFeatureEnumMap.cast(), + json); + } + + @override + String toJson(BillingClientFeature object) => + _$BillingClientFeatureEnumMap[object]!; +} diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.g.dart new file mode 100644 index 000000000000..efe7656d2138 --- /dev/null +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/billing_client_wrapper.g.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'billing_client_wrapper.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +const _$BillingResponseEnumMap = { + BillingResponse.serviceTimeout: -3, + BillingResponse.featureNotSupported: -2, + BillingResponse.serviceDisconnected: -1, + BillingResponse.ok: 0, + BillingResponse.userCanceled: 1, + BillingResponse.serviceUnavailable: 2, + BillingResponse.billingUnavailable: 3, + BillingResponse.itemUnavailable: 4, + BillingResponse.developerError: 5, + BillingResponse.error: 6, + BillingResponse.itemAlreadyOwned: 7, + BillingResponse.itemNotOwned: 8, +}; + +const _$SkuTypeEnumMap = { + SkuType.inapp: 'inapp', + SkuType.subs: 'subs', +}; + +const _$ProrationModeEnumMap = { + ProrationMode.unknownSubscriptionUpgradeDowngradePolicy: 0, + ProrationMode.immediateWithTimeProration: 1, + ProrationMode.immediateAndChargeProratedPrice: 2, + ProrationMode.immediateWithoutProration: 3, + ProrationMode.deferred: 4, +}; + +const _$BillingClientFeatureEnumMap = { + BillingClientFeature.inAppItemsOnVR: 'inAppItemsOnVr', + BillingClientFeature.priceChangeConfirmation: 'priceChangeConfirmation', + BillingClientFeature.subscriptions: 'subscriptions', + BillingClientFeature.subscriptionsOnVR: 'subscriptionsOnVr', + BillingClientFeature.subscriptionsUpdate: 'subscriptionsUpdate', +}; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.dart deleted file mode 100644 index 931d92f7b1e7..000000000000 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.dart +++ /dev/null @@ -1,143 +0,0 @@ -// 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:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; -import 'package:json_annotation/json_annotation.dart'; - -import '../../billing_client_wrappers.dart'; - -part 'enum_converters.g.dart'; - -/// Serializer for [BillingResponse]. -/// -/// Use these in `@JsonSerializable()` classes by annotating them with -/// `@BillingResponseConverter()`. -class BillingResponseConverter implements JsonConverter { - /// Default const constructor. - const BillingResponseConverter(); - - @override - BillingResponse fromJson(int? json) { - if (json == null) { - return BillingResponse.error; - } - return _$enumDecode( - _$BillingResponseEnumMap.cast(), json); - } - - @override - int toJson(BillingResponse object) => _$BillingResponseEnumMap[object]!; -} - -/// Serializer for [SkuType]. -/// -/// Use these in `@JsonSerializable()` classes by annotating them with -/// `@SkuTypeConverter()`. -class SkuTypeConverter implements JsonConverter { - /// Default const constructor. - const SkuTypeConverter(); - - @override - SkuType fromJson(String? json) { - if (json == null) { - return SkuType.inapp; - } - return _$enumDecode( - _$SkuTypeEnumMap.cast(), json); - } - - @override - String toJson(SkuType object) => _$SkuTypeEnumMap[object]!; -} - -/// Serializer for [ProrationMode]. -/// -/// Use these in `@JsonSerializable()` classes by annotating them with -/// `@ProrationModeConverter()`. -class ProrationModeConverter implements JsonConverter { - /// Default const constructor. - const ProrationModeConverter(); - - @override - ProrationMode fromJson(int? json) { - if (json == null) { - return ProrationMode.unknownSubscriptionUpgradeDowngradePolicy; - } - return _$enumDecode( - _$ProrationModeEnumMap.cast(), json); - } - - @override - int toJson(ProrationMode object) => _$ProrationModeEnumMap[object]!; -} - -/// Serializer for [PurchaseStateWrapper]. -/// -/// Use these in `@JsonSerializable()` classes by annotating them with -/// `@PurchaseStateConverter()`. -class PurchaseStateConverter - implements JsonConverter { - /// Default const constructor. - const PurchaseStateConverter(); - - @override - PurchaseStateWrapper fromJson(int? json) { - if (json == null) { - return PurchaseStateWrapper.unspecified_state; - } - return _$enumDecode( - _$PurchaseStateWrapperEnumMap.cast(), - json); - } - - @override - int toJson(PurchaseStateWrapper object) => - _$PurchaseStateWrapperEnumMap[object]!; - - /// Converts the purchase state stored in `object` to a [PurchaseStatus]. - /// - /// [PurchaseStateWrapper.unspecified_state] is mapped to [PurchaseStatus.error]. - PurchaseStatus toPurchaseStatus(PurchaseStateWrapper object) { - switch (object) { - case PurchaseStateWrapper.pending: - return PurchaseStatus.pending; - case PurchaseStateWrapper.purchased: - return PurchaseStatus.purchased; - case PurchaseStateWrapper.unspecified_state: - return PurchaseStatus.error; - } - } -} - -/// Serializer for [BillingClientFeature]. -/// -/// Use these in `@JsonSerializable()` classes by annotating them with -/// `@BillingClientFeatureConverter()`. -class BillingClientFeatureConverter - implements JsonConverter { - /// Default const constructor. - const BillingClientFeatureConverter(); - - @override - BillingClientFeature fromJson(String json) { - return _$enumDecode( - _$BillingClientFeatureEnumMap.cast(), - json); - } - - @override - String toJson(BillingClientFeature object) => - _$BillingClientFeatureEnumMap[object]!; -} - -// Define a class so we generate serializer helper methods for the enums -// See https://github.com/google/json_serializable.dart/issues/778 -@JsonSerializable() -class _SerializedEnums { - late BillingResponse response; - late SkuType type; - late PurchaseStateWrapper purchaseState; - late ProrationMode prorationMode; - late BillingClientFeature billingClientFeature; -} diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.g.dart deleted file mode 100644 index fe92f56653e4..000000000000 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/enum_converters.g.dart +++ /dev/null @@ -1,94 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'enum_converters.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_SerializedEnums _$SerializedEnumsFromJson(Map json) => _SerializedEnums() - ..response = _$enumDecode(_$BillingResponseEnumMap, json['response']) - ..type = _$enumDecode(_$SkuTypeEnumMap, json['type']) - ..purchaseState = - _$enumDecode(_$PurchaseStateWrapperEnumMap, json['purchaseState']) - ..prorationMode = _$enumDecode(_$ProrationModeEnumMap, json['prorationMode']) - ..billingClientFeature = - _$enumDecode(_$BillingClientFeatureEnumMap, json['billingClientFeature']); - -Map _$SerializedEnumsToJson(_SerializedEnums instance) => - { - 'response': _$BillingResponseEnumMap[instance.response], - 'type': _$SkuTypeEnumMap[instance.type], - 'purchaseState': _$PurchaseStateWrapperEnumMap[instance.purchaseState], - 'prorationMode': _$ProrationModeEnumMap[instance.prorationMode], - 'billingClientFeature': - _$BillingClientFeatureEnumMap[instance.billingClientFeature], - }; - -K _$enumDecode( - Map enumValues, - Object? source, { - K? unknownValue, -}) { - if (source == null) { - throw ArgumentError( - 'A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}', - ); - } - - return enumValues.entries.singleWhere( - (e) => e.value == source, - orElse: () { - if (unknownValue == null) { - throw ArgumentError( - '`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}', - ); - } - return MapEntry(unknownValue, enumValues.values.first); - }, - ).key; -} - -const _$BillingResponseEnumMap = { - BillingResponse.serviceTimeout: -3, - BillingResponse.featureNotSupported: -2, - BillingResponse.serviceDisconnected: -1, - BillingResponse.ok: 0, - BillingResponse.userCanceled: 1, - BillingResponse.serviceUnavailable: 2, - BillingResponse.billingUnavailable: 3, - BillingResponse.itemUnavailable: 4, - BillingResponse.developerError: 5, - BillingResponse.error: 6, - BillingResponse.itemAlreadyOwned: 7, - BillingResponse.itemNotOwned: 8, -}; - -const _$SkuTypeEnumMap = { - SkuType.inapp: 'inapp', - SkuType.subs: 'subs', -}; - -const _$PurchaseStateWrapperEnumMap = { - PurchaseStateWrapper.unspecified_state: 0, - PurchaseStateWrapper.purchased: 1, - PurchaseStateWrapper.pending: 2, -}; - -const _$ProrationModeEnumMap = { - ProrationMode.unknownSubscriptionUpgradeDowngradePolicy: 0, - ProrationMode.immediateWithTimeProration: 1, - ProrationMode.immediateAndChargeProratedPrice: 2, - ProrationMode.immediateWithoutProration: 3, - ProrationMode.deferred: 4, -}; - -const _$BillingClientFeatureEnumMap = { - BillingClientFeature.inAppItemsOnVR: 'inAppItemsOnVr', - BillingClientFeature.priceChangeConfirmation: 'priceChangeConfirmation', - BillingClientFeature.subscriptions: 'subscriptions', - BillingClientFeature.subscriptionsOnVR: 'subscriptionsOnVr', - BillingClientFeature.subscriptionsUpdate: 'subscriptionsUpdate', -}; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart index 374c26ab4a7a..742288e56412 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. import 'dart:ui' show hashValues; + import 'package:flutter/foundation.dart'; import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'enum_converters.dart'; + import 'billing_client_wrapper.dart'; import 'sku_details_wrapper.dart'; @@ -323,6 +324,7 @@ class PurchasesHistoryResult { /// Wraps /// [`BillingClient.api.Purchase.PurchaseState`](https://developer.android.com/reference/com/android/billingclient/api/Purchase.PurchaseState.html). /// * See also: [PurchaseWrapper]. +@JsonEnum(alwaysCreate: true) enum PurchaseStateWrapper { /// The state is unspecified. /// @@ -348,3 +350,39 @@ enum PurchaseStateWrapper { @JsonValue(2) pending, } + +/// Serializer for [PurchaseStateWrapper]. +/// +/// Use these in `@JsonSerializable()` classes by annotating them with +/// `@PurchaseStateConverter()`. +class PurchaseStateConverter + implements JsonConverter { + /// Default const constructor. + const PurchaseStateConverter(); + + @override + PurchaseStateWrapper fromJson(int? json) { + if (json == null) { + return PurchaseStateWrapper.unspecified_state; + } + return $enumDecode(_$PurchaseStateWrapperEnumMap, json); + } + + @override + int toJson(PurchaseStateWrapper object) => + _$PurchaseStateWrapperEnumMap[object]!; + + /// Converts the purchase state stored in `object` to a [PurchaseStatus]. + /// + /// [PurchaseStateWrapper.unspecified_state] is mapped to [PurchaseStatus.error]. + PurchaseStatus toPurchaseStatus(PurchaseStateWrapper object) { + switch (object) { + case PurchaseStateWrapper.pending: + return PurchaseStatus.pending; + case PurchaseStateWrapper.purchased: + return PurchaseStatus.purchased; + case PurchaseStateWrapper.unspecified_state: + return PurchaseStatus.error; + } + } +} diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart index b5d9fe8cd3af..5815a866c82d 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/purchase_wrapper.g.dart @@ -23,24 +23,6 @@ PurchaseWrapper _$PurchaseWrapperFromJson(Map json) => PurchaseWrapper( obfuscatedProfileId: json['obfuscatedProfileId'] as String?, ); -Map _$PurchaseWrapperToJson(PurchaseWrapper instance) => - { - 'orderId': instance.orderId, - 'packageName': instance.packageName, - 'purchaseTime': instance.purchaseTime, - 'purchaseToken': instance.purchaseToken, - 'signature': instance.signature, - 'sku': instance.sku, - 'isAutoRenewing': instance.isAutoRenewing, - 'originalJson': instance.originalJson, - 'developerPayload': instance.developerPayload, - 'isAcknowledged': instance.isAcknowledged, - 'purchaseState': - const PurchaseStateConverter().toJson(instance.purchaseState), - 'obfuscatedAccountId': instance.obfuscatedAccountId, - 'obfuscatedProfileId': instance.obfuscatedProfileId, - }; - PurchaseHistoryRecordWrapper _$PurchaseHistoryRecordWrapperFromJson(Map json) => PurchaseHistoryRecordWrapper( purchaseTime: json['purchaseTime'] as int? ?? 0, @@ -51,17 +33,6 @@ PurchaseHistoryRecordWrapper _$PurchaseHistoryRecordWrapperFromJson(Map json) => developerPayload: json['developerPayload'] as String?, ); -Map _$PurchaseHistoryRecordWrapperToJson( - PurchaseHistoryRecordWrapper instance) => - { - 'purchaseTime': instance.purchaseTime, - 'purchaseToken': instance.purchaseToken, - 'signature': instance.signature, - 'sku': instance.sku, - 'originalJson': instance.originalJson, - 'developerPayload': instance.developerPayload, - }; - PurchasesResultWrapper _$PurchasesResultWrapperFromJson(Map json) => PurchasesResultWrapper( responseCode: const BillingResponseConverter() @@ -77,15 +48,6 @@ PurchasesResultWrapper _$PurchasesResultWrapperFromJson(Map json) => [], ); -Map _$PurchasesResultWrapperToJson( - PurchasesResultWrapper instance) => - { - 'billingResult': instance.billingResult, - 'responseCode': - const BillingResponseConverter().toJson(instance.responseCode), - 'purchasesList': instance.purchasesList, - }; - PurchasesHistoryResult _$PurchasesHistoryResultFromJson(Map json) => PurchasesHistoryResult( billingResult: @@ -100,9 +62,8 @@ PurchasesHistoryResult _$PurchasesHistoryResultFromJson(Map json) => [], ); -Map _$PurchasesHistoryResultToJson( - PurchasesHistoryResult instance) => - { - 'billingResult': instance.billingResult, - 'purchaseHistoryRecordList': instance.purchaseHistoryRecordList, - }; +const _$PurchaseStateWrapperEnumMap = { + PurchaseStateWrapper.unspecified_state: 0, + PurchaseStateWrapper.purchased: 1, + PurchaseStateWrapper.pending: 2, +}; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart index 754f7a352f1c..8069a1f72281 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. import 'dart:ui' show hashValues; + import 'package:flutter/foundation.dart'; import 'package:json_annotation/json_annotation.dart'; + import 'billing_client_wrapper.dart'; -import 'enum_converters.dart'; // WARNING: Changes to `@JsonSerializable` classes need to be reflected in the // below generated file. Run `flutter packages pub run build_runner watch` to @@ -75,7 +76,6 @@ class SkuDetailsWrapper { /// /// Returns 0 if the SKU is not a subscription or doesn't have an introductory /// period. - @JsonKey(name: 'introductoryPriceAmountMicros', defaultValue: 0) final int introductoryPriceAmountMicros; /// String representation of [introductoryPrice] in micro-units 990000 diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.g.dart index 53d5931ecb56..05eb6bed0035 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/billing_client_wrappers/sku_details_wrapper.g.dart @@ -26,26 +26,6 @@ SkuDetailsWrapper _$SkuDetailsWrapperFromJson(Map json) => SkuDetailsWrapper( originalPriceAmountMicros: json['originalPriceAmountMicros'] as int? ?? 0, ); -Map _$SkuDetailsWrapperToJson(SkuDetailsWrapper instance) => - { - 'description': instance.description, - 'freeTrialPeriod': instance.freeTrialPeriod, - 'introductoryPrice': instance.introductoryPrice, - 'introductoryPriceAmountMicros': instance.introductoryPriceAmountMicros, - 'introductoryPriceCycles': instance.introductoryPriceCycles, - 'introductoryPricePeriod': instance.introductoryPricePeriod, - 'price': instance.price, - 'priceAmountMicros': instance.priceAmountMicros, - 'priceCurrencyCode': instance.priceCurrencyCode, - 'priceCurrencySymbol': instance.priceCurrencySymbol, - 'sku': instance.sku, - 'subscriptionPeriod': instance.subscriptionPeriod, - 'title': instance.title, - 'type': const SkuTypeConverter().toJson(instance.type), - 'originalPrice': instance.originalPrice, - 'originalPriceAmountMicros': instance.originalPriceAmountMicros, - }; - SkuDetailsResponseWrapper _$SkuDetailsResponseWrapperFromJson(Map json) => SkuDetailsResponseWrapper( billingResult: @@ -59,24 +39,9 @@ SkuDetailsResponseWrapper _$SkuDetailsResponseWrapperFromJson(Map json) => [], ); -Map _$SkuDetailsResponseWrapperToJson( - SkuDetailsResponseWrapper instance) => - { - 'billingResult': instance.billingResult, - 'skuDetailsList': instance.skuDetailsList, - }; - BillingResultWrapper _$BillingResultWrapperFromJson(Map json) => BillingResultWrapper( responseCode: const BillingResponseConverter() .fromJson(json['responseCode'] as int?), debugMessage: json['debugMessage'] as String?, ); - -Map _$BillingResultWrapperToJson( - BillingResultWrapper instance) => - { - 'responseCode': - const BillingResponseConverter().toJson(instance.responseCode), - 'debugMessage': instance.debugMessage, - }; diff --git a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart index 53b58bd664fd..e607164e59f1 100644 --- a/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_android/lib/src/types/google_play_purchase_details.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; import '../../billing_client_wrappers.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml index d51abbb43edc..7230b56d5af9 100644 --- a/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_android/pubspec.yaml @@ -2,10 +2,10 @@ name: in_app_purchase_android description: An implementation for the Android platform of the Flutter `in_app_purchase` plugin. This uses the Android BillingClient APIs. repository: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.1.5+1 +version: 0.1.6 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.14.0 <3.0.0" flutter: ">=2.0.0" flutter: @@ -21,12 +21,12 @@ dependencies: flutter: sdk: flutter in_app_purchase_platform_interface: ^1.1.0 - json_annotation: ^4.0.1 + json_annotation: ^4.3.0 meta: ^1.3.0 dev_dependencies: build_runner: ^2.0.0 flutter_test: sdk: flutter - json_serializable: ^5.0.2 + json_serializable: ^6.0.0 test: ^1.16.0 diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart index 02ae9ba33564..1a2a0e4712a7 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/billing_client_wrapper_test.dart @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:in_app_purchase_android/billing_client_wrappers.dart'; -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; import 'package:in_app_purchase_android/src/channel.dart'; import '../stub_in_app_purchase_platform.dart'; -import 'sku_details_wrapper_test.dart'; import 'purchase_wrapper_test.dart'; +import 'sku_details_wrapper_test.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart index 70b9fcad4da7..f51342045a7d 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/purchase_wrapper_test.dart @@ -4,7 +4,6 @@ import 'package:in_app_purchase_android/billing_client_wrappers.dart'; import 'package:in_app_purchase_android/in_app_purchase_android.dart'; -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; import 'package:test/test.dart'; final PurchaseWrapper dummyPurchase = PurchaseWrapper( diff --git a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart index 18804a41940e..08cde077be93 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/billing_client_wrappers/sku_details_wrapper_test.dart @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:in_app_purchase_android/billing_client_wrappers.dart'; import 'package:in_app_purchase_android/src/types/google_play_product_details.dart'; import 'package:test/test.dart'; -import 'package:in_app_purchase_android/billing_client_wrappers.dart'; -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; final SkuDetailsWrapper dummySkuDetails = SkuDetailsWrapper( description: 'description', diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart index a478cabac89b..ecefc4d37c84 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_addition_test.dart @@ -7,7 +7,6 @@ import 'package:flutter/widgets.dart' as widgets; import 'package:flutter_test/flutter_test.dart'; import 'package:in_app_purchase_android/billing_client_wrappers.dart'; import 'package:in_app_purchase_android/in_app_purchase_android.dart'; -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; import 'package:in_app_purchase_android/src/channel.dart'; import 'package:in_app_purchase_android/src/in_app_purchase_android_platform_addition.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart index 52ec08bea07a..bd704894daf8 100644 --- a/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_android/test/in_app_purchase_android_platform_test.dart @@ -9,7 +9,6 @@ import 'package:flutter/widgets.dart' as widgets; import 'package:flutter_test/flutter_test.dart'; import 'package:in_app_purchase_android/billing_client_wrappers.dart'; import 'package:in_app_purchase_android/in_app_purchase_android.dart'; -import 'package:in_app_purchase_android/src/billing_client_wrappers/enum_converters.dart'; import 'package:in_app_purchase_android/src/channel.dart'; import 'package:in_app_purchase_android/src/in_app_purchase_android_platform_addition.dart'; import 'package:in_app_purchase_platform_interface/in_app_purchase_platform_interface.dart'; diff --git a/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md index 76cafa9201cc..4daa6a2d1dcb 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4 + +* Require Dart SDK >= 2.14. + ## 0.1.3+5 * Updated example app to handle restored purchases properly. diff --git a/packages/in_app_purchase/in_app_purchase_ios/build.yaml b/packages/in_app_purchase/in_app_purchase_ios/build.yaml index e15cf14b85fd..651a557fc1ca 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/build.yaml +++ b/packages/in_app_purchase/in_app_purchase_ios/build.yaml @@ -1,7 +1,8 @@ +# See https://pub.dev/packages/build_config targets: $default: builders: json_serializable: options: any_map: true - create_to_json: true + create_to_json: false diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.dart index 70178260febf..8a0526f07ad7 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.dart @@ -23,7 +23,7 @@ class SKTransactionStatusConverter if (json == null) { return SKPaymentTransactionStateWrapper.unspecified; } - return _$enumDecode( + return $enumDecode( _$SKPaymentTransactionStateWrapperEnumMap .cast(), json); @@ -64,7 +64,7 @@ class SKSubscriptionPeriodUnitConverter if (json == null) { return SKSubscriptionPeriodUnit.day; } - return _$enumDecode( + return $enumDecode( _$SKSubscriptionPeriodUnitEnumMap .cast(), json); @@ -89,7 +89,7 @@ class SKProductDiscountPaymentModeConverter if (json == null) { return SKProductDiscountPaymentMode.payAsYouGo; } - return _$enumDecode( + return $enumDecode( _$SKProductDiscountPaymentModeEnumMap .cast(), json); diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.g.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.g.dart index ce0f56ba4d34..0d05720dc7ae 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.g.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/enum_converters.g.dart @@ -8,45 +8,11 @@ part of 'enum_converters.dart'; _SerializedEnums _$SerializedEnumsFromJson(Map json) => _SerializedEnums() ..response = - _$enumDecode(_$SKPaymentTransactionStateWrapperEnumMap, json['response']) - ..unit = _$enumDecode(_$SKSubscriptionPeriodUnitEnumMap, json['unit']) - ..discountPaymentMode = _$enumDecode( + $enumDecode(_$SKPaymentTransactionStateWrapperEnumMap, json['response']) + ..unit = $enumDecode(_$SKSubscriptionPeriodUnitEnumMap, json['unit']) + ..discountPaymentMode = $enumDecode( _$SKProductDiscountPaymentModeEnumMap, json['discountPaymentMode']); -Map _$SerializedEnumsToJson(_SerializedEnums instance) => - { - 'response': _$SKPaymentTransactionStateWrapperEnumMap[instance.response], - 'unit': _$SKSubscriptionPeriodUnitEnumMap[instance.unit], - 'discountPaymentMode': - _$SKProductDiscountPaymentModeEnumMap[instance.discountPaymentMode], - }; - -K _$enumDecode( - Map enumValues, - Object? source, { - K? unknownValue, -}) { - if (source == null) { - throw ArgumentError( - 'A value must be provided. Supported values: ' - '${enumValues.values.join(', ')}', - ); - } - - return enumValues.entries.singleWhere( - (e) => e.value == source, - orElse: () { - if (unknownValue == null) { - throw ArgumentError( - '`$source` is not one of the supported values: ' - '${enumValues.values.join(', ')}', - ); - } - return MapEntry(unknownValue, enumValues.values.first); - }, - ).key; -} - const _$SKPaymentTransactionStateWrapperEnumMap = { SKPaymentTransactionStateWrapper.purchasing: 0, SKPaymentTransactionStateWrapper.purchased: 1, diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart index 079e75078037..3decba2a9818 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.dart @@ -375,7 +375,7 @@ class SKError { /// [SKPaymentQueueWrapper.addPayment] directly with a product identifier to /// initiate a payment. @immutable -@JsonSerializable() +@JsonSerializable(createToJson: true) class SKPaymentWrapper { /// Creates a new [SKPaymentWrapper] with the provided information. const SKPaymentWrapper( @@ -448,7 +448,6 @@ class SKPaymentWrapper { /// /// See https://developer.apple.com/in-app-purchase/ for a guide on Sandbox /// testing. - @JsonKey(defaultValue: false) final bool simulatesAskToBuyInSandbox; @override diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart index 4d2b5e4b3d4b..8c0e64b2b9f6 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart @@ -15,12 +15,6 @@ SKError _$SKErrorFromJson(Map json) => SKError( {}, ); -Map _$SKErrorToJson(SKError instance) => { - 'code': instance.code, - 'domain': instance.domain, - 'userInfo': instance.userInfo, - }; - SKPaymentWrapper _$SKPaymentWrapperFromJson(Map json) => SKPaymentWrapper( productIdentifier: json['productIdentifier'] as String? ?? '', applicationUsername: json['applicationUsername'] as String?, diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart index 01cd6db0dda1..885e9c075b48 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_payment_transaction_wrappers.dart @@ -3,10 +3,12 @@ // found in the LICENSE file. import 'dart:ui' show hashValues; + import 'package:json_annotation/json_annotation.dart'; -import 'sk_product_wrapper.dart'; -import 'sk_payment_queue_wrapper.dart'; + import 'enum_converters.dart'; +import 'sk_payment_queue_wrapper.dart'; +import 'sk_product_wrapper.dart'; part 'sk_payment_transaction_wrappers.g.dart'; @@ -101,7 +103,7 @@ enum SKPaymentTransactionStateWrapper { /// /// Dart wrapper around StoreKit's /// [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction?language=objc). -@JsonSerializable() +@JsonSerializable(createToJson: true) class SKPaymentTransactionWrapper { /// Creates a new [SKPaymentTransactionWrapper] with the provided information. SKPaymentTransactionWrapper({ diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart index 485bf1932efa..c9079ff64a1e 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart @@ -20,13 +20,6 @@ SkProductResponseWrapper _$SkProductResponseWrapperFromJson(Map json) => [], ); -Map _$SkProductResponseWrapperToJson( - SkProductResponseWrapper instance) => - { - 'products': instance.products, - 'invalidProductIdentifiers': instance.invalidProductIdentifiers, - }; - SKProductSubscriptionPeriodWrapper _$SKProductSubscriptionPeriodWrapperFromJson( Map json) => SKProductSubscriptionPeriodWrapper( @@ -35,13 +28,6 @@ SKProductSubscriptionPeriodWrapper _$SKProductSubscriptionPeriodWrapperFromJson( .fromJson(json['unit'] as int?), ); -Map _$SKProductSubscriptionPeriodWrapperToJson( - SKProductSubscriptionPeriodWrapper instance) => - { - 'numberOfUnits': instance.numberOfUnits, - 'unit': const SKSubscriptionPeriodUnitConverter().toJson(instance.unit), - }; - SKProductDiscountWrapper _$SKProductDiscountWrapperFromJson(Map json) => SKProductDiscountWrapper( price: json['price'] as String? ?? '', @@ -58,17 +44,6 @@ SKProductDiscountWrapper _$SKProductDiscountWrapperFromJson(Map json) => )), ); -Map _$SKProductDiscountWrapperToJson( - SKProductDiscountWrapper instance) => - { - 'price': instance.price, - 'priceLocale': instance.priceLocale, - 'numberOfPeriods': instance.numberOfPeriods, - 'paymentMode': const SKProductDiscountPaymentModeConverter() - .toJson(instance.paymentMode), - 'subscriptionPeriod': instance.subscriptionPeriod, - }; - SKProductWrapper _$SKProductWrapperFromJson(Map json) => SKProductWrapper( productIdentifier: json['productIdentifier'] as String? ?? '', localizedTitle: json['localizedTitle'] as String? ?? '', @@ -92,29 +67,9 @@ SKProductWrapper _$SKProductWrapperFromJson(Map json) => SKProductWrapper( Map.from(json['introductoryPrice'] as Map)), ); -Map _$SKProductWrapperToJson(SKProductWrapper instance) => - { - 'productIdentifier': instance.productIdentifier, - 'localizedTitle': instance.localizedTitle, - 'localizedDescription': instance.localizedDescription, - 'priceLocale': instance.priceLocale, - 'subscriptionGroupIdentifier': instance.subscriptionGroupIdentifier, - 'price': instance.price, - 'subscriptionPeriod': instance.subscriptionPeriod, - 'introductoryPrice': instance.introductoryPrice, - }; - SKPriceLocaleWrapper _$SKPriceLocaleWrapperFromJson(Map json) => SKPriceLocaleWrapper( currencySymbol: json['currencySymbol'] as String? ?? '', currencyCode: json['currencyCode'] as String? ?? '', countryCode: json['countryCode'] as String? ?? '', ); - -Map _$SKPriceLocaleWrapperToJson( - SKPriceLocaleWrapper instance) => - { - 'currencySymbol': instance.currencySymbol, - 'currencyCode': instance.currencyCode, - 'countryCode': instance.countryCode, - }; diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart index 934fdea355e3..bcdae3206c00 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_storefront_wrapper.dart @@ -12,7 +12,7 @@ part 'sk_storefront_wrapper.g.dart'; /// /// Dart wrapper around StoreKit's /// [SKStorefront](https://developer.apple.com/documentation/storekit/skstorefront?language=objc). -@JsonSerializable() +@JsonSerializable(createToJson: true) class SKStorefrontWrapper { /// Creates a new [SKStorefrontWrapper] with the provided information. SKStorefrontWrapper({ diff --git a/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml index fdd769e90674..b40ad1da149e 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase_ios description: An implementation for the iOS platform of the Flutter `in_app_purchase` plugin. This uses the iOS StoreKit Framework. repository: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.1.3+5 +version: 0.1.4 environment: sdk: ">=2.14.0 <3.0.0" @@ -20,12 +20,12 @@ dependencies: flutter: sdk: flutter in_app_purchase_platform_interface: ^1.1.0 - json_annotation: ^4.0.1 + json_annotation: ^4.3.0 meta: ^1.3.0 dev_dependencies: build_runner: ^2.0.0 flutter_test: sdk: flutter - json_serializable: ^5.0.2 + json_serializable: ^6.0.0 test: ^1.16.0 From 42364e49fc25653768f4f659564215d247d66f81 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Wed, 27 Oct 2021 09:46:27 -0700 Subject: [PATCH 7/7] Implement Android WebView api with pigeon (Java portion) (#4441) --- .../android/build.gradle | 4 + .../DownloadListenerHostApiImpl.java | 44 + .../webviewflutter/FlutterWebViewClient.java | 2 +- .../GeneratedAndroidWebView.java | 1909 +++++++++++++++++ .../webviewflutter/InputAwareWebView.java | 2 +- .../webviewflutter/InstanceManager.java | 39 + .../webviewflutter/JavaScriptChannel.java | 2 +- .../JavaScriptChannelHostApiImpl.java | 61 + .../WebChromeClientHostApiImpl.java | 92 + .../WebSettingsHostApiImpl.java | 101 + .../WebViewClientHostApiImpl.java | 239 +++ .../webviewflutter/WebViewHostApiImpl.java | 233 ++ .../java/android/util/LongSparseArray.java | 29 + .../webviewflutter/DownloadListenerTest.java | 65 + .../webviewflutter/JavaScriptChannelTest.java | 60 + .../webviewflutter/WebChromeClientTest.java | 67 + .../webviewflutter/WebSettingsTest.java | 103 + .../webviewflutter/WebViewClientTest.java | 77 + .../plugins/webviewflutter/WebViewTest.java | 173 ++ .../generatePigeons.sh | 4 +- 20 files changed, 3302 insertions(+), 4 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/DownloadListenerHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannelHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/android/util/LongSparseArray.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java diff --git a/packages/webview_flutter/webview_flutter_android/android/build.gradle b/packages/webview_flutter/webview_flutter_android/android/build.gradle index 4a164317c60f..ef1485a765d0 100644 --- a/packages/webview_flutter/webview_flutter_android/android/build.gradle +++ b/packages/webview_flutter/webview_flutter_android/android/build.gradle @@ -42,6 +42,10 @@ android { testImplementation 'androidx.test:core:1.3.0' } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } testOptions { unitTests.includeAndroidResources = true diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/DownloadListenerHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/DownloadListenerHostApiImpl.java new file mode 100644 index 000000000000..202be87d7d1e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/DownloadListenerHostApiImpl.java @@ -0,0 +1,44 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.webkit.DownloadListener; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.DownloadListenerFlutterApi; + +class DownloadListenerHostApiImpl implements GeneratedAndroidWebView.DownloadListenerHostApi { + private final InstanceManager instanceManager; + private final DownloadListenerCreator downloadListenerCreator; + private final GeneratedAndroidWebView.DownloadListenerFlutterApi downloadListenerFlutterApi; + + static class DownloadListenerCreator { + DownloadListener createDownloadListener( + Long instanceId, DownloadListenerFlutterApi downloadListenerFlutterApi) { + return (url, userAgent, contentDisposition, mimetype, contentLength) -> + downloadListenerFlutterApi.onDownloadStart( + instanceId, url, userAgent, contentDisposition, mimetype, contentLength, reply -> {}); + } + } + + DownloadListenerHostApiImpl( + InstanceManager instanceManager, + DownloadListenerCreator downloadListenerCreator, + DownloadListenerFlutterApi downloadListenerFlutterApi) { + this.instanceManager = instanceManager; + this.downloadListenerCreator = downloadListenerCreator; + this.downloadListenerFlutterApi = downloadListenerFlutterApi; + } + + @Override + public void create(Long instanceId) { + final DownloadListener downloadListener = + downloadListenerCreator.createDownloadListener(instanceId, downloadListenerFlutterApi); + instanceManager.addInstance(downloadListener, instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java index 260ef8e8b15d..a86d3e8a4b63 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebViewClient.java @@ -104,7 +104,7 @@ boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } // This version of shouldOverrideUrlLoading is only invoked by the webview on devices with - // webview versions earlier than 67(it is also invoked when hasNavigationDelegate is false). + // webview versions earlier than 67(it is also invoked when hasNavigationDelegate is false). // On these devices we cannot tell whether the navigation is targeted to the main frame or not. // We proceed assuming that the navigation is targeted to the main frame. If the page had any // frames they will be loaded in the main frame instead. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java new file mode 100644 index 000000000000..ba2b9b1ac481 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java @@ -0,0 +1,1909 @@ +// 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. + +// Autogenerated from Pigeon (v1.0.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package io.flutter.plugins.webviewflutter; + +import io.flutter.plugin.common.BasicMessageChannel; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; +import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"}) +public class GeneratedAndroidWebView { + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class WebResourceRequestData { + private String url; + + public String getUrl() { + return url; + } + + public void setUrl(String setterArg) { + this.url = setterArg; + } + + private Boolean isForMainFrame; + + public Boolean getIsForMainFrame() { + return isForMainFrame; + } + + public void setIsForMainFrame(Boolean setterArg) { + this.isForMainFrame = setterArg; + } + + private Boolean isRedirect; + + public Boolean getIsRedirect() { + return isRedirect; + } + + public void setIsRedirect(Boolean setterArg) { + this.isRedirect = setterArg; + } + + private Boolean hasGesture; + + public Boolean getHasGesture() { + return hasGesture; + } + + public void setHasGesture(Boolean setterArg) { + this.hasGesture = setterArg; + } + + private String method; + + public String getMethod() { + return method; + } + + public void setMethod(String setterArg) { + this.method = setterArg; + } + + private Map requestHeaders; + + public Map getRequestHeaders() { + return requestHeaders; + } + + public void setRequestHeaders(Map setterArg) { + this.requestHeaders = setterArg; + } + + Map toMap() { + Map toMapResult = new HashMap<>(); + toMapResult.put("url", url); + toMapResult.put("isForMainFrame", isForMainFrame); + toMapResult.put("isRedirect", isRedirect); + toMapResult.put("hasGesture", hasGesture); + toMapResult.put("method", method); + toMapResult.put("requestHeaders", requestHeaders); + return toMapResult; + } + + static WebResourceRequestData fromMap(Map map) { + WebResourceRequestData fromMapResult = new WebResourceRequestData(); + Object url = map.get("url"); + fromMapResult.url = (String) url; + Object isForMainFrame = map.get("isForMainFrame"); + fromMapResult.isForMainFrame = (Boolean) isForMainFrame; + Object isRedirect = map.get("isRedirect"); + fromMapResult.isRedirect = (Boolean) isRedirect; + Object hasGesture = map.get("hasGesture"); + fromMapResult.hasGesture = (Boolean) hasGesture; + Object method = map.get("method"); + fromMapResult.method = (String) method; + Object requestHeaders = map.get("requestHeaders"); + fromMapResult.requestHeaders = (Map) requestHeaders; + return fromMapResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static class WebResourceErrorData { + private Long errorCode; + + public Long getErrorCode() { + return errorCode; + } + + public void setErrorCode(Long setterArg) { + this.errorCode = setterArg; + } + + private String description; + + public String getDescription() { + return description; + } + + public void setDescription(String setterArg) { + this.description = setterArg; + } + + Map toMap() { + Map toMapResult = new HashMap<>(); + toMapResult.put("errorCode", errorCode); + toMapResult.put("description", description); + return toMapResult; + } + + static WebResourceErrorData fromMap(Map map) { + WebResourceErrorData fromMapResult = new WebResourceErrorData(); + Object errorCode = map.get("errorCode"); + fromMapResult.errorCode = + (errorCode == null) + ? null + : ((errorCode instanceof Integer) ? (Integer) errorCode : (Long) errorCode); + Object description = map.get("description"); + fromMapResult.description = (String) description; + return fromMapResult; + } + } + + public interface Result { + void success(T result); + + void error(Throwable error); + } + + private static class WebViewHostApiCodec extends StandardMessageCodec { + public static final WebViewHostApiCodec INSTANCE = new WebViewHostApiCodec(); + + private WebViewHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface WebViewHostApi { + void create(Long instanceId, Boolean useHybridComposition); + + void dispose(Long instanceId); + + void loadUrl(Long instanceId, String url, Map headers); + + String getUrl(Long instanceId); + + Boolean canGoBack(Long instanceId); + + Boolean canGoForward(Long instanceId); + + void goBack(Long instanceId); + + void goForward(Long instanceId); + + void reload(Long instanceId); + + void clearCache(Long instanceId, Boolean includeDiskFiles); + + void evaluateJavascript(Long instanceId, String javascriptString, Result result); + + String getTitle(Long instanceId); + + void scrollTo(Long instanceId, Long x, Long y); + + void scrollBy(Long instanceId, Long x, Long y); + + Long getScrollX(Long instanceId); + + Long getScrollY(Long instanceId); + + void setWebContentsDebuggingEnabled(Boolean enabled); + + void setWebViewClient(Long instanceId, Long webViewClientInstanceId); + + void addJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId); + + void removeJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId); + + void setDownloadListener(Long instanceId, Long listenerInstanceId); + + void setWebChromeClient(Long instanceId, Long clientInstanceId); + + /** The codec used by WebViewHostApi. */ + static MessageCodec getCodec() { + return WebViewHostApiCodec.INSTANCE; + } + + /** Sets up an instance of `WebViewHostApi` to handle messages through the `binaryMessenger`. */ + static void setup(BinaryMessenger binaryMessenger, WebViewHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean useHybridCompositionArg = (Boolean) args.get(1); + if (useHybridCompositionArg == null) { + throw new NullPointerException("useHybridCompositionArg unexpectedly null."); + } + api.create(instanceIdArg.longValue(), useHybridCompositionArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.loadUrl", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String urlArg = (String) args.get(1); + if (urlArg == null) { + throw new NullPointerException("urlArg unexpectedly null."); + } + Map headersArg = (Map) args.get(2); + if (headersArg == null) { + throw new NullPointerException("headersArg unexpectedly null."); + } + api.loadUrl(instanceIdArg.longValue(), urlArg, headersArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getUrl", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String output = api.getUrl(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.canGoBack", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean output = api.canGoBack(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.canGoForward", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean output = api.canGoForward(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.goBack", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.goBack(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.goForward", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.goForward(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.reload", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.reload(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.clearCache", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean includeDiskFilesArg = (Boolean) args.get(1); + if (includeDiskFilesArg == null) { + throw new NullPointerException("includeDiskFilesArg unexpectedly null."); + } + api.clearCache(instanceIdArg.longValue(), includeDiskFilesArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.evaluateJavascript", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String javascriptStringArg = (String) args.get(1); + if (javascriptStringArg == null) { + throw new NullPointerException("javascriptStringArg unexpectedly null."); + } + Result resultCallback = + new Result() { + public void success(String result) { + wrapped.put("result", result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + wrapped.put("error", wrapError(error)); + reply.reply(wrapped); + } + }; + + api.evaluateJavascript( + instanceIdArg.longValue(), javascriptStringArg, resultCallback); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + reply.reply(wrapped); + } + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getTitle", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String output = api.getTitle(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.scrollTo", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number xArg = (Number) args.get(1); + if (xArg == null) { + throw new NullPointerException("xArg unexpectedly null."); + } + Number yArg = (Number) args.get(2); + if (yArg == null) { + throw new NullPointerException("yArg unexpectedly null."); + } + api.scrollTo(instanceIdArg.longValue(), xArg.longValue(), yArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.scrollBy", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number xArg = (Number) args.get(1); + if (xArg == null) { + throw new NullPointerException("xArg unexpectedly null."); + } + Number yArg = (Number) args.get(2); + if (yArg == null) { + throw new NullPointerException("yArg unexpectedly null."); + } + api.scrollBy(instanceIdArg.longValue(), xArg.longValue(), yArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getScrollX", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Long output = api.getScrollX(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getScrollY", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Long output = api.getScrollY(instanceIdArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Boolean enabledArg = (Boolean) args.get(0); + if (enabledArg == null) { + throw new NullPointerException("enabledArg unexpectedly null."); + } + api.setWebContentsDebuggingEnabled(enabledArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.setWebViewClient", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number webViewClientInstanceIdArg = (Number) args.get(1); + if (webViewClientInstanceIdArg == null) { + throw new NullPointerException("webViewClientInstanceIdArg unexpectedly null."); + } + api.setWebViewClient( + instanceIdArg.longValue(), webViewClientInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number javaScriptChannelInstanceIdArg = (Number) args.get(1); + if (javaScriptChannelInstanceIdArg == null) { + throw new NullPointerException( + "javaScriptChannelInstanceIdArg unexpectedly null."); + } + api.addJavaScriptChannel( + instanceIdArg.longValue(), javaScriptChannelInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number javaScriptChannelInstanceIdArg = (Number) args.get(1); + if (javaScriptChannelInstanceIdArg == null) { + throw new NullPointerException( + "javaScriptChannelInstanceIdArg unexpectedly null."); + } + api.removeJavaScriptChannel( + instanceIdArg.longValue(), javaScriptChannelInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.setDownloadListener", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number listenerInstanceIdArg = (Number) args.get(1); + if (listenerInstanceIdArg == null) { + throw new NullPointerException("listenerInstanceIdArg unexpectedly null."); + } + api.setDownloadListener( + instanceIdArg.longValue(), listenerInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.setWebChromeClient", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number clientInstanceIdArg = (Number) args.get(1); + if (clientInstanceIdArg == null) { + throw new NullPointerException("clientInstanceIdArg unexpectedly null."); + } + api.setWebChromeClient( + instanceIdArg.longValue(), clientInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class WebSettingsHostApiCodec extends StandardMessageCodec { + public static final WebSettingsHostApiCodec INSTANCE = new WebSettingsHostApiCodec(); + + private WebSettingsHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface WebSettingsHostApi { + void create(Long instanceId, Long webViewInstanceId); + + void dispose(Long instanceId); + + void setDomStorageEnabled(Long instanceId, Boolean flag); + + void setJavaScriptCanOpenWindowsAutomatically(Long instanceId, Boolean flag); + + void setSupportMultipleWindows(Long instanceId, Boolean support); + + void setJavaScriptEnabled(Long instanceId, Boolean flag); + + void setUserAgentString(Long instanceId, String userAgentString); + + void setMediaPlaybackRequiresUserGesture(Long instanceId, Boolean require); + + void setSupportZoom(Long instanceId, Boolean support); + + void setLoadWithOverviewMode(Long instanceId, Boolean overview); + + void setUseWideViewPort(Long instanceId, Boolean use); + + void setDisplayZoomControls(Long instanceId, Boolean enabled); + + void setBuiltInZoomControls(Long instanceId, Boolean enabled); + + /** The codec used by WebSettingsHostApi. */ + static MessageCodec getCodec() { + return WebSettingsHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `WebSettingsHostApi` to handle messages through the `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, WebSettingsHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebSettingsHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number webViewInstanceIdArg = (Number) args.get(1); + if (webViewInstanceIdArg == null) { + throw new NullPointerException("webViewInstanceIdArg unexpectedly null."); + } + api.create(instanceIdArg.longValue(), webViewInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebSettingsHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean flagArg = (Boolean) args.get(1); + if (flagArg == null) { + throw new NullPointerException("flagArg unexpectedly null."); + } + api.setDomStorageEnabled(instanceIdArg.longValue(), flagArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean flagArg = (Boolean) args.get(1); + if (flagArg == null) { + throw new NullPointerException("flagArg unexpectedly null."); + } + api.setJavaScriptCanOpenWindowsAutomatically(instanceIdArg.longValue(), flagArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean supportArg = (Boolean) args.get(1); + if (supportArg == null) { + throw new NullPointerException("supportArg unexpectedly null."); + } + api.setSupportMultipleWindows(instanceIdArg.longValue(), supportArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean flagArg = (Boolean) args.get(1); + if (flagArg == null) { + throw new NullPointerException("flagArg unexpectedly null."); + } + api.setJavaScriptEnabled(instanceIdArg.longValue(), flagArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String userAgentStringArg = (String) args.get(1); + if (userAgentStringArg == null) { + throw new NullPointerException("userAgentStringArg unexpectedly null."); + } + api.setUserAgentString(instanceIdArg.longValue(), userAgentStringArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean requireArg = (Boolean) args.get(1); + if (requireArg == null) { + throw new NullPointerException("requireArg unexpectedly null."); + } + api.setMediaPlaybackRequiresUserGesture(instanceIdArg.longValue(), requireArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean supportArg = (Boolean) args.get(1); + if (supportArg == null) { + throw new NullPointerException("supportArg unexpectedly null."); + } + api.setSupportZoom(instanceIdArg.longValue(), supportArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean overviewArg = (Boolean) args.get(1); + if (overviewArg == null) { + throw new NullPointerException("overviewArg unexpectedly null."); + } + api.setLoadWithOverviewMode(instanceIdArg.longValue(), overviewArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean useArg = (Boolean) args.get(1); + if (useArg == null) { + throw new NullPointerException("useArg unexpectedly null."); + } + api.setUseWideViewPort(instanceIdArg.longValue(), useArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean enabledArg = (Boolean) args.get(1); + if (enabledArg == null) { + throw new NullPointerException("enabledArg unexpectedly null."); + } + api.setDisplayZoomControls(instanceIdArg.longValue(), enabledArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean enabledArg = (Boolean) args.get(1); + if (enabledArg == null) { + throw new NullPointerException("enabledArg unexpectedly null."); + } + api.setBuiltInZoomControls(instanceIdArg.longValue(), enabledArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class JavaScriptChannelHostApiCodec extends StandardMessageCodec { + public static final JavaScriptChannelHostApiCodec INSTANCE = + new JavaScriptChannelHostApiCodec(); + + private JavaScriptChannelHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface JavaScriptChannelHostApi { + void create(Long instanceId, String channelName); + + void dispose(Long instanceId); + + /** The codec used by JavaScriptChannelHostApi. */ + static MessageCodec getCodec() { + return JavaScriptChannelHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `JavaScriptChannelHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, JavaScriptChannelHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.JavaScriptChannelHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + String channelNameArg = (String) args.get(1); + if (channelNameArg == null) { + throw new NullPointerException("channelNameArg unexpectedly null."); + } + api.create(instanceIdArg.longValue(), channelNameArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.JavaScriptChannelHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class JavaScriptChannelFlutterApiCodec extends StandardMessageCodec { + public static final JavaScriptChannelFlutterApiCodec INSTANCE = + new JavaScriptChannelFlutterApiCodec(); + + private JavaScriptChannelFlutterApiCodec() {} + } + + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class JavaScriptChannelFlutterApi { + private final BinaryMessenger binaryMessenger; + + public JavaScriptChannelFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + + static MessageCodec getCodec() { + return JavaScriptChannelFlutterApiCodec.INSTANCE; + } + + public void postMessage(Long instanceIdArg, String messageArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, messageArg)), + channelReply -> { + callback.reply(null); + }); + } + } + + private static class WebViewClientHostApiCodec extends StandardMessageCodec { + public static final WebViewClientHostApiCodec INSTANCE = new WebViewClientHostApiCodec(); + + private WebViewClientHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface WebViewClientHostApi { + void create(Long instanceId, Boolean shouldOverrideUrlLoading); + + void dispose(Long instanceId); + + /** The codec used by WebViewClientHostApi. */ + static MessageCodec getCodec() { + return WebViewClientHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `WebViewClientHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, WebViewClientHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewClientHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Boolean shouldOverrideUrlLoadingArg = (Boolean) args.get(1); + if (shouldOverrideUrlLoadingArg == null) { + throw new NullPointerException( + "shouldOverrideUrlLoadingArg unexpectedly null."); + } + api.create(instanceIdArg.longValue(), shouldOverrideUrlLoadingArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewClientHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class WebViewClientFlutterApiCodec extends StandardMessageCodec { + public static final WebViewClientFlutterApiCodec INSTANCE = new WebViewClientFlutterApiCodec(); + + private WebViewClientFlutterApiCodec() {} + + @Override + protected Object readValueOfType(byte type, ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return WebResourceErrorData.fromMap((Map) readValue(buffer)); + + case (byte) 129: + return WebResourceRequestData.fromMap((Map) readValue(buffer)); + + case (byte) 130: + return WebResourceRequestData.fromMap((Map) readValue(buffer)); + + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(ByteArrayOutputStream stream, Object value) { + if (value instanceof WebResourceErrorData) { + stream.write(128); + writeValue(stream, ((WebResourceErrorData) value).toMap()); + } else if (value instanceof WebResourceRequestData) { + stream.write(129); + writeValue(stream, ((WebResourceRequestData) value).toMap()); + } else if (value instanceof WebResourceRequestData) { + stream.write(130); + writeValue(stream, ((WebResourceRequestData) value).toMap()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class WebViewClientFlutterApi { + private final BinaryMessenger binaryMessenger; + + public WebViewClientFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + + static MessageCodec getCodec() { + return WebViewClientFlutterApiCodec.INSTANCE; + } + + public void onPageStarted( + Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)), + channelReply -> { + callback.reply(null); + }); + } + + public void onPageFinished( + Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)), + channelReply -> { + callback.reply(null); + }); + } + + public void onReceivedRequestError( + Long instanceIdArg, + Long webViewInstanceIdArg, + WebResourceRequestData requestArg, + WebResourceErrorData errorArg, + Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError", + getCodec()); + channel.send( + new ArrayList( + Arrays.asList(instanceIdArg, webViewInstanceIdArg, requestArg, errorArg)), + channelReply -> { + callback.reply(null); + }); + } + + public void onReceivedError( + Long instanceIdArg, + Long webViewInstanceIdArg, + Long errorCodeArg, + String descriptionArg, + String failingUrlArg, + Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError", + getCodec()); + channel.send( + new ArrayList( + Arrays.asList( + instanceIdArg, + webViewInstanceIdArg, + errorCodeArg, + descriptionArg, + failingUrlArg)), + channelReply -> { + callback.reply(null); + }); + } + + public void requestLoading( + Long instanceIdArg, + Long webViewInstanceIdArg, + WebResourceRequestData requestArg, + Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg, requestArg)), + channelReply -> { + callback.reply(null); + }); + } + + public void urlLoading( + Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading", getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)), + channelReply -> { + callback.reply(null); + }); + } + } + + private static class DownloadListenerHostApiCodec extends StandardMessageCodec { + public static final DownloadListenerHostApiCodec INSTANCE = new DownloadListenerHostApiCodec(); + + private DownloadListenerHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface DownloadListenerHostApi { + void create(Long instanceId); + + void dispose(Long instanceId); + + /** The codec used by DownloadListenerHostApi. */ + static MessageCodec getCodec() { + return DownloadListenerHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `DownloadListenerHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, DownloadListenerHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.DownloadListenerHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.create(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.DownloadListenerHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class DownloadListenerFlutterApiCodec extends StandardMessageCodec { + public static final DownloadListenerFlutterApiCodec INSTANCE = + new DownloadListenerFlutterApiCodec(); + + private DownloadListenerFlutterApiCodec() {} + } + + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class DownloadListenerFlutterApi { + private final BinaryMessenger binaryMessenger; + + public DownloadListenerFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + + static MessageCodec getCodec() { + return DownloadListenerFlutterApiCodec.INSTANCE; + } + + public void onDownloadStart( + Long instanceIdArg, + String urlArg, + String userAgentArg, + String contentDispositionArg, + String mimetypeArg, + Long contentLengthArg, + Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart", + getCodec()); + channel.send( + new ArrayList( + Arrays.asList( + instanceIdArg, + urlArg, + userAgentArg, + contentDispositionArg, + mimetypeArg, + contentLengthArg)), + channelReply -> { + callback.reply(null); + }); + } + } + + private static class WebChromeClientHostApiCodec extends StandardMessageCodec { + public static final WebChromeClientHostApiCodec INSTANCE = new WebChromeClientHostApiCodec(); + + private WebChromeClientHostApiCodec() {} + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface WebChromeClientHostApi { + void create(Long instanceId, Long webViewClientInstanceId); + + void dispose(Long instanceId); + + /** The codec used by WebChromeClientHostApi. */ + static MessageCodec getCodec() { + return WebChromeClientHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `WebChromeClientHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, WebChromeClientHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebChromeClientHostApi.create", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number webViewClientInstanceIdArg = (Number) args.get(1); + if (webViewClientInstanceIdArg == null) { + throw new NullPointerException("webViewClientInstanceIdArg unexpectedly null."); + } + api.create(instanceIdArg.longValue(), webViewClientInstanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebChromeClientHostApi.dispose", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + api.dispose(instanceIdArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class WebChromeClientFlutterApiCodec extends StandardMessageCodec { + public static final WebChromeClientFlutterApiCodec INSTANCE = + new WebChromeClientFlutterApiCodec(); + + private WebChromeClientFlutterApiCodec() {} + } + + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class WebChromeClientFlutterApi { + private final BinaryMessenger binaryMessenger; + + public WebChromeClientFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + + static MessageCodec getCodec() { + return WebChromeClientFlutterApiCodec.INSTANCE; + } + + public void onProgressChanged( + Long instanceIdArg, Long webViewInstanceIdArg, Long progressArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(instanceIdArg, webViewInstanceIdArg, progressArg)), + channelReply -> { + callback.reply(null); + }); + } + } + + private static Map wrapError(Throwable exception) { + Map errorMap = new HashMap<>(); + errorMap.put("message", exception.toString()); + errorMap.put("code", exception.getClass().getSimpleName()); + errorMap.put("details", null); + return errorMap; + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java index 51b2a3809fff..0a4cb3effd29 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java @@ -25,7 +25,7 @@ * *

See also {@link ThreadedInputConnectionProxyAdapterView}. */ -final class InputAwareWebView extends WebView { +class InputAwareWebView extends WebView { private static final String TAG = "InputAwareWebView"; private View threadedInputConnectionProxyView; private ThreadedInputConnectionProxyAdapterView proxyAdapterView; diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java new file mode 100644 index 000000000000..bfa7d6f17345 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java @@ -0,0 +1,39 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.util.LongSparseArray; +import java.util.HashMap; +import java.util.Map; + +class InstanceManager { + private final LongSparseArray instanceIdsToInstances = new LongSparseArray<>(); + private final Map instancesToInstanceIds = new HashMap<>(); + + /** Add a new instance with instanceId. */ + void addInstance(Object instance, long instanceId) { + instancesToInstanceIds.put(instance, instanceId); + instanceIdsToInstances.append(instanceId, instance); + } + + /** Remove the instance from the manager. */ + void removeInstance(long instanceId) { + final Object instance = instanceIdsToInstances.get(instanceId); + if (instance != null) { + instanceIdsToInstances.remove(instanceId); + instancesToInstanceIds.remove(instance); + } + } + + /** Retrieve the Object paired with instanceId. */ + Object getInstance(long instanceId) { + return instanceIdsToInstances.get(instanceId); + } + + /** Retrieve the instanceId paired with instance. */ + Long getInstanceId(Object instance) { + return instancesToInstanceIds.get(instance); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java index 4d596351b3d0..2f987c0f86b3 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java @@ -19,7 +19,7 @@ */ class JavaScriptChannel { private final MethodChannel methodChannel; - private final String javaScriptChannelName; + final String javaScriptChannelName; private final Handler platformThreadHandler; /** diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannelHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannelHostApiImpl.java new file mode 100644 index 000000000000..2d42d952955c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannelHostApiImpl.java @@ -0,0 +1,61 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.os.Handler; +import android.os.Looper; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.JavaScriptChannelFlutterApi; + +class JavaScriptChannelHostApiImpl implements GeneratedAndroidWebView.JavaScriptChannelHostApi { + private final InstanceManager instanceManager; + private final JavaScriptChannelCreator javaScriptChannelCreator; + private final JavaScriptChannelFlutterApi javaScriptChannelFlutterApi; + private final Handler platformThreadHandler; + + static class JavaScriptChannelCreator { + JavaScriptChannel createJavaScriptChannel( + Long instanceId, + JavaScriptChannelFlutterApi javaScriptChannelFlutterApi, + String channelName, + Handler platformThreadHandler) { + return new JavaScriptChannel(null, channelName, platformThreadHandler) { + @Override + public void postMessage(String message) { + final Runnable postMessageRunnable = + () -> javaScriptChannelFlutterApi.postMessage(instanceId, message, reply -> {}); + if (platformThreadHandler.getLooper() == Looper.myLooper()) { + postMessageRunnable.run(); + } else { + platformThreadHandler.post(postMessageRunnable); + } + } + }; + } + } + + JavaScriptChannelHostApiImpl( + InstanceManager instanceManager, + JavaScriptChannelCreator javaScriptChannelCreator, + JavaScriptChannelFlutterApi javaScriptChannelFlutterApi, + Handler platformThreadHandler) { + this.instanceManager = instanceManager; + this.javaScriptChannelCreator = javaScriptChannelCreator; + this.javaScriptChannelFlutterApi = javaScriptChannelFlutterApi; + this.platformThreadHandler = platformThreadHandler; + } + + @Override + public void create(Long instanceId, String channelName) { + final JavaScriptChannel javaScriptChannel = + javaScriptChannelCreator.createJavaScriptChannel( + instanceId, javaScriptChannelFlutterApi, channelName, platformThreadHandler); + instanceManager.addInstance(javaScriptChannel, instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java new file mode 100644 index 000000000000..32f8fcbdeed9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebChromeClientHostApiImpl.java @@ -0,0 +1,92 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.os.Build; +import android.os.Message; +import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebChromeClientFlutterApi; + +class WebChromeClientHostApiImpl implements GeneratedAndroidWebView.WebChromeClientHostApi { + private final InstanceManager instanceManager; + private final WebChromeClientCreator webChromeClientCreator; + private final WebChromeClientFlutterApi webChromeClientFlutterApi; + + static class WebChromeClientCreator { + WebChromeClient createWebChromeClient( + Long instanceId, + InstanceManager instanceManager, + WebViewClient webViewClient, + WebChromeClientFlutterApi webChromeClientFlutterApi) { + return new WebChromeClient() { + // Verifies that a url opened by `Window.open` has a secure url. + @Override + public boolean onCreateWindow( + final WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { + final WebViewClient newWindowWebViewClient = + new WebViewClient() { + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public boolean shouldOverrideUrlLoading( + @NonNull WebView view, @NonNull WebResourceRequest request) { + webViewClient.shouldOverrideUrlLoading(view, request); + return true; + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + webViewClient.shouldOverrideUrlLoading(view, url); + return true; + } + }; + + final WebView newWebView = new WebView(view.getContext()); + newWebView.setWebViewClient(newWindowWebViewClient); + + final WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; + transport.setWebView(newWebView); + resultMsg.sendToTarget(); + + return true; + } + + @Override + public void onProgressChanged(WebView view, int progress) { + webChromeClientFlutterApi.onProgressChanged( + instanceId, instanceManager.getInstanceId(view), (long) progress, reply -> {}); + } + }; + } + } + + WebChromeClientHostApiImpl( + InstanceManager instanceManager, + WebChromeClientCreator webChromeClientCreator, + WebChromeClientFlutterApi webChromeClientFlutterApi) { + this.instanceManager = instanceManager; + this.webChromeClientCreator = webChromeClientCreator; + this.webChromeClientFlutterApi = webChromeClientFlutterApi; + } + + @Override + public void create(Long instanceId, Long webViewClientInstanceId) { + final WebViewClient webViewClient = + (WebViewClient) instanceManager.getInstance(webViewClientInstanceId); + final WebChromeClient webChromeClient = + webChromeClientCreator.createWebChromeClient( + instanceId, instanceManager, webViewClient, webChromeClientFlutterApi); + instanceManager.addInstance(webChromeClient, instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java new file mode 100644 index 000000000000..e70a867c23ff --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java @@ -0,0 +1,101 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.webkit.WebSettings; +import android.webkit.WebView; + +class WebSettingsHostApiImpl implements GeneratedAndroidWebView.WebSettingsHostApi { + private final InstanceManager instanceManager; + private final WebSettingsCreator webSettingsCreator; + + static class WebSettingsCreator { + WebSettings createWebSettings(WebView webView) { + return webView.getSettings(); + } + } + + WebSettingsHostApiImpl(InstanceManager instanceManager, WebSettingsCreator webSettingsCreator) { + this.instanceManager = instanceManager; + this.webSettingsCreator = webSettingsCreator; + } + + @Override + public void create(Long instanceId, Long webViewInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(webViewInstanceId); + instanceManager.addInstance(webSettingsCreator.createWebSettings(webView), instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } + + @Override + public void setDomStorageEnabled(Long instanceId, Boolean flag) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setDomStorageEnabled(flag); + } + + @Override + public void setJavaScriptCanOpenWindowsAutomatically(Long instanceId, Boolean flag) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setJavaScriptCanOpenWindowsAutomatically(flag); + } + + @Override + public void setSupportMultipleWindows(Long instanceId, Boolean support) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setSupportMultipleWindows(support); + } + + @Override + public void setJavaScriptEnabled(Long instanceId, Boolean flag) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setJavaScriptEnabled(flag); + } + + @Override + public void setUserAgentString(Long instanceId, String userAgentString) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setUserAgentString(userAgentString); + } + + @Override + public void setMediaPlaybackRequiresUserGesture(Long instanceId, Boolean require) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setMediaPlaybackRequiresUserGesture(require); + } + + @Override + public void setSupportZoom(Long instanceId, Boolean support) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setSupportZoom(support); + } + + @Override + public void setLoadWithOverviewMode(Long instanceId, Boolean overview) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setLoadWithOverviewMode(overview); + } + + @Override + public void setUseWideViewPort(Long instanceId, Boolean use) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setUseWideViewPort(use); + } + + @Override + public void setDisplayZoomControls(Long instanceId, Boolean enabled) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setDisplayZoomControls(enabled); + } + + @Override + public void setBuiltInZoomControls(Long instanceId, Boolean enabled) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setBuiltInZoomControls(enabled); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java new file mode 100644 index 000000000000..4d17eb129db8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewClientHostApiImpl.java @@ -0,0 +1,239 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.graphics.Bitmap; +import android.os.Build; +import android.view.KeyEvent; +import android.webkit.WebResourceError; +import android.webkit.WebResourceRequest; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.webkit.WebResourceErrorCompat; +import androidx.webkit.WebViewClientCompat; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewClientFlutterApi; + +class WebViewClientHostApiImpl implements GeneratedAndroidWebView.WebViewClientHostApi { + private final InstanceManager instanceManager; + private final WebViewClientCreator webViewClientCreator; + private final WebViewClientFlutterApi webViewClientFlutterApi; + + @RequiresApi(api = Build.VERSION_CODES.M) + static GeneratedAndroidWebView.WebResourceErrorData createWebResourceErrorData( + WebResourceError error) { + final GeneratedAndroidWebView.WebResourceErrorData errorData = + new GeneratedAndroidWebView.WebResourceErrorData(); + errorData.setErrorCode((long) error.getErrorCode()); + errorData.setDescription(error.getDescription().toString()); + + return errorData; + } + + @SuppressLint("RequiresFeature") + static GeneratedAndroidWebView.WebResourceErrorData createWebResourceErrorData( + WebResourceErrorCompat error) { + final GeneratedAndroidWebView.WebResourceErrorData errorData = + new GeneratedAndroidWebView.WebResourceErrorData(); + errorData.setErrorCode((long) error.getErrorCode()); + errorData.setDescription(error.getDescription().toString()); + + return errorData; + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + static GeneratedAndroidWebView.WebResourceRequestData createWebResourceRequestData( + WebResourceRequest request) { + final GeneratedAndroidWebView.WebResourceRequestData requestData = + new GeneratedAndroidWebView.WebResourceRequestData(); + requestData.setUrl(request.getUrl().toString()); + requestData.setIsForMainFrame(request.isForMainFrame()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + requestData.setIsRedirect(request.isRedirect()); + } + requestData.setHasGesture(request.hasGesture()); + requestData.setMethod(request.getMethod()); + requestData.setRequestHeaders(request.getRequestHeaders()); + + return requestData; + } + + static class WebViewClientCreator { + WebViewClient createWebViewClient( + Long instanceId, + InstanceManager instanceManager, + Boolean shouldOverrideUrlLoading, + WebViewClientFlutterApi webViewClientFlutterApi) { + // WebViewClientCompat is used to get + // shouldOverrideUrlLoading(WebView view, WebResourceRequest request) + // invoked by the webview on older Android devices, without it pages that use iframes will + // be broken when a navigationDelegate is set on Android version earlier than N. + // + // However, this if statement attempts to avoid using WebViewClientCompat on versions >= N due + // to bug https://bugs.chromium.org/p/chromium/issues/detail?id=925887. Also, see + // https://github.com/flutter/flutter/issues/29446. + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return new WebViewClient() { + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + webViewClientFlutterApi.onPageStarted( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + } + + @Override + public void onPageFinished(WebView view, String url) { + webViewClientFlutterApi.onPageFinished( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + } + + @Override + public void onReceivedError( + WebView view, WebResourceRequest request, WebResourceError error) { + webViewClientFlutterApi.onReceivedRequestError( + instanceId, + instanceManager.getInstanceId(view), + createWebResourceRequestData(request), + createWebResourceErrorData(error), + reply -> {}); + } + + @SuppressWarnings("deprecation") + @Override + public void onReceivedError( + WebView view, int errorCode, String description, String failingUrl) { + webViewClientFlutterApi.onReceivedError( + instanceId, + instanceManager.getInstanceId(view), + (long) errorCode, + description, + failingUrl, + reply -> {}); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + webViewClientFlutterApi.requestLoading( + instanceId, + instanceManager.getInstanceId(view), + createWebResourceRequestData(request), + reply -> {}); + return shouldOverrideUrlLoading; + } + + @SuppressWarnings("deprecation") + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + webViewClientFlutterApi.urlLoading( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + return shouldOverrideUrlLoading; + } + + @Override + public void onUnhandledKeyEvent(WebView view, KeyEvent event) { + // Deliberately empty. Occasionally the webview will mark events as having failed to be + // handled even though they were handled. We don't want to propagate those as they're not + // truly lost. + } + }; + } else { + return new WebViewClientCompat() { + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + webViewClientFlutterApi.onPageStarted( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + } + + @Override + public void onPageFinished(WebView view, String url) { + webViewClientFlutterApi.onPageFinished( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + } + + // This method is only called when the WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR feature is + // enabled. The deprecated method is called when a device doesn't support this. + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @SuppressLint("RequiresFeature") + @Override + public void onReceivedError( + @NonNull WebView view, + @NonNull WebResourceRequest request, + @NonNull WebResourceErrorCompat error) { + webViewClientFlutterApi.onReceivedRequestError( + instanceId, + instanceManager.getInstanceId(view), + createWebResourceRequestData(request), + createWebResourceErrorData(error), + reply -> {}); + } + + @SuppressWarnings("deprecation") + @Override + public void onReceivedError( + WebView view, int errorCode, String description, String failingUrl) { + webViewClientFlutterApi.onReceivedError( + instanceId, + instanceManager.getInstanceId(view), + (long) errorCode, + description, + failingUrl, + reply -> {}); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public boolean shouldOverrideUrlLoading( + @NonNull WebView view, @NonNull WebResourceRequest request) { + webViewClientFlutterApi.requestLoading( + instanceId, + instanceManager.getInstanceId(view), + createWebResourceRequestData(request), + reply -> {}); + return shouldOverrideUrlLoading; + } + + @SuppressWarnings("deprecation") + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + webViewClientFlutterApi.urlLoading( + instanceId, instanceManager.getInstanceId(view), url, reply -> {}); + return shouldOverrideUrlLoading; + } + + @Override + public void onUnhandledKeyEvent(WebView view, KeyEvent event) { + // Deliberately empty. Occasionally the webview will mark events as having failed to be + // handled even though they were handled. We don't want to propagate those as they're not + // truly lost. + } + }; + } + } + } + + WebViewClientHostApiImpl( + InstanceManager instanceManager, + WebViewClientCreator webViewClientCreator, + WebViewClientFlutterApi webViewClientFlutterApi) { + this.instanceManager = instanceManager; + this.webViewClientCreator = webViewClientCreator; + this.webViewClientFlutterApi = webViewClientFlutterApi; + } + + @Override + public void create(Long instanceId, Boolean shouldOverrideUrlLoading) { + final WebViewClient webViewClient = + webViewClientCreator.createWebViewClient( + instanceId, instanceManager, shouldOverrideUrlLoading, webViewClientFlutterApi); + instanceManager.addInstance(webViewClient, instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java new file mode 100644 index 000000000000..35bdc608d6ff --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java @@ -0,0 +1,233 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import android.content.Context; +import android.view.View; +import android.webkit.DownloadListener; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import androidx.annotation.NonNull; +import io.flutter.plugin.platform.PlatformView; +import java.util.Map; + +class WebViewHostApiImpl implements GeneratedAndroidWebView.WebViewHostApi { + private final InstanceManager instanceManager; + private final WebViewProxy webViewProxy; + private final Context context; + + static class WebViewProxy { + WebView createWebView(Context context) { + return new WebViewPlatformView(context); + } + + WebView createInputAwareWebView(Context context) { + return new InputAwareWebViewPlatformView(context, null); + } + + void setWebContentsDebuggingEnabled(boolean enabled) { + WebView.setWebContentsDebuggingEnabled(enabled); + } + } + + private static class WebViewPlatformView extends WebView implements PlatformView { + public WebViewPlatformView(Context context) { + super(context); + } + + @Override + public View getView() { + return this; + } + + @Override + public void dispose() { + destroy(); + } + } + + private static class InputAwareWebViewPlatformView extends InputAwareWebView + implements PlatformView { + InputAwareWebViewPlatformView(Context context, View containerView) { + super(context, containerView); + } + + @Override + public View getView() { + return this; + } + + @Override + public void onFlutterViewAttached(@NonNull View flutterView) { + setContainerView(flutterView); + } + + @Override + public void onFlutterViewDetached() { + setContainerView(null); + } + + @Override + public void dispose() { + dispose(); + destroy(); + } + + @Override + public void onInputConnectionLocked() { + lockInputConnection(); + } + + @Override + public void onInputConnectionUnlocked() { + unlockInputConnection(); + } + } + + WebViewHostApiImpl(InstanceManager instanceManager, WebViewProxy webViewProxy, Context context) { + this.instanceManager = instanceManager; + this.webViewProxy = webViewProxy; + this.context = context; + } + + @Override + public void create(Long instanceId, Boolean useHybridComposition) { + final WebView webView = + useHybridComposition + ? webViewProxy.createWebView(context) + : webViewProxy.createInputAwareWebView(context); + instanceManager.addInstance(webView, instanceId); + } + + @Override + public void dispose(Long instanceId) { + instanceManager.removeInstance(instanceId); + } + + @Override + public void loadUrl(Long instanceId, String url, Map headers) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.loadUrl(url, headers); + } + + @Override + public String getUrl(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return webView.getUrl(); + } + + @Override + public Boolean canGoBack(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return webView.canGoBack(); + } + + @Override + public Boolean canGoForward(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return webView.canGoForward(); + } + + @Override + public void goBack(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.goBack(); + } + + @Override + public void goForward(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.goForward(); + } + + @Override + public void reload(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.reload(); + } + + @Override + public void clearCache(Long instanceId, Boolean includeDiskFiles) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.clearCache(includeDiskFiles); + } + + @Override + public void evaluateJavascript( + Long instanceId, String javascriptString, GeneratedAndroidWebView.Result result) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.evaluateJavascript(javascriptString, result::success); + } + + @Override + public String getTitle(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return webView.getTitle(); + } + + @Override + public void scrollTo(Long instanceId, Long x, Long y) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.scrollTo(x.intValue(), y.intValue()); + } + + @Override + public void scrollBy(Long instanceId, Long x, Long y) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.scrollBy(x.intValue(), y.intValue()); + } + + @Override + public Long getScrollX(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return (long) webView.getScrollX(); + } + + @Override + public Long getScrollY(Long instanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + return (long) webView.getScrollY(); + } + + @Override + public void setWebContentsDebuggingEnabled(Boolean enabled) { + webViewProxy.setWebContentsDebuggingEnabled(enabled); + } + + @Override + public void setWebViewClient(Long instanceId, Long webViewClientInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.setWebViewClient((WebViewClient) instanceManager.getInstance(webViewClientInstanceId)); + } + + @Override + public void addJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + final JavaScriptChannel javaScriptChannel = + (JavaScriptChannel) instanceManager.getInstance(javaScriptChannelInstanceId); + webView.addJavascriptInterface(javaScriptChannel, javaScriptChannel.javaScriptChannelName); + } + + @Override + public void removeJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + final JavaScriptChannel javaScriptChannel = + (JavaScriptChannel) instanceManager.getInstance(javaScriptChannelInstanceId); + webView.removeJavascriptInterface(javaScriptChannel.javaScriptChannelName); + } + + @Override + public void setDownloadListener(Long instanceId, Long listenerInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.setDownloadListener((DownloadListener) instanceManager.getInstance(listenerInstanceId)); + } + + @Override + public void setWebChromeClient(Long instanceId, Long clientInstanceId) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + webView.setWebChromeClient((WebChromeClient) instanceManager.getInstance(instanceId)); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/android/util/LongSparseArray.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/android/util/LongSparseArray.java new file mode 100644 index 000000000000..4a90e394e259 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/android/util/LongSparseArray.java @@ -0,0 +1,29 @@ +// 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. + +package android.util; + +import java.util.HashMap; + +// Creates an implementation of LongSparseArray that can be used with unittests and the JVM. +// Typically android.util.LongSparseArray does nothing when not used with an Android environment. +public class LongSparseArray { + private final HashMap mHashMap; + + public LongSparseArray() { + mHashMap = new HashMap<>(); + } + + public void append(long key, E value) { + mHashMap.put(key, value); + } + + public E get(long key) { + return mHashMap.get(key); + } + + public void remove(long key) { + mHashMap.remove(key); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java new file mode 100644 index 000000000000..5ba073c7f418 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java @@ -0,0 +1,65 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.webkit.DownloadListener; +import io.flutter.plugins.webviewflutter.DownloadListenerHostApiImpl.DownloadListenerCreator; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.DownloadListenerFlutterApi; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class DownloadListenerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public DownloadListenerFlutterApi mockFlutterApi; + + InstanceManager testInstanceManager; + DownloadListenerHostApiImpl testHostApiImpl; + DownloadListener testDownloadListener; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + + final DownloadListenerCreator downloadListenerCreator = + new DownloadListenerCreator() { + @Override + DownloadListener createDownloadListener( + Long instanceId, DownloadListenerFlutterApi downloadListenerFlutterApi) { + testDownloadListener = + super.createDownloadListener(instanceId, downloadListenerFlutterApi); + return testDownloadListener; + } + }; + + testHostApiImpl = + new DownloadListenerHostApiImpl( + testInstanceManager, downloadListenerCreator, mockFlutterApi); + testHostApiImpl.create(0L); + } + + @Test + public void postMessage() { + testDownloadListener.onDownloadStart( + "https://www.google.com", "userAgent", "contentDisposition", "mimetype", 54); + verify(mockFlutterApi) + .onDownloadStart( + eq(0L), + eq("https://www.google.com"), + eq("userAgent"), + eq("contentDisposition"), + eq("mimetype"), + eq(54L), + any()); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java new file mode 100644 index 000000000000..697ea0b70b90 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java @@ -0,0 +1,60 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.os.Handler; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.JavaScriptChannelFlutterApi; +import io.flutter.plugins.webviewflutter.JavaScriptChannelHostApiImpl.JavaScriptChannelCreator; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class JavaScriptChannelTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public GeneratedAndroidWebView.JavaScriptChannelFlutterApi mockFlutterApi; + + InstanceManager testInstanceManager; + JavaScriptChannelHostApiImpl testHostApiImpl; + JavaScriptChannel testJavaScriptChannel; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + + final JavaScriptChannelCreator javaScriptChannelCreator = + new JavaScriptChannelCreator() { + @Override + JavaScriptChannel createJavaScriptChannel( + Long instanceId, + JavaScriptChannelFlutterApi javaScriptChannelFlutterApi, + String channelName, + Handler platformThreadHandler) { + testJavaScriptChannel = + super.createJavaScriptChannel( + instanceId, javaScriptChannelFlutterApi, channelName, platformThreadHandler); + return testJavaScriptChannel; + } + }; + + testHostApiImpl = + new JavaScriptChannelHostApiImpl( + testInstanceManager, javaScriptChannelCreator, mockFlutterApi, new Handler()); + testHostApiImpl.create(0L, "aChannelName"); + } + + @Test + public void postMessage() { + testJavaScriptChannel.postMessage("A message post."); + verify(mockFlutterApi).postMessage(eq(0L), eq("A message post."), any()); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java new file mode 100644 index 000000000000..5ab3ab10fe03 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java @@ -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. + +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebChromeClientFlutterApi; +import io.flutter.plugins.webviewflutter.WebChromeClientHostApiImpl.WebChromeClientCreator; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class WebChromeClientTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebChromeClientFlutterApi mockFlutterApi; + + @Mock public WebView mockWebView; + + @Mock public WebViewClient mockWebViewClient; + + InstanceManager testInstanceManager; + WebChromeClientHostApiImpl testHostApiImpl; + WebChromeClient testWebChromeClient; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + testInstanceManager.addInstance(mockWebView, 0L); + testInstanceManager.addInstance(mockWebViewClient, 1L); + + final WebChromeClientCreator webChromeClientCreator = + new WebChromeClientCreator() { + @Override + WebChromeClient createWebChromeClient( + Long instanceId, + InstanceManager instanceManager, + WebViewClient webViewClient, + WebChromeClientFlutterApi webChromeClientFlutterApi) { + testWebChromeClient = + super.createWebChromeClient( + instanceId, instanceManager, webViewClient, webChromeClientFlutterApi); + return testWebChromeClient; + } + }; + + testHostApiImpl = + new WebChromeClientHostApiImpl(testInstanceManager, webChromeClientCreator, mockFlutterApi); + testHostApiImpl.create(2L, 1L); + } + + @Test + public void onProgressChanged() { + testWebChromeClient.onProgressChanged(mockWebView, 23); + verify(mockFlutterApi).onProgressChanged(eq(2L), eq(0L), eq(23L), any()); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java new file mode 100644 index 000000000000..8ef32ddcb4ca --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java @@ -0,0 +1,103 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.webkit.WebSettings; +import io.flutter.plugins.webviewflutter.WebSettingsHostApiImpl.WebSettingsCreator; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class WebSettingsTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebSettings mockWebSettings; + + @Mock WebSettingsCreator mockWebSettingsCreator; + + InstanceManager testInstanceManager; + WebSettingsHostApiImpl testHostApiImpl; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + when(mockWebSettingsCreator.createWebSettings(any())).thenReturn(mockWebSettings); + testHostApiImpl = new WebSettingsHostApiImpl(testInstanceManager, mockWebSettingsCreator); + testHostApiImpl.create(0L, 0L); + } + + @Test + public void setDomStorageEnabled() { + testHostApiImpl.setDomStorageEnabled(0L, true); + verify(mockWebSettings).setDomStorageEnabled(true); + } + + @Test + public void setJavaScriptCanOpenWindowsAutomatically() { + testHostApiImpl.setJavaScriptCanOpenWindowsAutomatically(0L, false); + verify(mockWebSettings).setJavaScriptCanOpenWindowsAutomatically(false); + } + + @Test + public void setSupportMultipleWindows() { + testHostApiImpl.setSupportMultipleWindows(0L, true); + verify(mockWebSettings).setSupportMultipleWindows(true); + } + + @Test + public void setJavaScriptEnabled() { + testHostApiImpl.setJavaScriptEnabled(0L, false); + verify(mockWebSettings).setJavaScriptEnabled(false); + } + + @Test + public void setUserAgentString() { + testHostApiImpl.setUserAgentString(0L, "hello"); + verify(mockWebSettings).setUserAgentString("hello"); + } + + @Test + public void setMediaPlaybackRequiresUserGesture() { + testHostApiImpl.setMediaPlaybackRequiresUserGesture(0L, false); + verify(mockWebSettings).setMediaPlaybackRequiresUserGesture(false); + } + + @Test + public void setSupportZoom() { + testHostApiImpl.setSupportZoom(0L, true); + verify(mockWebSettings).setSupportZoom(true); + } + + @Test + public void setLoadWithOverviewMode() { + testHostApiImpl.setLoadWithOverviewMode(0L, false); + verify(mockWebSettings).setLoadWithOverviewMode(false); + } + + @Test + public void setUseWideViewPort() { + testHostApiImpl.setUseWideViewPort(0L, true); + verify(mockWebSettings).setUseWideViewPort(true); + } + + @Test + public void setDisplayZoomControls() { + testHostApiImpl.setDisplayZoomControls(0L, false); + verify(mockWebSettings).setDisplayZoomControls(false); + } + + @Test + public void setBuiltInZoomControls() { + testHostApiImpl.setBuiltInZoomControls(0L, true); + verify(mockWebSettings).setBuiltInZoomControls(true); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java new file mode 100644 index 000000000000..f6d2054564e2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java @@ -0,0 +1,77 @@ +// 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. + +package io.flutter.plugins.webviewflutter; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.webkit.WebView; +import android.webkit.WebViewClient; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewClientFlutterApi; +import io.flutter.plugins.webviewflutter.WebViewClientHostApiImpl.WebViewClientCreator; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class WebViewClientTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebViewClientFlutterApi mockFlutterApi; + + @Mock public WebView mockWebView; + + InstanceManager testInstanceManager; + WebViewClientHostApiImpl testHostApiImpl; + WebViewClient testWebViewClient; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + testInstanceManager.addInstance(mockWebView, 0L); + + final WebViewClientCreator webViewClientCreator = + new WebViewClientCreator() { + @Override + WebViewClient createWebViewClient( + Long instanceId, + InstanceManager instanceManager, + Boolean shouldOverrideUrlLoading, + WebViewClientFlutterApi webViewClientFlutterApi) { + testWebViewClient = + super.createWebViewClient( + instanceId, instanceManager, shouldOverrideUrlLoading, webViewClientFlutterApi); + return testWebViewClient; + } + }; + + testHostApiImpl = + new WebViewClientHostApiImpl(testInstanceManager, webViewClientCreator, mockFlutterApi); + testHostApiImpl.create(1L, true); + } + + @Test + public void onPageStarted() { + testWebViewClient.onPageStarted(mockWebView, "https://www.google.com", null); + verify(mockFlutterApi).onPageStarted(eq(1L), eq(0L), eq("https://www.google.com"), any()); + } + + @Test + public void onReceivedError() { + testWebViewClient.onReceivedError(mockWebView, 32, "description", "https://www.google.com"); + verify(mockFlutterApi) + .onReceivedError( + eq(1L), eq(0L), eq(32L), eq("description"), eq("https://www.google.com"), any()); + } + + @Test + public void urlLoading() { + testWebViewClient.shouldOverrideUrlLoading(mockWebView, "https://www.google.com"); + verify(mockFlutterApi).urlLoading(eq(1L), eq(0L), eq("https://www.google.com"), any()); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java index 131a5a3eb53a..b914ce913e76 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java @@ -5,11 +5,45 @@ package io.flutter.plugins.webviewflutter; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.content.Context; +import android.webkit.DownloadListener; +import android.webkit.ValueCallback; +import android.webkit.WebView; import android.webkit.WebViewClient; +import java.util.HashMap; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class WebViewTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public WebView mockWebView; + + @Mock WebViewHostApiImpl.WebViewProxy mockWebViewProxy; + + @Mock Context mockContext; + + InstanceManager testInstanceManager; + WebViewHostApiImpl testHostApiImpl; + + @Before + public void setUp() { + testInstanceManager = new InstanceManager(); + when(mockWebViewProxy.createWebView(mockContext)).thenReturn(mockWebView); + testHostApiImpl = new WebViewHostApiImpl(testInstanceManager, mockWebViewProxy, mockContext); + testHostApiImpl.create(0L, true); + } + @Test public void errorCodes() { assertEquals( @@ -46,4 +80,143 @@ public void errorCodes() { FlutterWebViewClient.errorCodeToString(WebViewClient.ERROR_UNSUPPORTED_SCHEME), "unsupportedScheme"); } + + @Test + public void loadUrl() { + testHostApiImpl.loadUrl(0L, "https://www.google.com", new HashMap<>()); + verify(mockWebView).loadUrl("https://www.google.com", new HashMap<>()); + } + + @Test + public void getUrl() { + when(mockWebView.getUrl()).thenReturn("https://www.google.com"); + assertEquals(testHostApiImpl.getUrl(0L), "https://www.google.com"); + } + + @Test + public void canGoBack() { + when(mockWebView.canGoBack()).thenReturn(true); + assertEquals(testHostApiImpl.canGoBack(0L), true); + } + + @Test + public void canGoForward() { + when(mockWebView.canGoForward()).thenReturn(false); + assertEquals(testHostApiImpl.canGoForward(0L), false); + } + + @Test + public void goBack() { + testHostApiImpl.goBack(0L); + verify(mockWebView).goBack(); + } + + @Test + public void goForward() { + testHostApiImpl.goForward(0L); + verify(mockWebView).goForward(); + } + + @Test + public void reload() { + testHostApiImpl.reload(0L); + verify(mockWebView).reload(); + } + + @Test + public void clearCache() { + testHostApiImpl.clearCache(0L, false); + verify(mockWebView).clearCache(false); + } + + @Test + public void evaluateJavaScript() { + final String[] successValue = new String[1]; + testHostApiImpl.evaluateJavascript( + 0L, + "2 + 2", + new GeneratedAndroidWebView.Result() { + @Override + public void success(String result) { + successValue[0] = result; + } + + @Override + public void error(Throwable error) {} + }); + + @SuppressWarnings("unchecked") + final ArgumentCaptor> callbackCaptor = + ArgumentCaptor.forClass(ValueCallback.class); + verify(mockWebView).evaluateJavascript(eq("2 + 2"), callbackCaptor.capture()); + + callbackCaptor.getValue().onReceiveValue("da result"); + assertEquals(successValue[0], "da result"); + } + + @Test + public void getTitle() { + when(mockWebView.getTitle()).thenReturn("My title"); + assertEquals(testHostApiImpl.getTitle(0L), "My title"); + } + + @Test + public void scrollTo() { + testHostApiImpl.scrollTo(0L, 12L, 13L); + verify(mockWebView).scrollTo(12, 13); + } + + @Test + public void scrollBy() { + testHostApiImpl.scrollBy(0L, 15L, 23L); + verify(mockWebView).scrollBy(15, 23); + } + + @Test + public void getScrollX() { + when(mockWebView.getScrollX()).thenReturn(55); + assertEquals((long) testHostApiImpl.getScrollX(0L), 55); + } + + @Test + public void getScrollY() { + when(mockWebView.getScrollY()).thenReturn(23); + assertEquals((long) testHostApiImpl.getScrollY(0L), 23); + } + + @Test + public void setWebViewClient() { + final WebViewClient mockWebViewClient = mock(WebViewClient.class); + testInstanceManager.addInstance(mockWebViewClient, 1L); + + testHostApiImpl.setWebViewClient(0L, 1L); + verify(mockWebView).setWebViewClient(mockWebViewClient); + } + + @Test + public void addJavaScriptChannel() { + final JavaScriptChannel javaScriptChannel = new JavaScriptChannel(null, "aName", null); + testInstanceManager.addInstance(javaScriptChannel, 1L); + + testHostApiImpl.addJavaScriptChannel(0L, 1L); + verify(mockWebView).addJavascriptInterface(javaScriptChannel, "aName"); + } + + @Test + public void removeJavaScriptChannel() { + final JavaScriptChannel javaScriptChannel = new JavaScriptChannel(null, "aName", null); + testInstanceManager.addInstance(javaScriptChannel, 1L); + + testHostApiImpl.removeJavaScriptChannel(0L, 1L); + verify(mockWebView).removeJavascriptInterface("aName"); + } + + @Test + public void setDownloadListener() { + final DownloadListener mockDownloadListener = mock(DownloadListener.class); + testInstanceManager.addInstance(mockDownloadListener, 1L); + + testHostApiImpl.setDownloadListener(0L, 1L); + verify(mockWebView).setDownloadListener(mockDownloadListener); + } } diff --git a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh index d866473636cc..30a6918fc922 100755 --- a/packages/webview_flutter/webview_flutter_android/generatePigeons.sh +++ b/packages/webview_flutter/webview_flutter_android/generatePigeons.sh @@ -5,4 +5,6 @@ flutter pub run pigeon \ --input pigeons/android_webview.dart \ --dart_out lib/src/android_webview.pigeon.dart \ ---dart_test_out test/android_webview.pigeon.dart +--dart_test_out test/android_webview.pigeon.dart \ +--java_out android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.Java \ +--java_package io.flutter.plugins.webviewflutter