diff --git a/packages/webview_flutter/webview_flutter/lib/src/legacy/webview.dart b/packages/webview_flutter/webview_flutter/lib/src/legacy/webview.dart index 0dddb2d5214f2d82499c0ac83b2a5ef9b6120aeb..872b4d1d0ced1a5688f6290fd2bbe75903cb4877 100644 --- a/packages/webview_flutter/webview_flutter/lib/src/legacy/webview.dart +++ b/packages/webview_flutter/webview_flutter/lib/src/legacy/webview.dart @@ -14,6 +14,7 @@ import 'package:webview_flutter_android/src/webview_flutter_android_legacy.dart' import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart'; // ignore: implementation_imports import 'package:webview_flutter_wkwebview/src/webview_flutter_wkwebview_legacy.dart'; +import 'package:webview_flutter_ohos/src/webview_flutter_ohos_legacy.dart'; /// Optional callback invoked when a web view is first created. [controller] is /// the [WebViewController] for the created web view. @@ -124,6 +125,8 @@ class WebView extends StatefulWidget { case TargetPlatform.iOS: _platform = CupertinoWebView(); // ignore: no_default_cases + case TargetPlatform.ohos: + _platform = SurfaceOhosWebView(); default: throw UnsupportedError( "Trying to use the default webview implementation for $defaultTargetPlatform but there isn't a default one"); diff --git a/packages/webview_flutter/webview_flutter/lib/src/webview_flutter_legacy.dart b/packages/webview_flutter/webview_flutter/lib/src/webview_flutter_legacy.dart index d040fc2e71d8066b2b85682f93a7cbf8ad71d0b7..9304ba28c27c87ddbc4c0cee0b8bb631c0732e9f 100644 --- a/packages/webview_flutter/webview_flutter/lib/src/webview_flutter_legacy.dart +++ b/packages/webview_flutter/webview_flutter/lib/src/webview_flutter_legacy.dart @@ -4,6 +4,7 @@ export 'package:webview_flutter_android/src/webview_flutter_android_legacy.dart'; export 'package:webview_flutter_wkwebview/src/webview_flutter_wkwebview_legacy.dart'; +export 'package:webview_flutter_ohos/src/webview_flutter_ohos_legacy.dart'; export 'legacy/platform_interface.dart'; export 'legacy/webview.dart'; diff --git a/packages/webview_flutter/webview_flutter/pubspec.yaml b/packages/webview_flutter/webview_flutter/pubspec.yaml index c48857425b2a73639d9215d92cdd747f876a6688..8904781211ab99e6c67cf69b294cc76e11436269 100644 --- a/packages/webview_flutter/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/pubspec.yaml @@ -15,6 +15,8 @@ flutter: default_package: webview_flutter_android ios: default_package: webview_flutter_wkwebview + ohos: + default_package: webview_flutter_ohos dependencies: flutter: @@ -22,6 +24,10 @@ dependencies: webview_flutter_android: ^3.16.0 webview_flutter_platform_interface: ^2.10.0 webview_flutter_wkwebview: ^3.13.0 + webview_flutter_ohos: + git: + url: "https://gitee.com/openharmony-sig/flutter_packages.git" + path: "packages/webview_flutter/webview_flutter_ohos" dev_dependencies: build_runner: ^2.1.5 diff --git a/packages/webview_flutter/webview_flutter_ohos/.gitignore b/packages/webview_flutter/webview_flutter_ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6665baf5ad7de7fd7352c04cfa1b6d9e318a73c9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages + +pubspec.lock +GeneratedPluginRegistrant* +ohos/**/oh_modules +ohos/**.har +ohos/**/BuildProfile.ets +ohos/**/oh-package-lock.json5 diff --git a/packages/webview_flutter/webview_flutter_ohos/AUTHORS b/packages/webview_flutter/webview_flutter_ohos/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..9bc82248cb04d3f2b20f63f89a4455f07c95dadd --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/AUTHORS @@ -0,0 +1,83 @@ +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> +Maurits van Beusekom +Nick Bradshaw +Kai Yu + diff --git a/packages/webview_flutter/webview_flutter_ohos/CHANGELOG.md b/packages/webview_flutter/webview_flutter_ohos/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..2178cd4454c036ea48c56324ceb07b3a909eacb4 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/CHANGELOG.md @@ -0,0 +1,342 @@ +## NEXT + +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 3.14.0 + +* Adds support to show JavaScript dialog. See `AndroidWebViewController.setOnJavaScriptAlertDialog`, `AndroidWebViewController.setOnJavaScriptConfirmDialog` and `AndroidWebViewController.setOnJavaScriptTextInputDialog`. + +## 3.9.3 + +* Fixes bug where the `PlatformWebViewWidget` was rebuilt unnecessarily. + +## 3.9.2 + +* Fixes bug where `PlatformWebViewWidget` doesn't rebuild when the controller or PlatformView + implementation flag changes. + +## 3.9.1 + +* Adjusts SDK checks for better testability. + +## 3.9.0 + +* Adds support for `WebResouceError.url`. + +## 3.8.2 + +* Fixes unawaited_futures violations. + +## 3.8.1 + +* Bumps androidx.webkit:webkit from 1.6.0 to 1.7.0. + +## 3.8.0 + +* Adds support for handling geolocation permissions. See + `AndroidWebViewController.setGeolocationPermissionsPromptCallbacks`. + +## 3.7.1 + +* Removes obsolete null checks on non-nullable values. + +## 3.7.0 + +* Adds support to accept third party cookies. See + `AndroidWebViewCookieManager.setAcceptThirdPartyCookies`. + +## 3.6.3 + +* Updates gradle, AGP and fixes some lint errors. + +## 3.6.2 + +* Fixes compatibility with AGP versions older than 4.2. + +## 3.6.1 + +* Adds a namespace for compatibility with AGP 8.0. + +## 3.6.0 + +* Adds support for `PlatformWebViewController.setOnPlatformPermissionRequest`. + +## 3.5.3 + +* Bumps gradle from 7.2.2 to 8.0.0. + +## 3.5.2 + +* Updates internal Java InstanceManager to only stop finalization callbacks when stopped. + +## 3.5.1 + +* Updates pigeon dev dependency to `9.2.4`. +* Fixes Android lint warnings. + +## 3.5.0 + +* Adds support for `PlatformNavigationDelegate.onUrlChange`. +* Bumps androidx.webkit:webkit from 1.6.0 to 1.6.1. +* Fixes common typos in tests and documentation. + +## 3.4.5 + +* Removes unused internal `WebView` field and Java class. + +## 3.4.4 + +* Fixes a bug where the native `WebView` wouldn't be traversed for autofill automatically. +* Updates minimum Flutter version to 3.3. + +## 3.4.3 + +* Updates internal Java InstanceManager to be cleared on hot restart. + +## 3.4.2 + +* Clarifies explanation of endorsement in README. + +## 3.4.1 + +* Fixes a potential bug where a `WebView` that was not added to the `InstanceManager` could be + returned by a `WebViewClient` or `WebChromeClient`. + +## 3.4.0 + +* Adds support to set text zoom of a page. See `AndroidWebViewController.setTextZoom`. +* Aligns Dart and Flutter SDK constraints. + +## 3.3.2 + +* Resolves compilations warnings. +* Updates compileSdkVersion to 33. +* Bumps androidx.webkit:webkit from 1.5.0 to 1.6.0. + +## 3.3.1 + +* Updates links for the merge of flutter/plugins into flutter/packages. + +## 3.3.0 + +* Adds support to access native `WebView`. + +## 3.2.4 + +* Renames Pigeon output files. + +## 3.2.3 + +* Fixes bug that prevented the web view from being garbage collected. +* Fixes bug causing a `LateInitializationError` when a `PlatformNavigationDelegate` is not provided. + +## 3.2.2 + +* Updates example code for `use_build_context_synchronously` lint. + +## 3.2.1 + +* Updates code for stricter lint checks. + +## 3.2.0 + +* Adds support for handling file selection. See `AndroidWebViewController.setOnShowFileSelector`. +* Updates pigeon dev dependency to `4.2.14`. + +## 3.1.3 + +* Fixes crash when the Java `InstanceManager` was used after plugin was removed from the engine. + +## 3.1.2 + +* Fixes bug where an `AndroidWebViewController` couldn't be reused with a new `WebViewWidget`. + +## 3.1.1 + +* Fixes bug where a `AndroidNavigationDelegate` was required to load a request. + +## 3.1.0 + +* Adds support for selecting Hybrid Composition on versions 23+. Please use + `AndroidWebViewControllerCreationParams.displayWithHybridComposition`. + +## 3.0.0 + +* **BREAKING CHANGE** Updates platform implementation to `2.0.0` release of + `webview_flutter_platform_interface`. See + [webview_flutter](https://pub.dev/packages/webview_flutter/versions/4.0.0) for updated usage. + +## 2.10.4 + +* Updates code for `no_leading_underscores_for_local_identifiers` lint. +* Bumps androidx.annotation from 1.4.0 to 1.5.0. + +## 2.10.3 + +* Updates imports for `prefer_relative_imports`. + +## 2.10.2 + +* Adds a getter to expose the Java InstanceManager. + +## 2.10.1 + +* Adds a method to the `WebView` wrapper to retrieve the X and Y positions simultaneously. +* Removes reference to https://github.com/flutter/flutter/issues/97744 from `README`. + +## 2.10.0 + +* Bumps webkit from 1.0.0 to 1.5.0. +* Raises minimum `compileSdkVersion` to 32. + +## 2.9.5 + +* Adds dispose methods for HostApi and FlutterApi of JavaObject. + +## 2.9.4 + +* Fixes avoid_redundant_argument_values lint warnings and minor typos. +* Bumps gradle from 7.2.1 to 7.2.2. + +## 2.9.3 + +* Updates the Dart InstanceManager to take a listener for when an object is garbage collected. + See https://github.com/flutter/flutter/issues/107199. + +## 2.9.2 + +* Updates the Java InstanceManager to take a listener for when an object is garbage collected. + See https://github.com/flutter/flutter/issues/107199. + +## 2.9.1 + +* Updates Android WebView classes as Copyable. This is a part of moving the api to handle garbage + collection automatically. See https://github.com/flutter/flutter/issues/107199. + +## 2.9.0 + +* Ignores unnecessary import warnings in preparation for [upcoming Flutter changes](https://github.com/flutter/flutter/pull/106316). +* Fixes bug where `Directionality` from context didn't affect `SurfaceAndroidWebView`. +* Fixes bug where default text direction was different for `SurfaceAndroidWebView` and `AndroidWebView`. + Default is now `TextDirection.ltr` for both. +* Fixes bug where setting WebView to a transparent background could cause visual errors when using + `SurfaceAndroidWebView`. Hybrid composition is now used when the background color is not 100% + opaque. +* Raises minimum Flutter version to 3.0.0. + +## 2.8.14 + +* Bumps androidx.annotation from 1.0.0 to 1.4.0. + +## 2.8.13 + +* Fixes a bug which causes an exception when the `onNavigationRequestCallback` return `false`. + +## 2.8.12 + +* Bumps mockito-inline from 3.11.1 to 4.6.1. + +## 2.8.11 + +* Ignores unnecessary import warnings in preparation for [upcoming Flutter changes](https://github.com/flutter/flutter/pull/104231). + +## 2.8.10 + +* Updates references to the obsolete master branch. + +## 2.8.9 + +* Updates Gradle to 7.2.1. + +## 2.8.8 + +* Minor fixes for new analysis options. + +## 2.8.7 + +* Removes unnecessary imports. +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 2.8.6 + +* Updates pigeon developer dependency to the latest version which adds support for null safety. + +## 2.8.5 + +* Migrates deprecated `Scaffold.showSnackBar` to `ScaffoldMessenger` in example app. + +## 2.8.4 + +* Fixes bug preventing `mockito` code generation for tests. +* Fixes regression where local storage wasn't cleared when `WebViewController.clearCache` was + called. + +## 2.8.3 + +* Fixes a bug causing `debuggingEnabled` to always be set to true. +* Fixes an integration test race condition. + +## 2.8.2 + +* Adds the `WebSettings.setAllowFileAccess()` method and ensure that file access is allowed when the `WebViewAndroidWidget.loadFile()` method is executed. + +## 2.8.1 + +* Fixes bug where the default user agent string was being set for every rebuild. See + https://github.com/flutter/flutter/issues/94847. + +## 2.8.0 + +* Implements new cookie manager for setting cookies and providing initial cookies. + +## 2.7.0 + +* Adds support for the `loadRequest` method from the platform interface. + +## 2.6.0 + +* Adds implementation of the `loadFlutterAsset` method from the platform interface. + +## 2.5.0 + +* Adds an option to set the background color of the webview. + +## 2.4.0 + +* Adds support for Android's `WebView.loadData` and `WebView.loadDataWithBaseUrl` methods and implements the `loadFile` and `loadHtmlString` methods from the platform interface. +* Updates to webview_flutter_platform_interface version 1.5.2. + +## 2.3.1 + +* Adds explanation on how to generate the pigeon communication layer and mockito mock objects. +* Updates compileSdkVersion to 31. + +## 2.3.0 + +* Replaces platform implementation with API built with pigeon. + +## 2.2.1 + +* Fix `NullPointerException` from a race condition when changing focus. This only affects `WebView` +when it is created without Hybrid Composition. + +## 2.2.0 + +* Implemented new `runJavascript` and `runJavascriptReturningResult` methods in platform interface. + +## 2.1.0 + +* Add `zoomEnabled` functionality. + +## 2.0.15 + +* Added Overrides in FlutterWebView.java + +## 2.0.14 + +* Update example App so navigation menu loads immediatly but only becomes available when `WebViewController` is available (same behavior as example App in webview_flutter package). + +## 2.0.13 + +* Extract Android implementation from `webview_flutter`. diff --git a/packages/webview_flutter/webview_flutter_ohos/LICENSE b/packages/webview_flutter/webview_flutter_ohos/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..77130909e47468e360b0905ca04746163aff6a0f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/LICENSE @@ -0,0 +1,26 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/packages/webview_flutter/webview_flutter_ohos/README.md b/packages/webview_flutter/webview_flutter_ohos/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a51f1991a1b9ea2b364cfd641001a11ed7e34b62 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/README.md @@ -0,0 +1,21 @@ +# webview\_flutter\_ohos + +The OpenHarmony implementation of [`webview_flutter`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `webview_flutter` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +## Display Mode + +This plugin supports two different platform view display modes. The default display mode is subject +to change in the future, and will not be considered a breaking change, so if you want to ensure a +specific mode, you can set it explicitly. + +[1]: https://pub.dev/packages/webview_flutter +[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin diff --git a/packages/webview_flutter/webview_flutter_ohos/example/.gitignore b/packages/webview_flutter/webview_flutter_ohos/example/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..24476c5d1eb55824c76d8b01a3965f94abad1ef8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/webview_flutter/webview_flutter_ohos/example/README.md b/packages/webview_flutter/webview_flutter_ohos/example/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f005f871a1a39702aa6a11f4f2be02eed1dae630 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/README.md @@ -0,0 +1,16 @@ +# webview_flutter_demo + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_audio.ogg b/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_audio.ogg new file mode 100644 index 0000000000000000000000000000000000000000..27e17104277b38ae70d3936f5afb4ea32477ec22 Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_audio.ogg differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_video.mp4 b/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_video.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a203d0cdf13ea5106cdb8c98b52301f0e3719bac Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/assets/sample_video.mp4 differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/assets/www/index.html b/packages/webview_flutter/webview_flutter_ohos/example/assets/www/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9895dd3ce6cb92238e0e771ada1403ec3136f1b5 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/assets/www/index.html @@ -0,0 +1,20 @@ + + + + +Load file or HTML string example + + + + +

Local demo page

+

+ This is an example page used to demonstrate how to load a local file or HTML + string using the Flutter + webview plugin. +

+ + + \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/assets/www/styles/style.css b/packages/webview_flutter/webview_flutter_ohos/example/assets/www/styles/style.css new file mode 100644 index 0000000000000000000000000000000000000000..c2140b8b0fd84ba2504f5287b994736279477a0b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/assets/www/styles/style.css @@ -0,0 +1,3 @@ +h1 { + color: blue; +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/lib/main.dart b/packages/webview_flutter/webview_flutter_ohos/example/lib/main.dart new file mode 100644 index 0000000000000000000000000000000000000000..a87d8e743909bd7df0349a8115d7de4196089a12 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/lib/main.dart @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:webview_flutter_ohos/webview_flutter_ohos.dart'; +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; + +void main() { + runApp(const MaterialApp(home: WebViewExample())); +} + +const String kNavigationExamplePage = ''' + +Navigation Delegate Example + +

+The navigation delegate is set to block navigation to the pub.dev website. +

+ + + +'''; + +const String kLocalExamplePage = ''' + + + +Load file or HTML string example + + + +

Local demo page

+

+ This is an example page used to demonstrate how to load a local file or HTML + string using the Flutter + webview plugin. +

+ + + +'''; + +const String kTransparentBackgroundPage = ''' + + + + Transparent background test + + + +
+

Transparent background test

+
+
+ + +'''; + +const String kLogExamplePage = ''' + + + +Load file or HTML string example + + + +

Local demo page

+

+ This page is used to test the forwarding of console logs to Dart. +

+ + + +
+ + + + + +
+ + + +'''; + +const String kAlertTestPage = ''' + + + + + + + +

Click the following button to see the effect

+
+ + + +
+ + +'''; + +class WebViewExample extends StatefulWidget { + const WebViewExample({super.key, this.cookieManager}); + + final PlatformWebViewCookieManager? cookieManager; + + @override + State createState() => _WebViewExampleState(); +} + +class _WebViewExampleState extends State { + late final PlatformWebViewController _controller; + + Future getUserAgent() async { + String userAgent = await _controller.getUserAgent() ?? ''; + if(defaultTargetPlatform != TargetPlatform.ohos){ + return userAgent; + } + return '$userAgent HuaweiBrower'; + } + + @override + void initState() { + super.initState(); + + _controller = PlatformWebViewController( + OhosWebViewControllerCreationParams(), + ) + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(const Color(0x80000000)) + ..setPlatformNavigationDelegate( + PlatformNavigationDelegate( + const PlatformNavigationDelegateCreationParams(), + ) + ..setOnProgress((int progress) { + debugPrint('WebView is loading (progress : $progress%)'); + }) + ..setOnPageStarted((String url) { + debugPrint('Page started loading: $url'); + }) + ..setOnPageFinished((String url) { + debugPrint('Page finished loading: $url'); + }) + ..setOnHttpError((HttpResponseError error) { + debugPrint( + 'HTTP error occured on page: ${error.response?.statusCode}', + ); + }) + ..setOnWebResourceError((WebResourceError error) { + debugPrint(''' +Page resource error: + code: ${error.errorCode} + description: ${error.description} + errorType: ${error.errorType} + isForMainFrame: ${error.isForMainFrame} + url: ${error.url} + '''); + }) + ..setOnNavigationRequest((NavigationRequest request) { + if (request.url.contains('pub.dev')) { + debugPrint('blocking navigation to ${request.url}'); + return NavigationDecision.prevent; + } + debugPrint('allowing navigation to ${request.url}'); + return NavigationDecision.navigate; + }) + ..setOnUrlChange((UrlChange change) { + debugPrint('url change to ${change.url}'); + }) + ..setOnHttpAuthRequest((HttpAuthRequest request) { + openDialog(request); + }), + ) + ..addJavaScriptChannel(JavaScriptChannelParams( + name: 'Toaster', + onMessageReceived: (JavaScriptMessage message) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message.message)), + ); + }, + )) + ..setOnPlatformPermissionRequest( + (PlatformWebViewPermissionRequest request) { + debugPrint( + 'requesting permissions for ${request.types.map((WebViewPermissionResourceType type) => type.name)}', + ); + request.grant(); + }, + ) + ..loadRequest( + LoadRequestParams( + uri: Uri.parse('https://flutter.dev'), + ), + ); + + getUserAgent().then((String userAgent){ + _controller.setUserAgent(userAgent); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF4CAF50), + appBar: AppBar( + title: const Text('Flutter WebView example'), + // This drop down menu demonstrates that Flutter widgets can be shown over the web view. + actions: [ + NavigationControls(webViewController: _controller), + SampleMenu( + webViewController: _controller, + cookieManager: widget.cookieManager, + ), + ], + ), + body: PlatformWebViewWidget( + PlatformWebViewWidgetCreationParams(controller: _controller), + ).build(context), + floatingActionButton: favoriteButton(), + ); + } + + Widget favoriteButton() { + return FloatingActionButton( + onPressed: () async { + final String? url = await _controller.currentUrl(); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Favorited $url')), + ); + } + }, + child: const Icon(Icons.favorite), + ); + } + + Future openDialog(HttpAuthRequest httpRequest) async { + final TextEditingController usernameTextController = + TextEditingController(); + final TextEditingController passwordTextController = + TextEditingController(); + + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text('${httpRequest.host}: ${httpRequest.realm ?? '-'}'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + decoration: const InputDecoration(labelText: 'Username'), + autofocus: true, + controller: usernameTextController, + ), + TextField( + decoration: const InputDecoration(labelText: 'Password'), + controller: passwordTextController, + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + httpRequest.onProceed( + WebViewCredential( + user: usernameTextController.text, + password: passwordTextController.text, + ), + ); + Navigator.of(context).pop(); + }, + child: const Text('Authenticate'), + ), + ], + ); + }, + ); + } +} + +enum MenuOptions { + showUserAgent, + listCookies, + clearCookies, + addToCache, + listCache, + clearCache, + navigationDelegate, + doPostRequest, + loadLocalFile, + loadFlutterAsset, + loadHtmlString, + transparentBackground, + setCookie, + videoExample, + logExample, + basicAuthentication, + javaScriptAlert, +} + +class SampleMenu extends StatelessWidget { + SampleMenu({ + super.key, + required this.webViewController, + PlatformWebViewCookieManager? cookieManager, + }) : cookieManager = cookieManager ?? + PlatformWebViewCookieManager( + const PlatformWebViewCookieManagerCreationParams(), + ); + + final PlatformWebViewController webViewController; + late final PlatformWebViewCookieManager cookieManager; + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + key: const ValueKey('ShowPopupMenu'), + onSelected: (MenuOptions value) { + switch (value) { + case MenuOptions.showUserAgent: + _onShowUserAgent(); + case MenuOptions.listCookies: + _onListCookies(context); + case MenuOptions.clearCookies: + _onClearCookies(context); + case MenuOptions.addToCache: + _onAddToCache(context); + case MenuOptions.listCache: + _onListCache(); + case MenuOptions.clearCache: + _onClearCache(context); + case MenuOptions.navigationDelegate: + _onNavigationDelegateExample(); + case MenuOptions.doPostRequest: + _onDoPostRequest(); + case MenuOptions.loadLocalFile: + _onLoadLocalFileExample(); + case MenuOptions.loadFlutterAsset: + _onLoadFlutterAssetExample(); + case MenuOptions.loadHtmlString: + _onLoadHtmlStringExample(); + case MenuOptions.transparentBackground: + _onTransparentBackground(); + case MenuOptions.setCookie: + _onSetCookie(); + case MenuOptions.videoExample: + _onVideoExample(context); + case MenuOptions.logExample: + _onLogExample(); + case MenuOptions.basicAuthentication: + _promptForUrl(context); + case MenuOptions.javaScriptAlert: + _onJavaScriptAlertExample(context); + } + }, + itemBuilder: (BuildContext context) => >[ + const PopupMenuItem( + value: MenuOptions.showUserAgent, + child: Text('Show user agent'), + ), + const PopupMenuItem( + value: MenuOptions.listCookies, + child: Text('List cookies'), + ), + const PopupMenuItem( + value: MenuOptions.clearCookies, + child: Text('Clear cookies'), + ), + const PopupMenuItem( + value: MenuOptions.addToCache, + child: Text('Add to cache'), + ), + const PopupMenuItem( + value: MenuOptions.listCache, + child: Text('List cache'), + ), + const PopupMenuItem( + value: MenuOptions.clearCache, + child: Text('Clear cache'), + ), + const PopupMenuItem( + value: MenuOptions.navigationDelegate, + child: Text('Navigation Delegate example'), + ), + const PopupMenuItem( + value: MenuOptions.doPostRequest, + child: Text('Post Request'), + ), + const PopupMenuItem( + value: MenuOptions.loadHtmlString, + child: Text('Load HTML string'), + ), + const PopupMenuItem( + value: MenuOptions.loadLocalFile, + child: Text('Load local file'), + ), + const PopupMenuItem( + value: MenuOptions.loadFlutterAsset, + child: Text('Load Flutter Asset'), + ), + const PopupMenuItem( + value: MenuOptions.setCookie, + child: Text('Set cookie'), + ), + const PopupMenuItem( + key: ValueKey('ShowTransparentBackgroundExample'), + value: MenuOptions.transparentBackground, + child: Text('Transparent background example'), + ), + const PopupMenuItem( + value: MenuOptions.logExample, + child: Text('Log example'), + ), + const PopupMenuItem( + value: MenuOptions.videoExample, + child: Text('Video example'), + ), + const PopupMenuItem( + value: MenuOptions.basicAuthentication, + child: Text('Basic Authentication Example'), + ), + const PopupMenuItem( + value: MenuOptions.javaScriptAlert, + child: Text('JavaScript Alert Example'), + ), + ], + ); + } + + Future _onShowUserAgent() { + // Send a message with the user agent string to the Toaster JavaScript channel we registered + // with the WebView. + return webViewController.runJavaScript( + 'Toaster.postMessage("User Agent: " + navigator.userAgent);', + ); + } + + Future _onListCookies(BuildContext context) async { + final String cookies = await webViewController + .runJavaScriptReturningResult('document.cookie') as String; + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Column( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Cookies:'), + _getCookieList(cookies), + ], + ), + )); + } + } + + Future _onAddToCache(BuildContext context) async { + await webViewController.runJavaScript( + 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";', + ); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Added a test entry to cache.'), + )); + } + } + + Future _onListCache() { + return webViewController.runJavaScript('caches.keys()' + // ignore: missing_whitespace_between_adjacent_strings + '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' + '.then((caches) => Toaster.postMessage(caches))'); + } + + Future _onClearCache(BuildContext context) async { + await webViewController.clearCache(); + await webViewController.clearLocalStorage(); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar( + content: Text('Cache cleared.'), + )); + } + } + + Future _onClearCookies(BuildContext context) async { + final bool hadCookies = await cookieManager.clearCookies(); + String message = 'There were cookies. Now, they are gone!'; + if (!hadCookies) { + message = 'There are no cookies.'; + } + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(message), + )); + } + } + + Future _onNavigationDelegateExample() { + final String contentBase64 = base64Encode( + const Utf8Encoder().convert(kNavigationExamplePage), + ); + return webViewController.loadRequest( + LoadRequestParams( + uri: Uri.parse('data:text/html;base64,$contentBase64'), + ), + ); + } + + Future _onSetCookie() async { + await cookieManager.setCookie( + const WebViewCookie( + name: 'foo', + value: 'bar', + domain: 'httpbin.org', + path: '/anything', + ), + ); + await webViewController.loadRequest(LoadRequestParams( + uri: Uri.parse('https://httpbin.org/anything'), + )); + } + + Future _onVideoExample(BuildContext context) { + final OhosWebViewController ohosController = + webViewController as OhosWebViewController; + // #docregion fullscreen_example + ohosController.setCustomWidgetCallbacks( + onShowCustomWidget: (Widget widget, OnHideCustomWidgetCallback callback) { + Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => widget, + fullscreenDialog: true, + )); + }, + onHideCustomWidget: () { + Navigator.of(context).pop(); + }, + ); + // #enddocregion fullscreen_example + + return ohosController.loadRequest( + LoadRequestParams( + uri: Uri.parse('https://www.youtube.com/watch?v=4AoFA19gbLo'), + ), + ); + } + + Future _onDoPostRequest() { + return webViewController.loadRequest(LoadRequestParams( + uri: Uri.parse('https://httpbin.org/post'), + method: LoadRequestMethod.post, + headers: const { + 'foo': 'bar', + 'Content-Type': 'text/plain', + }, + body: Uint8List.fromList('Test Body'.codeUnits), + )); + } + + Future _onLoadLocalFileExample() async { + final String pathToIndex = await _prepareLocalFile(); + await webViewController.loadFile(pathToIndex); + } + + Future _onLoadFlutterAssetExample() { + return webViewController.loadFlutterAsset('assets/www/index.html'); + } + + Future _onLoadHtmlStringExample() { + return webViewController.loadHtmlString(kLocalExamplePage); + } + + Future _onTransparentBackground() { + return webViewController.loadHtmlString(kTransparentBackgroundPage); + } + + Future _onJavaScriptAlertExample(BuildContext context) { + webViewController.setOnJavaScriptAlertDialog( + (JavaScriptAlertDialogRequest request) async { + await _showAlert(context, request.message); + }); + + webViewController.setOnJavaScriptConfirmDialog( + (JavaScriptConfirmDialogRequest request) async { + final bool result = await _showConfirm(context, request.message); + return result; + }); + + webViewController.setOnJavaScriptTextInputDialog( + (JavaScriptTextInputDialogRequest request) async { + final String result = + await _showTextInput(context, request.message, request.defaultText); + return result; + }); + + return webViewController.loadHtmlString(kAlertTestPage); + } + + Widget _getCookieList(String cookies) { + if (cookies == '""') { + return Container(); + } + final List cookieList = cookies.split(';'); + final Iterable cookieWidgets = + cookieList.map((String cookie) => Text(cookie)); + return Column( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: cookieWidgets.toList(), + ); + } + + static Future _prepareLocalFile() async { + final String tmpDir = (await getTemporaryDirectory()).path; + final File indexFile = File( + {tmpDir, 'www', 'index.html'}.join(Platform.pathSeparator)); + + await indexFile.create(recursive: true); + await indexFile.writeAsString(kLocalExamplePage); + + return indexFile.path; + } + + Future _onLogExample() { + webViewController + .setOnConsoleMessage((JavaScriptConsoleMessage consoleMessage) { + if (kDebugMode) { + debugPrint( + '== JS == ${consoleMessage.level.name}: ${consoleMessage.message}'); + } + }); + return webViewController.loadHtmlString(kLogExamplePage); + } + + Future _promptForUrl(BuildContext context) { + final TextEditingController urlTextController = TextEditingController(); + + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Input URL to visit'), + content: TextField( + decoration: const InputDecoration(labelText: 'URL'), + autofocus: true, + controller: urlTextController, + ), + actions: [ + TextButton( + onPressed: () { + if (urlTextController.text.isNotEmpty) { + final Uri? uri = Uri.tryParse(urlTextController.text); + if (uri != null && uri.scheme.isNotEmpty) { + webViewController.loadRequest( + LoadRequestParams(uri: uri), + ); + Navigator.pop(context); + } + } + }, + child: const Text('Visit'), + ), + ], + ); + }, + ); + } + + Future _showAlert(BuildContext context, String message) async { + return showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + content: Text(message), + actions: [ + TextButton( + onPressed: () { + Navigator.of(ctx).pop(); + }, + child: const Text('OK')) + ], + ); + }); + } + + Future _showConfirm(BuildContext context, String message) async { + return await showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + content: Text(message), + actions: [ + TextButton( + onPressed: () { + Navigator.of(ctx).pop(false); + }, + child: const Text('Cancel')), + TextButton( + onPressed: () { + Navigator.of(ctx).pop(true); + }, + child: const Text('OK')), + ], + ); + }) ?? + false; + } + + Future _showTextInput( + BuildContext context, String message, String? defaultText) async { + return await showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + content: Text(message), + actions: [ + TextButton( + onPressed: () { + Navigator.of(ctx).pop('Text test'); + }, + child: const Text('Enter')), + ], + ); + }) ?? + ''; + } +} + +class NavigationControls extends StatelessWidget { + const NavigationControls({super.key, required this.webViewController}); + + final PlatformWebViewController webViewController; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + IconButton( + icon: const Icon(Icons.arrow_back_ios), + onPressed: () async { + if (await webViewController.canGoBack()) { + await webViewController.goBack(); + } else { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('No back history item')), + ); + } + } + }, + ), + IconButton( + icon: const Icon(Icons.arrow_forward_ios), + onPressed: () async { + if (await webViewController.canGoForward()) { + await webViewController.goForward(); + } else { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('No forward history item')), + ); + } + } + }, + ), + IconButton( + icon: const Icon(Icons.replay), + onPressed: () => webViewController.reload(), + ), + ], + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/.gitignore b/packages/webview_flutter/webview_flutter_ohos/example/ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..556a6a5d499b5c121cf07f9e29bdda705b13c906 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/.gitignore @@ -0,0 +1,13 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +oh-package-lock.json5 +*.har \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/app.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fb03ddd86ab880686c1ecdd155485ec652d6ee0f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.example.webview_flutter_demo", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/element/string.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7f69aa3f541d5dc60d1e4691ef20146e60353fd2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "webview_flutter_demo" + } + ] +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/media/app_icon.png b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/ohos/AppScope/resources/base/media/app_icon.png differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/build-profile.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1d12140d202702d7c73d64f1b291fe5c45a660ce --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/build-profile.json5 @@ -0,0 +1,27 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/.gitignore b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4312a1575b0c8cf83a788d387dd483fcca09aee6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/.gitignore @@ -0,0 +1,9 @@ + +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test +*.har +src/main/resources/rawfile/flutter_assets diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/build-profile.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..633d360fbc91a3186a23b66ab71b27e5618944cb --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/build-profile.json5 @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "apiType": 'stageMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + "runtimeOS": "HarmonyOS" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/hvigorfile.ts b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/hvigorfile.ts @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { hapTasks } from '@ohos/hvigor-ohos-plugin'; diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/libs/arm64-v8a/libc++_shared.so b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/libs/arm64-v8a/libc++_shared.so new file mode 100644 index 0000000000000000000000000000000000000000..831c9353702073d45889352a4dafb93103d67d20 Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/libs/arm64-v8a/libc++_shared.so differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/oh-package.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..541ee5ca28ad402dc425d413f2674aae5220bf9c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/oh-package.json5 @@ -0,0 +1,14 @@ +{ + "license": "", + "devDependencies": {}, + "author": "", + "name": "entry", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.0", + "dependencies": { + "@ohos/flutter_ohos": "file:../har/flutter.har", + "path_provider_ohos": "file:../har/path_provider_ohos.har", + "webview_flutter_ohos": "file:../har/webview_flutter_ohos.har" + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..483d8221a8cd571c048ec6eba973cd0a97d8cfb9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterAbility } from '@ohos/flutter_ohos' +import { FlutterPlugin } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'; +import List from '@ohos.util.List'; +import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine'; + +export default class EntryAbility extends FlutterAbility { + configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + GeneratedPluginRegistrant.registerWith(flutterEngine); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/pages/Index.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..1125f9fdd95f4310a182c1c9e3680f37f73686c9 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import common from '@ohos.app.ability.common'; +import { FlutterPage } from '@ohos/flutter_ohos' + +let storage = LocalStorage.getShared() +const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS' + +@Entry(storage) +@Component +struct Index { + private context = getContext(this) as common.UIAbilityContext + @LocalStorageLink('viewId') viewId: string = ""; + + build() { + Column() { + FlutterPage({ viewId: this.viewId }) + } + } + + onBackPress(): boolean { + this.context.eventHub.emit(EVENT_BACK_PRESS) + return true + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/module.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1aeeb2da1b769819c2fdf57c01c550109e20938a --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/module.json5 @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name" : "ohos.permission.INTERNET", + "reason": "$string:EntryAbility_desc", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + }, + ] + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/color.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/string.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/media/icon.png b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/media/icon.png differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/en_US/element/string.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..d2efde923f91d4f9e111bb4ae2ba36f5abe2fcf2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "webview_flutter" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..25d4c71ff3cd584f5d64f6f8c0ac864928c234c4 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(function () { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(function () { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(function () { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(function () { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain',0, function () { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc' + let b = 'b' + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f4140030e65d20df6af30a6bf51e464dea8f8aa6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ca645e6013cfce8e7dbb728313cb8840c4da660 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; + +export default class TestAbility extends UIAbility { + onCreate(want, launchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..cef0447cd2f137ef82d223ead2e156808878ab90 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..1def08f2e9dcbfa3454a07b7a3b82b173bb90d02 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/module.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fab77ce2e0c61e3ad010bab5b27ccbd15f9a8c96 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/module.json5 @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigor/hvigor-config.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2eedd831a4ab8f424ad9a295ac99e33e05cfa81d --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigor/hvigor-config.json5 @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "properties": { + "ohos.nativeResolver": false + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigorfile.ts b/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a172b770e3b15f67c12152d00f38f2084d3915b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/hvigorfile.ts @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { appTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/ohos/oh-package.json5 b/packages/webview_flutter/webview_flutter_ohos/example/ohos/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8777672692c2a24fb9dc646c841c621f46cafd2a --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/ohos/oh-package.json5 @@ -0,0 +1,19 @@ +{ + "modelVersion": "5.0.0", + "license": "", + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "author": "", + "name": "apptemplate", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.0", + "dependencies": {}, + "overrides": { + "@ohos/flutter_ohos": "file:./har/flutter.har", + "path_provider_ohos": "file:./har/path_provider_ohos.har", + "webview_flutter_ohos": "file:./har/webview_flutter_ohos.har", + "@ohos/flutter_module": "file:./entry" + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_ohos/example/pubspec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c86fbd7d2cfd8b465a6de6e8ad6891d3233af967 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/example/pubspec.yaml @@ -0,0 +1,53 @@ +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: webview_flutter_ohos_example +description: Demonstrates how to use the webview_flutter_ohos plugin. +publish_to: none + +environment: + sdk: ^3.2.0 + flutter: ">=3.16.0" + +dependencies: + flutter: + sdk: flutter + path_provider: + path: "../../../path_provider/path_provider" + path_provider_platform_interface: ^2.0.0 + webview_flutter_ohos: + # When depending on this package from a real application you should use: + # webview_flutter: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + +dependency_overrides: + path_provider_ohos: + path: ../../../path_provider/path_provider_ohos + webview_flutter_platform_interface: + path: ../../webview_flutter_platform_interface + +dev_dependencies: + espresso: ^0.2.0 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true + assets: + - assets/sample_audio.ogg + - assets/sample_video.mp4 + - assets/www/index.html + - assets/www/styles/style.css diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/instance_manager.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/instance_manager.dart new file mode 100644 index 0000000000000000000000000000000000000000..8fb6210a8709f8bbb7ab991ad357bc4d5e84a0a5 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/instance_manager.dart @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flutter/foundation.dart'; + +/// An immutable object that can provide functional copies of itself. +/// +/// All implementers are expected to be immutable as defined by the annotation. +@immutable +mixin Copyable { + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [InstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + Copyable copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class InstanceManager { + /// Constructs an [InstanceManager]. + InstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(Copyable instance) { + final int identifier = _nextUniqueIdentifier(); + _addInstanceWithIdentifier(instance, identifier); + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(Copyable instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// This does not remove the weak referenced instance associated with + /// [identifier]. This can be done with [removeWeakReference]. + T? remove(int identifier) { + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference(int identifier) { + final Copyable? weakInstance = _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final Copyable? strongInstance = _strongInstances[identifier]; + if (strongInstance != null) { + final Copyable copy = strongInstance.copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(Copyable instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + /// + /// Returns unique identifier of the [instance] added. + void addHostCreatedInstance(Copyable instance, int identifier) { + _addInstanceWithIdentifier(instance, identifier); + } + + void _addInstanceWithIdentifier(Copyable instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _weakInstances[identifier] = WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final Copyable copy = instance.copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos.dart new file mode 100644 index 0000000000000000000000000000000000000000..5fcd18a67cf50b963017dfe08f93725419477248 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos.dart @@ -0,0 +1,83 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +// ignore: implementation_imports +import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart'; + +import '../ohos_webview.dart'; +import '../instance_manager.dart'; +import 'webview_ohos_widget.dart'; + +/// Builds an Ohos webview. +/// +/// This is used as the default implementation for [WebView.platform] on Ohos. It uses +/// an [OhosView] to embed the webview in the widget hierarchy, and uses a method channel to +/// communicate with the platform code. +class OhosWebView implements WebViewPlatform { + /// Constructs an [OhosWebView]. + OhosWebView({@visibleForTesting InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances used to communicate with the native objects they + /// represent. + @protected + final InstanceManager instanceManager; + + @override + Widget build({ + required BuildContext context, + required CreationParams creationParams, + required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler, + required JavascriptChannelRegistry javascriptChannelRegistry, + WebViewPlatformCreatedCallback? onWebViewPlatformCreated, + Set>? gestureRecognizers, + }) { + return WebViewOhosWidget( + creationParams: creationParams, + callbacksHandler: webViewPlatformCallbacksHandler, + javascriptChannelRegistry: javascriptChannelRegistry, + onBuildWidget: (WebViewOhosPlatformController controller) { + return GestureDetector( + // We prevent text selection by intercepting the long press event. + // This is a temporary stop gap due to issues with text selection on Ohos: + // https://github.com/flutter/flutter/issues/24585 - the text selection + // dialog is not responding to touch events. + // https://github.com/flutter/flutter/issues/24584 - the text selection + // handles are not showing. + // TODO(amirh): remove this when the issues above are fixed. + onLongPress: () {}, + excludeFromSemantics: true, + child: OhosView( + viewType: 'plugins.flutter.io/webview', + onPlatformViewCreated: (int id) { + if (onWebViewPlatformCreated != null) { + onWebViewPlatformCreated(controller); + } + }, + gestureRecognizers: gestureRecognizers, + layoutDirection: + Directionality.maybeOf(context) ?? TextDirection.rtl, + creationParams: instanceManager.getIdentifier(controller.webView), + creationParamsCodec: const StandardMessageCodec(), + ), + ); + }, + ); + } + + @override + Future clearCookies() { + if (WebViewCookieManagerPlatform.instance == null) { + throw Exception( + 'Could not clear cookies as no implementation for WebViewCookieManagerPlatform has been registered.'); + } + return WebViewCookieManagerPlatform.instance!.clearCookies(); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_cookie_manager.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_cookie_manager.dart new file mode 100644 index 0000000000000000000000000000000000000000..2474255e5a596312b28ab7c6b58ba0744627a881 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_cookie_manager.dart @@ -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. + +import 'package:flutter/foundation.dart'; +// ignore: implementation_imports +import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart'; + +import '../ohos_webview.dart' as ohos_webview; + +/// Handles all cookie operations for the current platform. +class WebViewOhosCookieManager extends WebViewCookieManagerPlatform { + /// Constructs a [WebViewOhosCookieManager]. + WebViewOhosCookieManager({ + @visibleForTesting ohos_webview.CookieManager? cookieManager, + }) : _cookieManager = cookieManager ?? ohos_webview.CookieManager.instance; + + final ohos_webview.CookieManager _cookieManager; + + @override + Future clearCookies() => _cookieManager.removeAllCookies(); + + @override + Future setCookie(WebViewCookie cookie) { + if (!_isValidPath(cookie.path)) { + throw ArgumentError( + 'The path property for the provided cookie was not given a legal value.'); + } + return _cookieManager.setCookie( + cookie.domain, + '${Uri.encodeComponent(cookie.name)}=${Uri.encodeComponent(cookie.value)}; path=${cookie.path}', + ); + } + + bool _isValidPath(String path) { + // Permitted ranges based on RFC6265bis: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + for (final int char in path.codeUnits) { + if ((char < 0x20 || char > 0x3A) && (char < 0x3C || char > 0x7E)) { + return false; + } + } + return true; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_widget.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_widget.dart new file mode 100644 index 0000000000000000000000000000000000000000..36d9ac9366dfcabbef3c62b74bc85c7bfeb94d19 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_ohos_widget.dart @@ -0,0 +1,668 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:flutter/widgets.dart'; +// ignore: implementation_imports +import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart'; + +import '../ohos_webview.dart' as ohos_webview; +import '../weak_reference_utils.dart'; +import 'webview_ohos_cookie_manager.dart'; + +/// Creates a [Widget] with a [ohos_webview.WebView]. +class WebViewOhosWidget extends StatefulWidget { + /// Constructs a [WebViewOhosWidget]. + const WebViewOhosWidget({ + super.key, + required this.creationParams, + required this.callbacksHandler, + required this.javascriptChannelRegistry, + required this.onBuildWidget, + @visibleForTesting this.webViewProxy = const WebViewProxy(), + @visibleForTesting + this.flutterAssetManager = const ohos_webview.FlutterAssetManager(), + @visibleForTesting this.webStorage, + }); + + /// Initial parameters used to setup the WebView. + final CreationParams creationParams; + + /// Handles callbacks that are made by [ohos_webview.WebViewClient], [ohos_webview.DownloadListener], and [ohos_webview.WebChromeClient]. + final WebViewPlatformCallbacksHandler callbacksHandler; + + /// Manages named JavaScript channels and forwarding incoming messages on the correct channel. + final JavascriptChannelRegistry javascriptChannelRegistry; + + /// Handles constructing [ohos_webview.WebView]s and calling static methods. + /// + /// This should only be changed for testing purposes. + final WebViewProxy webViewProxy; + + /// Manages access to Flutter assets that are part of the Ohos App bundle. + /// + /// This should only be changed for testing purposes. + final ohos_webview.FlutterAssetManager flutterAssetManager; + + /// Callback to build a widget once [ohos_webview.WebView] has been initialized. + final Widget Function(WebViewOhosPlatformController controller) + onBuildWidget; + + /// Manages the JavaScript storage APIs. + final ohos_webview.WebStorage? webStorage; + + @override + State createState() => _WebViewOhosWidgetState(); +} + +class _WebViewOhosWidgetState extends State { + late final WebViewOhosPlatformController controller; + + @override + void initState() { + super.initState(); + controller = WebViewOhosPlatformController( + creationParams: widget.creationParams, + callbacksHandler: widget.callbacksHandler, + javascriptChannelRegistry: widget.javascriptChannelRegistry, + webViewProxy: widget.webViewProxy, + flutterAssetManager: widget.flutterAssetManager, + webStorage: widget.webStorage, + ); + } + + @override + Widget build(BuildContext context) { + return widget.onBuildWidget(controller); + } +} + +/// Implementation of [WebViewPlatformController] with the Ohos WebView api. +class WebViewOhosPlatformController extends WebViewPlatformController { + /// Construct a [WebViewOhosPlatformController]. + WebViewOhosPlatformController({ + required CreationParams creationParams, + required this.callbacksHandler, + required this.javascriptChannelRegistry, + @visibleForTesting this.webViewProxy = const WebViewProxy(), + @visibleForTesting + this.flutterAssetManager = const ohos_webview.FlutterAssetManager(), + @visibleForTesting ohos_webview.WebStorage? webStorage, + }) : webStorage = webStorage ?? ohos_webview.WebStorage.instance, + assert(creationParams.webSettings?.hasNavigationDelegate != null), + super(callbacksHandler) { + webView = webViewProxy.createWebView(); + + webView.settings.setDomStorageEnabled(true); + webView.settings.setJavaScriptCanOpenWindowsAutomatically(true); + webView.settings.setSupportMultipleWindows(true); + webView.settings.setLoadWithOverviewMode(true); + webView.settings.setUseWideViewPort(true); + webView.settings.setDisplayZoomControls(false); + webView.settings.setBuiltInZoomControls(true); + + _setCreationParams(creationParams); + webView.setDownloadListener(downloadListener); + webView.setWebChromeClient(webChromeClient); + webView.setWebViewClient(webViewClient); + + final String? initialUrl = creationParams.initialUrl; + if (initialUrl != null) { + loadUrl(initialUrl, {}); + } + } + + final Map _javaScriptChannels = + {}; + + late final ohos_webview.WebViewClient _webViewClient = + webViewProxy.createWebViewClient( + onPageStarted: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return (_, String url) { + weakReference.target?.callbacksHandler.onPageStarted(url); + }; + }), + onPageFinished: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return (_, String url) { + weakReference.target?.callbacksHandler.onPageFinished(url); + }; + }), + onReceivedError: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return ( + _, + int errorCode, + String description, + String failingUrl, + ) { + weakReference.target?.callbacksHandler + .onWebResourceError(WebResourceError( + errorCode: errorCode, + description: description, + failingUrl: failingUrl, + errorType: _errorCodeToErrorType(errorCode), + )); + }; + }), + onReceivedRequestError: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return ( + _, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceError error, + ) { + if (request.isForMainFrame) { + weakReference.target?.callbacksHandler + .onWebResourceError(WebResourceError( + errorCode: error.errorCode, + description: error.description, + failingUrl: request.url, + errorType: _errorCodeToErrorType(error.errorCode), + )); + } + }; + }), + urlLoading: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return (_, String url) { + weakReference.target?._handleNavigationRequest( + url: url, + isForMainFrame: true, + ); + }; + }), + requestLoading: withWeakReferenceTo(this, ( + WeakReference weakReference, + ) { + return (_, ohos_webview.WebResourceRequest request) { + weakReference.target?._handleNavigationRequest( + url: request.url, + isForMainFrame: request.isForMainFrame, + ); + }; + }), + ); + + bool _hasNavigationDelegate = false; + bool _hasProgressTracking = false; + + /// Represents the WebView maintained by platform code. + late final ohos_webview.WebView webView; + + /// Handles callbacks that are made by [ohos_webview.WebViewClient], [ohos_webview.DownloadListener], and [ohos_webview.WebChromeClient]. + final WebViewPlatformCallbacksHandler callbacksHandler; + + /// Manages named JavaScript channels and forwarding incoming messages on the correct channel. + final JavascriptChannelRegistry javascriptChannelRegistry; + + /// Handles constructing [ohos_webview.WebView]s and calling static methods. + /// + /// This should only be changed for testing purposes. + final WebViewProxy webViewProxy; + + /// Manages access to Flutter assets that are part of the Ohos App bundle. + /// + /// This should only be changed for testing purposes. + final ohos_webview.FlutterAssetManager flutterAssetManager; + + /// Receives callbacks when content should be downloaded instead. + @visibleForTesting + late final ohos_webview.DownloadListener downloadListener = + ohos_webview.DownloadListener( + onDownloadStart: withWeakReferenceTo( + this, + (WeakReference weakReference) { + return ( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + weakReference.target?._handleNavigationRequest( + url: url, + isForMainFrame: true, + ); + }; + }, + ), + ); + + /// Handles JavaScript dialogs, favicons, titles, new windows, and the progress for [ohos_webview.WebView]. + @visibleForTesting + late final ohos_webview.WebChromeClient webChromeClient = + ohos_webview.WebChromeClient( + onProgressChanged: withWeakReferenceTo( + this, + (WeakReference weakReference) { + return (_, int progress) { + final WebViewOhosPlatformController? controller = + weakReference.target; + if (controller != null && controller._hasProgressTracking) { + controller.callbacksHandler.onProgress(progress); + } + }; + }, + )); + + /// Manages the JavaScript storage APIs. + final ohos_webview.WebStorage webStorage; + + /// Receive various notifications and requests for [ohos_webview.WebView]. + @visibleForTesting + ohos_webview.WebViewClient get webViewClient => _webViewClient; + + @override + Future loadHtmlString(String html, {String? baseUrl}) { + return webView.loadDataWithBaseUrl( + baseUrl: baseUrl, + data: html, + mimeType: 'text/html', + ); + } + + @override + Future loadFile(String absoluteFilePath) { + final String url = absoluteFilePath.startsWith('file://') + ? absoluteFilePath + : 'file://$absoluteFilePath'; + + webView.settings.setAllowFileAccess(true); + return webView.loadUrl(url, {}); + } + + @override + Future loadFlutterAsset(String key) async { + final String assetFilePath = + await flutterAssetManager.getAssetFilePathByName(key); + final List pathElements = assetFilePath.split('/'); + final String fileName = pathElements.removeLast(); + final List paths = + await flutterAssetManager.list(pathElements.join('/')); + + if (!paths.contains(fileName)) { + throw ArgumentError( + 'Asset for key "$key" not found.', + 'key', + ); + } + +/* return webView.loadUrl( + 'file:///ohos_asset/$assetFilePath', + {}, + );*/ + + webView.settings.setAllowFileAccess(true); + final String url = "resources/rawfile/" + assetFilePath; + return webView.loadUrl(url, {}); + } + + @override + Future loadUrl( + String url, + Map? headers, + ) { + return webView.loadUrl(url, headers ?? {}); + } + + /// When making a POST request, headers are ignored. As a workaround, make + /// the request manually and load the response data using [loadHTMLString]. + @override + Future loadRequest( + WebViewRequest request, + ) async { + if (!request.uri.hasScheme) { + throw ArgumentError('WebViewRequest#uri is required to have a scheme.'); + } + switch (request.method) { + case WebViewRequestMethod.get: + return webView.loadUrl(request.uri.toString(), request.headers); + case WebViewRequestMethod.post: + return webView.postUrl( + request.uri.toString(), request.body ?? Uint8List(0)); + } + // The enum comes from a different package, which could get a new value at + // any time, so a fallback case is necessary. Since there is no reasonable + // default behavior, throw to alert the client that they need an updated + // version. This is deliberately outside the switch rather than a `default` + // so that the linter will flag the switch as needing an update. + // ignore: dead_code + throw UnimplementedError( + 'This version of webview_ohos_widget currently has no ' + 'implementation for HTTP method ${request.method.serialize()} in ' + 'loadRequest.'); + } + + @override + Future currentUrl() => webView.getUrl(); + + @override + Future canGoBack() => webView.canGoBack(); + + @override + Future canGoForward() => webView.canGoForward(); + + @override + Future goBack() => webView.goBack(); + + @override + Future goForward() => webView.goForward(); + + @override + Future reload() => webView.reload(); + + @override + Future clearCache() { + webView.clearCache(true); + return webStorage.deleteAllData(); + } + + @override + Future updateSettings(WebSettings setting) async { + _hasProgressTracking = setting.hasProgressTracking ?? _hasProgressTracking; + await Future.wait(>[ + _setUserAgent(setting.userAgent), + if (setting.hasNavigationDelegate != null) + _setHasNavigationDelegate(setting.hasNavigationDelegate!), + if (setting.javascriptMode != null) + _setJavaScriptMode(setting.javascriptMode!), + if (setting.debuggingEnabled != null) + _setDebuggingEnabled(setting.debuggingEnabled!), + if (setting.zoomEnabled != null) _setZoomEnabled(setting.zoomEnabled!), + ]); + } + + @override + Future evaluateJavascript(String javascript) async { + return runJavascriptReturningResult(javascript); + } + + @override + Future runJavascript(String javascript) async { + await webView.evaluateJavascript(javascript); + } + + @override + Future runJavascriptReturningResult(String javascript) async { + return await webView.evaluateJavascript(javascript) ?? ''; + } + + @override + Future addJavascriptChannels(Set javascriptChannelNames) { + return Future.wait( + javascriptChannelNames.where( + (String channelName) { + return !_javaScriptChannels.containsKey(channelName); + }, + ).map>( + (String channelName) { + final WebViewOhosJavaScriptChannel javaScriptChannel = + WebViewOhosJavaScriptChannel( + channelName, javascriptChannelRegistry); + _javaScriptChannels[channelName] = javaScriptChannel; + return webView.addJavaScriptChannel(javaScriptChannel); + }, + ), + ); + } + + @override + Future removeJavascriptChannels( + Set javascriptChannelNames, + ) { + return Future.wait( + javascriptChannelNames.where( + (String channelName) { + return _javaScriptChannels.containsKey(channelName); + }, + ).map>( + (String channelName) { + final WebViewOhosJavaScriptChannel javaScriptChannel = + _javaScriptChannels[channelName]!; + _javaScriptChannels.remove(channelName); + return webView.removeJavaScriptChannel(javaScriptChannel); + }, + ), + ); + } + + @override + Future getTitle() => webView.getTitle(); + + @override + Future scrollTo(int x, int y) => webView.scrollTo(x, y); + + @override + Future scrollBy(int x, int y) => webView.scrollBy(x, y); + + @override + Future getScrollX() => webView.getScrollX(); + + @override + Future getScrollY() => webView.getScrollY(); + + void _setCreationParams(CreationParams creationParams) { + final WebSettings? webSettings = creationParams.webSettings; + if (webSettings != null) { + updateSettings(webSettings); + } + + final String? userAgent = creationParams.userAgent; + if (userAgent != null) { + webView.settings.setUserAgentString(userAgent); + } + + webView.settings.setMediaPlaybackRequiresUserGesture( + creationParams.autoMediaPlaybackPolicy != + AutoMediaPlaybackPolicy.always_allow, + ); + + final Color? backgroundColor = creationParams.backgroundColor; + if (backgroundColor != null) { + //webView.setBackgroundColor(backgroundColor); + } + + addJavascriptChannels(creationParams.javascriptChannelNames); + + // TODO(BeMacized): Remove once platform implementations + // are able to register themselves (Flutter >=2.8), + // https://github.com/flutter/flutter/issues/94224 + WebViewCookieManagerPlatform.instance ??= WebViewOhosCookieManager(); + + creationParams.cookies + .forEach(WebViewCookieManagerPlatform.instance!.setCookie); + } + + Future _setHasNavigationDelegate(bool hasNavigationDelegate) { + _hasNavigationDelegate = hasNavigationDelegate; + return _webViewClient.setSynchronousReturnValueForShouldOverrideUrlLoading( + hasNavigationDelegate, + ); + } + + Future _setJavaScriptMode(JavascriptMode mode) { + switch (mode) { + case JavascriptMode.disabled: + return webView.settings.setJavaScriptEnabled(false); + case JavascriptMode.unrestricted: + return webView.settings.setJavaScriptEnabled(true); + } + } + + Future _setDebuggingEnabled(bool debuggingEnabled) { + return webViewProxy.setWebContentsDebuggingEnabled(debuggingEnabled); + } + + Future _setUserAgent(WebSetting userAgent) { + if (userAgent.isPresent) { + // If the string is empty, the system default value will be used. + return webView.settings.setUserAgentString(userAgent.value ?? ''); + } + + return Future.value(); + } + + Future _setZoomEnabled(bool zoomEnabled) { + return webView.settings.setSupportZoom(zoomEnabled); + } + + static WebResourceErrorType _errorCodeToErrorType(int errorCode) { + switch (errorCode) { + case ohos_webview.WebViewClient.errorAuthentication: + return WebResourceErrorType.authentication; + case ohos_webview.WebViewClient.errorBadUrl: + return WebResourceErrorType.badUrl; + case ohos_webview.WebViewClient.errorConnect: + return WebResourceErrorType.connect; + case ohos_webview.WebViewClient.errorFailedSslHandshake: + return WebResourceErrorType.failedSslHandshake; + case ohos_webview.WebViewClient.errorFile: + return WebResourceErrorType.file; + case ohos_webview.WebViewClient.errorFileNotFound: + return WebResourceErrorType.fileNotFound; + case ohos_webview.WebViewClient.errorHostLookup: + return WebResourceErrorType.hostLookup; + case ohos_webview.WebViewClient.errorIO: + return WebResourceErrorType.io; + case ohos_webview.WebViewClient.errorProxyAuthentication: + return WebResourceErrorType.proxyAuthentication; + case ohos_webview.WebViewClient.errorRedirectLoop: + return WebResourceErrorType.redirectLoop; + case ohos_webview.WebViewClient.errorTimeout: + return WebResourceErrorType.timeout; + case ohos_webview.WebViewClient.errorTooManyRequests: + return WebResourceErrorType.tooManyRequests; + case ohos_webview.WebViewClient.errorUnknown: + return WebResourceErrorType.unknown; + case ohos_webview.WebViewClient.errorUnsafeResource: + return WebResourceErrorType.unsafeResource; + case ohos_webview.WebViewClient.errorUnsupportedAuthScheme: + return WebResourceErrorType.unsupportedAuthScheme; + case ohos_webview.WebViewClient.errorUnsupportedScheme: + return WebResourceErrorType.unsupportedScheme; + } + + if (errorCode < 0) { + return WebResourceErrorType.unknown; + } + + throw ArgumentError( + 'Could not find a WebResourceErrorType for errorCode: $errorCode', + ); + } + + void _handleNavigationRequest({ + required String url, + required bool isForMainFrame, + }) { + if (!_hasNavigationDelegate) { + return; + } + + final FutureOr returnValue = callbacksHandler.onNavigationRequest( + url: url, + isForMainFrame: isForMainFrame, + ); + + if (returnValue is bool && returnValue) { + loadUrl(url, {}); + } else if (returnValue is Future) { + returnValue.then((bool shouldLoadUrl) { + if (shouldLoadUrl) { + loadUrl(url, {}); + } + }); + } + } +} + +/// Exposes a channel to receive calls from javaScript. +class WebViewOhosJavaScriptChannel + extends ohos_webview.JavaScriptChannel { + /// Creates a [WebViewOhosJavaScriptChannel]. + WebViewOhosJavaScriptChannel( + super.channelName, + this.javascriptChannelRegistry, + ) : super( + postMessage: withWeakReferenceTo( + javascriptChannelRegistry, + (WeakReference weakReference) { + return (String message) { + weakReference.target?.onJavascriptChannelMessage( + channelName, + message, + ); + }; + }, + ), + ); + + /// Manages named JavaScript channels and forwarding incoming messages on the correct channel. + final JavascriptChannelRegistry javascriptChannelRegistry; +} + +/// Handles constructing [ohos_webview.WebView]s and calling static methods. +/// +/// This should only be used for testing purposes. +@visibleForTesting +class WebViewProxy { + /// Creates a [WebViewProxy]. + const WebViewProxy(); + + /// Constructs a [ohos_webview.WebView]. + ohos_webview.WebView createWebView() { + return ohos_webview.WebView(); + } + + /// Constructs a [ohos_webview.WebViewClient]. + ohos_webview.WebViewClient createWebViewClient({ + void Function(ohos_webview.WebView webView, String url)? onPageStarted, + void Function(ohos_webview.WebView webView, String url)? onPageFinished, + void Function( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceError error, + )? onReceivedRequestError, + void Function( + ohos_webview.WebView webView, + int errorCode, + String description, + String failingUrl, + )? onReceivedError, + void Function(ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request)? + requestLoading, + void Function(ohos_webview.WebView webView, String url)? urlLoading, + }) { + return ohos_webview.WebViewClient( + onPageStarted: onPageStarted, + onPageFinished: onPageFinished, + onReceivedRequestError: onReceivedRequestError, + onReceivedError: onReceivedError, + requestLoading: requestLoading, + urlLoading: urlLoading, + ); + } + + /// 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 + /// [ohos_webview.WebView] documentation for the debugging guide. The + /// default is false. + /// + /// See [ohos_webview.WebView].setWebContentsDebuggingEnabled. + Future setWebContentsDebuggingEnabled(bool enabled) { + return ohos_webview.WebView.setWebContentsDebuggingEnabled(enabled); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_surface_ohos.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_surface_ohos.dart new file mode 100644 index 0000000000000000000000000000000000000000..dca266fd27e9268b979b9bd3183e076a547db82e --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/legacy/webview_surface_ohos.dart @@ -0,0 +1,119 @@ +// 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/gestures.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +// ignore: implementation_imports +import 'package:webview_flutter_platform_interface/src/webview_flutter_platform_interface_legacy.dart'; + +import '../ohos_webview.dart'; +import 'webview_ohos.dart'; +import 'webview_ohos_widget.dart'; + +/// Ohos [WebViewPlatform] that uses [OhosViewSurface] to build the +/// [WebView] widget. +/// +/// To use this, set [WebView.platform] to an instance of this class. +/// +/// This implementation uses [OhosViewSurface] to render the [WebView] on +/// Ohos. It solves multiple issues related to accessibility and interaction +/// with the [WebView] at the cost of some performance on Ohos versions below +/// 10. +/// +/// To support transparent backgrounds on all Ohos devices, this +/// implementation uses hybrid composition when the opacity of +/// `CreationParams.backgroundColor` is less than 1.0. See +/// https://github.com/flutter/flutter/wiki/Hybrid-Composition for more +/// information. +class SurfaceOhosWebView extends OhosWebView { + /// Constructs a [SurfaceOhosWebView]. + SurfaceOhosWebView({@visibleForTesting super.instanceManager}); + + @override + Widget build({ + required BuildContext context, + required CreationParams creationParams, + required JavascriptChannelRegistry javascriptChannelRegistry, + WebViewPlatformCreatedCallback? onWebViewPlatformCreated, + Set>? gestureRecognizers, + required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler, + }) { + return WebViewOhosWidget( + creationParams: creationParams, + callbacksHandler: webViewPlatformCallbacksHandler, + javascriptChannelRegistry: javascriptChannelRegistry, + onBuildWidget: (WebViewOhosPlatformController controller) { + return PlatformViewLink( + viewType: 'plugins.flutter.io/webview', + surfaceFactory: ( + BuildContext context, + PlatformViewController controller, + ) { + return OhosViewSurface( + controller: controller as OhosViewController, + gestureRecognizers: gestureRecognizers ?? + const >{}, + hitTestBehavior: PlatformViewHitTestBehavior.opaque, + ); + }, + onCreatePlatformView: (PlatformViewCreationParams params) { + final Color? backgroundColor = creationParams.backgroundColor; + return _createViewController( + // On some Ohos devices, transparent backgrounds can cause + // rendering issues on the non hybrid composition + // OhosViewSurface. This switches the WebView to Hybrid + // Composition when the background color is not 100% opaque. + hybridComposition: + backgroundColor != null && backgroundColor.opacity < 1.0, + id: params.id, + viewType: 'plugins.flutter.io/webview', + // WebView content is not affected by the Ohos view's layout direction, + // we explicitly set it here so that the widget doesn't require an ambient + // directionality. + layoutDirection: + Directionality.maybeOf(context) ?? TextDirection.ltr, + webViewIdentifier: + instanceManager.getIdentifier(controller.webView)!, + ) + ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) + ..addOnPlatformViewCreatedListener((int id) { + if (onWebViewPlatformCreated != null) { + onWebViewPlatformCreated(controller); + } + }) + ..create(); + }, + ); + }, + ); + } + + OhosViewController _createViewController({ + required bool hybridComposition, + required int id, + required String viewType, + required TextDirection layoutDirection, + required int webViewIdentifier, + }) { + if (hybridComposition) { + return PlatformViewsService.initExpensiveOhosView( + id: id, + viewType: viewType, + layoutDirection: layoutDirection, + creationParams: webViewIdentifier, + creationParamsCodec: const StandardMessageCodec(), + ); + } + return PlatformViewsService.initSurfaceOhosView( + id: id, + viewType: viewType, + layoutDirection: layoutDirection, + creationParams: webViewIdentifier, + creationParamsCodec: const StandardMessageCodec(), + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_proxy.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_proxy.dart new file mode 100644 index 0000000000000000000000000000000000000000..e0bc4a579a5edd5290b59302dca03ba4336112f2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_proxy.dart @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'ohos_webview.dart' as ohos_webview; + +/// Handles constructing objects and calling static methods for the Ohos +/// WebView native library. +/// +/// This class provides dependency injection for the implementations of the +/// platform interface classes. Improving the ease of unit testing and/or +/// overriding the underlying Ohos WebView classes. +/// +/// By default each function calls the default constructor of the WebView class +/// it intends to return. +class OhosWebViewProxy { + /// Constructs a [OhosWebViewProxy]. + const OhosWebViewProxy({ + this.createOhosWebView = ohos_webview.WebView.new, + this.createOhosWebChromeClient = ohos_webview.WebChromeClient.new, + this.createOhosWebViewClient = ohos_webview.WebViewClient.new, + this.createFlutterAssetManager = ohos_webview.FlutterAssetManager.new, + this.createJavaScriptChannel = ohos_webview.JavaScriptChannel.new, + this.createDownloadListener = ohos_webview.DownloadListener.new, + }); + + /// Constructs a [ohos_webview.WebView]. + final ohos_webview.WebView Function({ + void Function(int left, int top, int oldLeft, int oldTop)? onScrollChanged, + }) createOhosWebView; + + /// Constructs a [ohos_webview.WebChromeClient]. + final ohos_webview.WebChromeClient Function({ + void Function(ohos_webview.WebView webView, int progress)? + onProgressChanged, + Future> Function( + ohos_webview.WebView webView, + ohos_webview.FileChooserParams params, + )? onShowFileChooser, + void Function( + ohos_webview.WebChromeClient instance, + ohos_webview.PermissionRequest request, + )? onPermissionRequest, + Future Function(String origin, + ohos_webview.GeolocationPermissionsCallback callback)? + onGeolocationPermissionsShowPrompt, + void Function(ohos_webview.WebChromeClient instance)? + onGeolocationPermissionsHidePrompt, + void Function(ohos_webview.WebChromeClient instance, + ohos_webview.ConsoleMessage message)? + onConsoleMessage, + void Function( + ohos_webview.WebChromeClient instance, + ohos_webview.View view, + ohos_webview.CustomViewCallback callback)? + onShowCustomView, + void Function(ohos_webview.WebChromeClient instance)? onHideCustomView, + Future Function(String url, String message)? onJsAlert, + Future Function(String url, String message)? onJsConfirm, + Future Function(String url, String message, String defaultValue)? + onJsPrompt, + }) createOhosWebChromeClient; + + /// Constructs a [ohos_webview.WebViewClient]. + final ohos_webview.WebViewClient Function({ + void Function(ohos_webview.WebView webView, String url)? onPageStarted, + void Function(ohos_webview.WebView webView, String url)? onPageFinished, + void Function( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceResponse response, + )? onReceivedHttpError, + void Function( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceError error, + )? onReceivedRequestError, + @Deprecated('Only called on Ohos version < 23.') + void Function( + ohos_webview.WebView webView, + int errorCode, + String description, + String failingUrl, + )? onReceivedError, + void Function( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + )? requestLoading, + void Function(ohos_webview.WebView webView, String url)? urlLoading, + void Function(ohos_webview.WebView webView, String url, bool isReload)? + doUpdateVisitedHistory, + void Function( + ohos_webview.WebView webView, + ohos_webview.HttpAuthHandler handler, + String host, + String realm, + )? onReceivedHttpAuthRequest, + }) createOhosWebViewClient; + + /// Constructs a [ohos_webview.FlutterAssetManager]. + final ohos_webview.FlutterAssetManager Function() createFlutterAssetManager; + + /// Constructs a [ohos_webview.JavaScriptChannel]. + final ohos_webview.JavaScriptChannel Function( + String channelName, { + required void Function(String) postMessage, + }) createJavaScriptChannel; + + /// Constructs a [ohos_webview.DownloadListener]. + final ohos_webview.DownloadListener Function({ + required void Function( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) onDownloadStart, + }) createDownloadListener; + + /// 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 + /// [ohos_webview.WebView] documentation for the debugging guide. The + /// default is false. + /// + /// See [ohos_webview.WebView].setWebContentsDebuggingEnabled. + Future setWebContentsDebuggingEnabled(bool enabled) { + return ohos_webview.WebView.setWebContentsDebuggingEnabled(enabled); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.dart new file mode 100644 index 0000000000000000000000000000000000000000..04db28f0c79e4c79118bfd6aff1045dc8fabfc1d --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.dart @@ -0,0 +1,1640 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart' show BinaryMessenger; + +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; + +import 'ohos_webview.g.dart'; +import 'ohos_webview_api_impls.dart'; +import 'instance_manager.dart'; + +export 'ohos_webview_api_impls.dart' + show ConsoleMessage, ConsoleMessageLevel, FileChooserMode; + +/// Root of the TS class hierarchy. +class OhosObject with Copyable { + /// Constructs a [OhosObject] without creating the associated TS object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + OhosObject.detached({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : _api = OhosObjectHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ); + + /// Global instance of [InstanceManager]. + static final InstanceManager globalInstanceManager = _initInstanceManager(); + + static InstanceManager _initInstanceManager() { + WidgetsFlutterBinding.ensureInitialized(); + // Clears the native `InstanceManager` on initial use of the Dart one. + InstanceManagerHostApi().clear(); + return InstanceManager( + onWeakReferenceRemoved: (int identifier) { + OhosObjectHostApiImpl().dispose(identifier); + }, + ); + } + + /// Pigeon Host Api implementation for [OhosObject]. + final OhosObjectHostApiImpl _api; + + /// Release the reference to a native TS instance. + static void dispose(OhosObject instance) { + instance._api.instanceManager.removeWeakReference(instance); + } + + @override + OhosObject copy() { + return OhosObject.detached(); + } +} + +/// A callback interface used by the host application to set the Geolocation +/// permission state for an origin. +@immutable +class GeolocationPermissionsCallback extends OhosObject { + /// Instantiates a [GeolocationPermissionsCallback] without creating and + /// attaching to an instance of the associated native class. + /// + /// This should only be used outside of tests by subclasses created by this + /// library or to create a copy. + @protected + GeolocationPermissionsCallback.detached({ + super.binaryMessenger, + super.instanceManager, + }) : _geolocationPermissionsCallbackApi = + GeolocationPermissionsCallbackHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + super.detached(); + + final GeolocationPermissionsCallbackHostApiImpl + _geolocationPermissionsCallbackApi; + + /// Sets the Geolocation permission state for the supplied origin. + /// + /// [origin]: The origin for which permissions are set. + /// + /// [allow]: Whether or not the origin should be allowed to use the Geolocation API. + /// + /// [retain]: Whether the permission should be retained beyond the lifetime of + /// a page currently being displayed by a WebView. + Future invoke(String origin, bool allow, bool retain) { + return _geolocationPermissionsCallbackApi.invokeFromInstances( + this, + origin, + allow, + retain, + ); + } + + @override + GeolocationPermissionsCallback copy() { + return GeolocationPermissionsCallback.detached( + binaryMessenger: _geolocationPermissionsCallbackApi.binaryMessenger, + instanceManager: _geolocationPermissionsCallbackApi.instanceManager, + ); + } +} + +/// An Ohos 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. +/// +/// When a [WebView] is no longer needed [release] must be called. +class WebView extends OhosObject { + /// Constructs a new WebView. + /// + /// Due to changes in Flutter 3.0 the [useHybridComposition] doesn't have + /// any effect and should not be exposed publicly. More info here: + /// https://github.com/flutter/flutter/issues/108106 + WebView({ + this.onScrollChanged, + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + api.createFromInstance(this); + } + + /// Constructs a [WebView] without creating the associated TS object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + WebView.detached({ + this.onScrollChanged, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Pigeon Host Api implementation for [WebView]. + @visibleForTesting + static WebViewHostApiImpl api = WebViewHostApiImpl(); + + /// The [WebSettings] object used to control the settings for this WebView. + late final WebSettings settings = WebSettings(this); + + /// Called in response to an internal scroll in this view + /// (i.e., the view scrolled its own contents). + /// + /// This is typically as a result of [scrollBy] or [scrollTo] + /// having been called. + final void Function( + int left, + int top, + int oldLeft, + int oldTop, + )? onScrollChanged; + + /// 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 data into this WebView using a 'data' scheme URL. + /// + /// Note that JavaScript's same origin policy means that script running in a + /// page loaded using this method will be unable to access content loaded + /// using any scheme other than 'data', including 'http(s)'. To avoid this + /// restriction, use [loadDataWithBaseURL()] with an appropriate base URL. + /// + /// The [encoding] parameter specifies whether the data is base64 or URL + /// encoded. If the data is base64 encoded, the value of the encoding + /// parameter must be `'base64'`. HTML can be encoded with + /// `base64.encode(bytes)` like so: + /// ```dart + /// import 'dart:convert'; + /// + /// final unencodedHtml = ''' + /// '%28' is the code for '(' + /// '''; + /// final encodedHtml = base64.encode(utf8.encode(unencodedHtml)); + /// print(encodedHtml); + /// ``` + /// + /// The [mimeType] parameter specifies the format of the data. If WebView + /// can't handle the specified MIME type, it will download the data. If + /// `null`, defaults to 'text/html'. + Future loadData({ + required String data, + String? mimeType, + String? encoding, + }) { + return api.loadDataFromInstance( + this, + data, + mimeType, + encoding, + ); + } + + /// Loads the given data into this WebView. + /// + /// The [baseUrl] is used as base URL for the content. It is used both to + /// resolve relative URLs and when applying JavaScript's same origin policy. + /// + /// The [historyUrl] is used for the history entry. + /// + /// The [mimeType] parameter specifies the format of the data. If WebView + /// can't handle the specified MIME type, it will download the data. If + /// `null`, defaults to 'text/html'. + /// + /// Note that content specified in this way can access local device files (via + /// 'file' scheme URLs) only if baseUrl specifies a scheme other than 'http', + /// 'https', 'ftp', 'ftps', 'about' or 'javascript'. + /// + /// If the base URL uses the data scheme, this method is equivalent to calling + /// [loadData] and the [historyUrl] is ignored, and the data will be treated + /// as part of a data: URL, including the requirement that the content be + /// URL-encoded or base64 encoded. If the base URL uses any other scheme, then + /// the data will be loaded into the WebView as a plain string (i.e. not part + /// of a data URL) and any URL-encoded entities in the string will not be + /// decoded. + /// + /// Note that the [baseUrl] is sent in the 'Referer' HTTP header when + /// requesting subresources (images, etc.) of the page loaded using this + /// method. + /// + /// If a valid HTTP or HTTPS base URL is not specified in [baseUrl], then + /// content loaded using this method will have a `window.origin` value of + /// `"null"`. This must not be considered to be a trusted origin by the + /// application or by any JavaScript code running inside the WebView (for + /// example, event sources in DOM event handlers or web messages), because + /// malicious content can also create frames with a null origin. If you need + /// to identify the main frame's origin in a trustworthy way, you should use a + /// valid HTTP or HTTPS base URL to set the origin. + Future loadDataWithBaseUrl({ + String? baseUrl, + required String data, + String? mimeType, + String? encoding, + String? historyUrl, + }) { + return api.loadDataWithBaseUrlFromInstance( + this, + baseUrl, + data, + mimeType, + encoding, + historyUrl, + ); + } + + /// 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); + } + + /// Loads the URL with postData using "POST" method into this WebView. + /// + /// If url is not a network URL, it will be loaded with [loadUrl] instead, ignoring the postData param. + Future postUrl(String url, Uint8List data) { + return api.postUrlFromInstance(this, url, data); + } + + /// 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() { + return api.getUrlFromInstance(this); + } + + /// 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 Ohos 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) { + return api.evaluateJavascriptFromInstance( + this, + javascriptString, + ); + } + + // 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() { + return api.getTitleFromInstance(this); + } + + // 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); + } + + /// Returns the X and Y scroll position of this view. + Future getScrollPosition() { + return api.getScrollPositionFromInstance(this); + } + + /// Sets the [WebViewClient] that will receive various notifications and requests. + /// + /// This will replace the current handler. + Future setWebViewClient(WebViewClient 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); + 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) { + JavaScriptChannel.api.createFromInstance(javaScriptChannel); + return api.removeJavaScriptChannelFromInstance(this, 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) { + 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) { + return api.setWebChromeClientFromInstance(this, client); + } + + @override + WebView copy() { + return WebView.detached( + onScrollChanged: onScrollChanged, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// Manages cookies globally for all webviews. +class CookieManager extends OhosObject { + /// Instantiates a [CookieManager] without creating and attaching to an + /// instance of the associated native class. + /// + /// This should only be used outside of tests by subclasses created by this + /// library or to create a copy for an [InstanceManager]. + @protected + CookieManager.detached({super.binaryMessenger, super.instanceManager}) + : _cookieManagerApi = CookieManagerHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + super.detached(); + + static final CookieManager _instance = + CookieManagerHostApiImpl().attachInstanceFromInstances( + CookieManager.detached(), + ); + + final CookieManagerHostApiImpl _cookieManagerApi; + + /// Access a static field synchronously. + static CookieManager get instance { + OhosWebViewFlutterApis.instance.ensureSetUp(); + return _instance; + } + + /// Sets a single cookie (key-value pair) for the given URL. Any existing + /// cookie with the same host, path and name will be replaced with the new + /// cookie. The cookie being set will be ignored if it is expired. To set + /// multiple cookies, your application should invoke this method multiple + /// times. + /// + /// The value parameter must follow the format of the Set-Cookie HTTP + /// response header defined by RFC6265bis. This is a key-value pair of the + /// form "key=value", optionally followed by a list of cookie attributes + /// delimited with semicolons (ex. "key=value; Max-Age=123"). Please consult + /// the RFC specification for a list of valid attributes. + /// + /// Note: if specifying a value containing the "Secure" attribute, url must + /// use the "https://" scheme. + /// + /// Params: + /// url – the URL for which the cookie is to be set + /// value – the cookie as a string, using the format of the 'Set-Cookie' HTTP response header + Future setCookie(String url, String value) { + return _cookieManagerApi.setCookieFromInstances(this, url, value); + } + + /// Removes all cookies. + /// + /// The returned future resolves to true if any cookies were removed. + Future removeAllCookies() { + return _cookieManagerApi.removeAllCookiesFromInstances(this); + } + + /// Sets whether the WebView should allow third party cookies to be set. + /// + /// Apps that target `Build.VERSION_CODES.KITKAT` or below default to allowing + /// third party cookies. Apps targeting `Build.VERSION_CODES.LOLLIPOP` or + /// later default to disallowing third party cookies. + Future setAcceptThirdPartyCookies(WebView webView, bool accept) { + return _cookieManagerApi.setAcceptThirdPartyCookiesFromInstances( + this, + webView, + accept, + ); + } + + @override + CookieManager copy() { + return CookieManager.detached( + binaryMessenger: _cookieManagerApi.binaryMessenger, + instanceManager: _cookieManagerApi.instanceManager, + ); + } +} + +/// 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 extends OhosObject { + /// Constructs a [WebSettings]. + /// + /// This constructor is only used for testing. An instance should be obtained + /// with [WebView.settings]. + @visibleForTesting + WebSettings( + WebView webView, { + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + api.createFromInstance(this, webView); + } + + /// Constructs a [WebSettings] without creating the associated TS object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + WebSettings.detached({ + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// 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.setSupportMultipleWindowsFromInstance(this, support); + } + + /// Sets the background color of this WebView. + Future setBackgroundColor(Color color) { + return api.setBackgroundColorFromInstance(this, color.value); + } + + /// 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 Ohos 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 Ohos 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 Ohos so it's recommended to + /// disable [setDisplayZoomControls]. + Future setBuiltInZoomControls(bool enabled) { + return api.setBuiltInZoomControlsFromInstance(this, enabled); + } + + /// Enables or disables file access within WebView. + /// + /// This enables or disables file system access only. Assets and resources are + /// still accessible using file:///ohos_asset and file:///ohos_res. The + /// default value is true for apps targeting Build.VERSION_CODES.Q and below, + /// and false when targeting Build.VERSION_CODES.R and above. + Future setAllowFileAccess(bool enabled) { + return api.setAllowFileAccessFromInstance(this, enabled); + } + + /// Sets the text zoom of the page in percent. + /// + /// The default is 100. + Future setTextZoom(int textZoom) { + return api.setSetTextZoomFromInstance(this, textZoom); + } + + /// Gets the WebView's user-agent string. + Future getUserAgentString() { + return api.getUserAgentStringFromInstance(this); + } + + @override + WebSettings copy() { + return WebSettings.detached( + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// Exposes a channel to receive calls from javaScript. +/// +/// See [WebView.addJavaScriptChannel]. +class JavaScriptChannel extends OhosObject { + /// Constructs a [JavaScriptChannel]. + JavaScriptChannel( + this.channelName, { + required this.postMessage, + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + OhosWebViewFlutterApis.instance.ensureSetUp(); + api.createFromInstance(this); + } + + /// Constructs a [JavaScriptChannel] without creating the associated TS + /// object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + JavaScriptChannel.detached( + this.channelName, { + required this.postMessage, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// 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. + final void Function(String message) postMessage; + + @override + JavaScriptChannel copy() { + return JavaScriptChannel.detached( + channelName, + postMessage: postMessage, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// Receive various notifications and requests for [WebView]. +class WebViewClient extends OhosObject { + /// Constructs a [WebViewClient]. + WebViewClient({ + this.onPageStarted, + this.onPageFinished, + this.onReceivedHttpError, + this.onReceivedRequestError, + @Deprecated('Only called on Ohos version < 23.') this.onReceivedError, + this.requestLoading, + this.urlLoading, + this.doUpdateVisitedHistory, + this.onReceivedHttpAuthRequest, + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + OhosWebViewFlutterApis.instance.ensureSetUp(); + api.createFromInstance(this); + } + + /// Constructs a [WebViewClient] without creating the associated TS object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + WebViewClient.detached({ + this.onPageStarted, + this.onPageFinished, + this.onReceivedHttpError, + this.onReceivedRequestError, + @Deprecated('Only called on Ohos version < 23.') this.onReceivedError, + this.requestLoading, + this.urlLoading, + this.doUpdateVisitedHistory, + this.onReceivedHttpAuthRequest, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// @ohos.web.netErrorList (ArkWeb网络协议栈错误列表) + /// https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-neterrorlist-V5 + + /// User authentication failed on server. + static const int errorAuthentication = -100; + + /// Malformed URL. + static const int errorBadUrl = -300; + + /// Failed to connect to the server. + static const int errorConnect = -106; + + /// Failed to perform SSL handshake. + static const int errorFailedSslHandshake = -148; + + /// Generic file error. + static const int errorFile = -16; + + /// File not found. + static const int errorFileNotFound = -808; + + /// Server or proxy hostname lookup failed. + static const int errorHostLookup = -121; + + /// Failed to read or write to the server. + static const int errorIO = -1; + + /// User authentication failed on proxy. + static const int errorProxyAuthentication = -115; + + /// Too many redirects. + static const int errorRedirectLoop = -303; + + /// Connection timed out. + static const int errorTimeout = -409; + + /// Too many requests during this load. + static const int errorTooManyRequests = -114; + + /// Generic error. + static const int errorUnknown = -9; + + /// Resource load was canceled by Safe Browsing. + static const int errorUnsafeResource = -311; + + /// Unsupported authentication scheme (not basic or digest). + static const int errorUnsupportedAuthScheme = -339; + + /// Unsupported URI scheme. + static const int errorUnsupportedScheme = -301; + + /// Pigeon Host Api implementation for [WebViewClient]. + @visibleForTesting + static WebViewClientHostApiImpl api = WebViewClientHostApiImpl(); + + /// 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). + final void Function(WebView webView, String url)? onPageStarted; + + // 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. + final void Function(WebView webView, String url)? onPageFinished; + + /// Notify the host application that an HTTP error has been received from the + /// server while loading a resource. + /// + /// HTTP errors have status codes >= 400. This callback 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. + final void Function(WebView webView, WebResourceRequest request, + WebResourceResponse response)? onReceivedHttpError; + + /// 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. + final void Function( + WebView webView, + WebResourceRequest request, + WebResourceError error, + )? onReceivedRequestError; + + /// 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 Ohos version < 23.') + final void Function( + WebView webView, + int errorCode, + String description, + String failingUrl, + )? onReceivedError; + + /// When the current [WebView] wants to load a URL. + /// + /// The value set by [setSynchronousReturnValueForShouldOverrideUrlLoading] + /// indicates whether the [WebView] loaded the request. + final void Function(WebView webView, WebResourceRequest request)? + requestLoading; + + /// When the current [WebView] wants to load a URL. + /// + /// The value set by [setSynchronousReturnValueForShouldOverrideUrlLoading] + /// indicates whether the [WebView] loaded the URL. + final void Function(WebView webView, String url)? urlLoading; + + /// Notify the host application to update its visited links database. + final void Function(WebView webView, String url, bool isReload)? + doUpdateVisitedHistory; + + /// This callback is only called for requests that require HTTP authentication. + final void Function( + WebView webView, + HttpAuthHandler handler, + String host, + String realm, + )? onReceivedHttpAuthRequest; + + /// Sets the required synchronous return value for the TS method, + /// `WebViewClient.shouldOverrideUrlLoading(...)`. + /// + /// The TS method, `WebViewClient.shouldOverrideUrlLoading(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the TS method. + /// + /// Setting this to true causes the current [WebView] to abort loading any URL + /// received by [requestLoading] or [urlLoading], while setting this to false + /// causes the [WebView] to continue loading a URL as usual. + /// + /// Defaults to false. + Future setSynchronousReturnValueForShouldOverrideUrlLoading( + bool value, + ) { + return api.setShouldOverrideUrlLoadingReturnValueFromInstance(this, value); + } + + @override + WebViewClient copy() { + return WebViewClient.detached( + onPageStarted: onPageStarted, + onPageFinished: onPageFinished, + onReceivedHttpError: onReceivedHttpError, + onReceivedRequestError: onReceivedRequestError, + onReceivedError: onReceivedError, + requestLoading: requestLoading, + urlLoading: urlLoading, + doUpdateVisitedHistory: doUpdateVisitedHistory, + onReceivedHttpAuthRequest: onReceivedHttpAuthRequest, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// The interface to be used when content can not be handled by the rendering +/// engine for [WebView], and should be downloaded instead. +class DownloadListener extends OhosObject { + /// Constructs a [DownloadListener]. + DownloadListener({ + required this.onDownloadStart, + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + OhosWebViewFlutterApis.instance.ensureSetUp(); + api.createFromInstance(this); + } + + /// Constructs a [DownloadListener] without creating the associated TS + /// object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + DownloadListener.detached({ + required this.onDownloadStart, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Pigeon Host Api implementation for [DownloadListener]. + @visibleForTesting + static DownloadListenerHostApiImpl api = DownloadListenerHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + final void Function( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) onDownloadStart; + + @override + DownloadListener copy() { + return DownloadListener.detached( + onDownloadStart: onDownloadStart, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// Responsible for request the Geolocation API. +typedef GeolocationPermissionsShowPrompt = Future Function( + String origin, + GeolocationPermissionsCallback callback, +); + +/// Responsible for request the Geolocation API is Cancel. +typedef GeolocationPermissionsHidePrompt = void Function( + WebChromeClient instance, +); + +/// Signature for the callback that is responsible for showing a custom view. +typedef ShowCustomViewCallback = void Function( + WebChromeClient instance, + View view, + CustomViewCallback callback, +); + +/// Signature for the callback that is responsible for hiding a custom view. +typedef HideCustomViewCallback = void Function( + WebChromeClient instance, +); + +/// Handles JavaScript dialogs, favicons, titles, and the progress for [WebView]. +class WebChromeClient extends OhosObject { + /// Constructs a [WebChromeClient]. + WebChromeClient({ + this.onProgressChanged, + this.onShowFileChooser, + this.onPermissionRequest, + this.onGeolocationPermissionsShowPrompt, + this.onGeolocationPermissionsHidePrompt, + this.onShowCustomView, + this.onHideCustomView, + this.onConsoleMessage, + this.onJsAlert, + this.onJsConfirm, + this.onJsPrompt, + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + OhosWebViewFlutterApis.instance.ensureSetUp(); + api.createFromInstance(this); + } + + /// Constructs a [WebChromeClient] without creating the associated TS + /// object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + WebChromeClient.detached({ + this.onProgressChanged, + this.onShowFileChooser, + this.onPermissionRequest, + this.onGeolocationPermissionsShowPrompt, + this.onGeolocationPermissionsHidePrompt, + this.onShowCustomView, + this.onHideCustomView, + this.onConsoleMessage, + this.onJsAlert, + this.onJsConfirm, + this.onJsPrompt, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Pigeon Host Api implementation for [WebChromeClient]. + @visibleForTesting + static WebChromeClientHostApiImpl api = WebChromeClientHostApiImpl(); + + /// Notify the host application that a file should be downloaded. + final void Function(WebView webView, int progress)? onProgressChanged; + + /// Indicates the client should show a file chooser. + /// + /// To handle the request for a file chooser with this callback, passing true + /// to [setSynchronousReturnValueForOnShowFileChooser] is required. Otherwise, + /// the returned list of strings will be ignored and the client will use the + /// default handling of a file chooser request. + /// + /// Only invoked on Ohos versions 21+. + final Future> Function( + WebView webView, + FileChooserParams params, + )? onShowFileChooser; + + /// Notify the host application that web content is requesting permission to + /// access the specified resources and the permission currently isn't granted + /// or denied. + /// + /// Only invoked on Ohos versions 21+. + final void Function( + WebChromeClient instance, + PermissionRequest request, + )? onPermissionRequest; + + /// Indicates the client should handle geolocation permissions. + final GeolocationPermissionsShowPrompt? onGeolocationPermissionsShowPrompt; + + /// Notify the host application that a request for Geolocation permissions, + /// made with a previous call to [onGeolocationPermissionsShowPrompt] has been + /// canceled. + final GeolocationPermissionsHidePrompt? onGeolocationPermissionsHidePrompt; + + /// Notify the host application that the current page has entered full screen + /// mode. + /// + /// After this call, web content will no longer be rendered in the WebView, + /// but will instead be rendered in `view`. + final ShowCustomViewCallback? onShowCustomView; + + /// Notify the host application that the current page has exited full screen + /// mode. + final HideCustomViewCallback? onHideCustomView; + + /// Report a JavaScript console message to the host application. + final void Function(WebChromeClient instance, ConsoleMessage message)? + onConsoleMessage; + + /// Notify the host application that the web page wants to display a + /// JavaScript alert() dialog. + final Future Function(String url, String message)? onJsAlert; + + /// Notify the host application that the web page wants to display a + /// JavaScript confirm() dialog. + final Future Function(String url, String message)? onJsConfirm; + + /// Notify the host application that the web page wants to display a + /// JavaScript prompt() dialog. + final Future Function( + String url, String message, String defaultValue)? onJsPrompt; + + /// Sets the required synchronous return value for the TS method, + /// `WebChromeClient.onShowFileChooser(...)`. + /// + /// The TS method, `WebChromeClient.onShowFileChooser(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the TS method. + /// + /// Setting this to true indicates that all file chooser requests should be + /// handled by [onShowFileChooser] and the returned list of Strings will be + /// returned to the WebView. Otherwise, the client will use the default + /// handling and the returned value in [onShowFileChooser] will be ignored. + /// + /// Requires [onShowFileChooser] to be nonnull. + /// + /// Defaults to false. + Future setSynchronousReturnValueForOnShowFileChooser( + bool value, + ) { + if (value && onShowFileChooser == null) { + throw StateError( + 'Setting this to true requires `onShowFileChooser` to be nonnull.', + ); + } + return api.setSynchronousReturnValueForOnShowFileChooserFromInstance( + this, + value, + ); + } + + /// Sets the required synchronous return value for the Java method, + /// `WebChromeClient.onShowFileChooser(...)`. + /// + /// The Java method, `WebChromeClient.onConsoleMessage(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the Java method. + /// + /// Setting this to true indicates that the client is handling all console + /// messages. + /// + /// Requires [onConsoleMessage] to be nonnull. + /// + /// Defaults to false. + Future setSynchronousReturnValueForOnConsoleMessage( + bool value, + ) { + if (value && onConsoleMessage == null) { + throw StateError( + 'Setting this to true requires `onConsoleMessage` to be nonnull.', + ); + } + return api.setSynchronousReturnValueForOnConsoleMessageFromInstance( + this, + value, + ); + } + + /// Sets the required synchronous return value for the ets method, + /// `WebChromeClient.onJsAlert(...)`. + /// + /// The ets method, `WebChromeClient.onJsAlert(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the ets method. + /// + /// Setting this to true indicates that the client is handling all console + /// messages. + /// + /// Requires [onJsAlert] to be nonnull. + /// + /// Defaults to false. + Future setSynchronousReturnValueForOnJsAlert( + bool value, + ) { + if (value && onJsAlert == null) { + throw StateError( + 'Setting this to true requires `onJsAlert` to be nonnull.', + ); + } + return api.setSynchronousReturnValueForOnJsAlertFromInstance(this, value); + } + + /// Sets the required synchronous return value for the ets method, + /// `WebChromeClient.onJsConfirm(...)`. + /// + /// The ets method, `WebChromeClient.onJsConfirm(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the ets method. + /// + /// Setting this to true indicates that the client is handling all console + /// messages. + /// + /// Requires [onJsConfirm] to be nonnull. + /// + /// Defaults to false. + Future setSynchronousReturnValueForOnJsConfirm( + bool value, + ) { + if (value && onJsConfirm == null) { + throw StateError( + 'Setting this to true requires `onJsConfirm` to be nonnull.', + ); + } + return api.setSynchronousReturnValueForOnJsConfirmFromInstance(this, value); + } + + /// Sets the required synchronous return value for the ets method, + /// `WebChromeClient.onJsPrompt(...)`. + /// + /// The ets method, `WebChromeClient.onJsPrompt(...)`, requires + /// a boolean to be returned and this method sets the returned value for all + /// calls to the ets method. + /// + /// Setting this to true indicates that the client is handling all console + /// messages. + /// + /// Requires [onJsPrompt] to be nonnull. + /// + /// Defaults to false. + Future setSynchronousReturnValueForOnJsPrompt( + bool value, + ) { + if (value && onJsPrompt == null) { + throw StateError( + 'Setting this to true requires `onJsPrompt` to be nonnull.', + ); + } + return api.setSynchronousReturnValueForOnJsPromptFromInstance(this, value); + } + + @override + WebChromeClient copy() { + return WebChromeClient.detached( + onProgressChanged: onProgressChanged, + onShowFileChooser: onShowFileChooser, + onPermissionRequest: onPermissionRequest, + onGeolocationPermissionsShowPrompt: onGeolocationPermissionsShowPrompt, + onGeolocationPermissionsHidePrompt: onGeolocationPermissionsHidePrompt, + onShowCustomView: onShowCustomView, + onHideCustomView: onHideCustomView, + onConsoleMessage: onConsoleMessage, + onJsAlert: onJsAlert, + onJsConfirm: onJsConfirm, + onJsPrompt: onJsPrompt, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// This class defines a permission request and is used when web content +/// requests access to protected resources. +/// +/// Only supported on Ohos versions >= 21. +class PermissionRequest extends OhosObject { + /// Instantiates a [PermissionRequest] without creating and attaching to an + /// instance of the associated native class. + /// + /// This should only be used outside of tests by subclasses created by this + /// library or to create a copy for an [InstanceManager]. + @protected + PermissionRequest.detached({ + required this.resources, + required super.binaryMessenger, + required super.instanceManager, + }) : _permissionRequestApi = PermissionRequestHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + super.detached(); + + /// Resource belongs to audio capture device, like microphone. + static const String audioCapture = 'TYPE_AUDIO_CAPTURE'; + + /// Resource will allow sysex messages to be sent to or received from MIDI + /// devices. + static const String midiSysex = 'TYPE_MIDI_SYSEX'; + + /// Resource belongs to video capture device, like camera. + static const String videoCapture = 'TYPE_VIDEO_CAPTURE'; + + /// Resource belongs to protected media identifier. + static const String protectedMediaId = + 'ohos.webkit.resource.PROTECTED_MEDIA_ID'; + + final PermissionRequestHostApiImpl _permissionRequestApi; + + /// Resources the web page is trying to access. + final List resources; + + /// Call this method to get the resources the web page is trying to access. + Future grant(List resources) { + return _permissionRequestApi.grantFromInstances(this, resources); + } + + /// Call this method to grant origin the permission to access the given + /// resources. + Future deny() { + return _permissionRequestApi.denyFromInstances(this); + } + + @override + PermissionRequest copy() { + return PermissionRequest.detached( + resources: resources, + binaryMessenger: _permissionRequestApi.binaryMessenger, + instanceManager: _permissionRequestApi.instanceManager, + ); + } +} + +/// Parameters received when a [WebChromeClient] should show a file chooser. +class FileChooserParams extends OhosObject { + /// Constructs a [FileChooserParams] without creating the associated TS + /// object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + FileChooserParams.detached({ + required this.isCaptureEnabled, + required this.acceptTypes, + required this.filenameHint, + required this.mode, + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Preference for a live media captured value (e.g. Camera, Microphone). + final bool isCaptureEnabled; + + /// A list of acceptable MIME types. + final List acceptTypes; + + /// The file name of a default selection if specified, or null. + final String? filenameHint; + + /// Mode of how to select files for a file chooser. + final FileChooserMode mode; + + @override + FileChooserParams copy() { + return FileChooserParams.detached( + isCaptureEnabled: isCaptureEnabled, + acceptTypes: acceptTypes, + filenameHint: filenameHint, + mode: mode, + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// 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, + }); + + /// The URL for which the resource request was made. + final String url; + + /// Whether the request was made in order to fetch the main frame's document. + final bool isForMainFrame; + + /// Whether the request was a result of a server-side redirect. + /// + /// Only supported on Ohos version >= 24. + final bool? isRedirect; + + /// Whether a gesture (such as a click) was associated with the request. + final bool hasGesture; + + /// The method associated with the request, for example "GET". + final String method; + + /// The headers associated with the request. + final Map requestHeaders; +} + +/// Encapsulates information about the web resource response. +/// +/// See [WebViewClient.onReceivedHttpError]. +class WebResourceResponse { + /// Constructs a [WebResourceResponse]. + WebResourceResponse({ + required this.statusCode, + }); + + /// The HTTP status code associated with the response. + final int statusCode; +} + +/// 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; +} + +/// Manages Flutter assets that are part of Ohos's app bundle. +class FlutterAssetManager { + /// Constructs the [FlutterAssetManager]. + const FlutterAssetManager(); + + /// Pigeon Host Api implementation for [FlutterAssetManager]. + @visibleForTesting + static FlutterAssetManagerHostApi api = FlutterAssetManagerHostApi(); + + /// Lists all assets at the given path. + /// + /// The assets are returned as a `List`. The `List` only + /// contains files which are direct childs + Future> list(String path) => api.list(path); + + /// Gets the relative file path to the Flutter asset with the given name. + Future getAssetFilePathByName(String name) => + api.getAssetFilePathByName(name); +} + +/// Manages the JavaScript storage APIs provided by the [WebView]. +class WebStorage extends OhosObject { + /// Constructs a [WebStorage]. + /// + /// This constructor is only used for testing. An instance should be obtained + /// with [WebStorage.instance]. + @visibleForTesting + WebStorage({ + @visibleForTesting super.binaryMessenger, + @visibleForTesting super.instanceManager, + }) : super.detached() { + OhosWebViewFlutterApis.instance.ensureSetUp(); + api.createFromInstance(this); + } + + /// Constructs a [WebStorage] without creating the associated TS object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies. + @protected + WebStorage.detached({ + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Pigeon Host Api implementation for [WebStorage]. + @visibleForTesting + static WebStorageHostApiImpl api = WebStorageHostApiImpl(); + + /// The singleton instance of this class. + static WebStorage instance = WebStorage(); + + /// Clears all storage currently being used by the JavaScript storage APIs. + Future deleteAllData() { + return api.deleteAllDataFromInstance(this); + } + + @override + WebStorage copy() { + return WebStorage.detached( + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// The basic building block for user interface components. +/// +/// See https://developer.android.com/reference/android/view/View. +class View extends OhosObject { + /// Instantiates a [View] without creating and attaching to an + /// instance of the associated native class. + /// + /// This should only be used outside of tests by subclasses created by this + /// library or to create a copy for an [InstanceManager]. + @protected + View.detached({super.binaryMessenger, super.instanceManager}) + : super.detached(); + + @override + View copy() { + return View.detached( + binaryMessenger: _api.binaryMessenger, + instanceManager: _api.instanceManager, + ); + } +} + +/// A callback interface used by the host application to notify the current page +/// that its custom view has been dismissed. +/// +/// See https://developer.android.com/reference/android/webkit/WebChromeClient.CustomViewCallback. +class CustomViewCallback extends OhosObject { + /// Instantiates a [CustomViewCallback] without creating and attaching to an + /// instance of the associated native class. + /// + /// This should only be used outside of tests by subclasses created by this + /// library or to create a copy for an [InstanceManager]. + @protected + CustomViewCallback.detached({ + super.binaryMessenger, + super.instanceManager, + }) : _customViewCallbackApi = CustomViewCallbackHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + super.detached(); + + final CustomViewCallbackHostApiImpl _customViewCallbackApi; + + /// Invoked when the host application dismisses the custom view. + Future onCustomViewHidden() { + return _customViewCallbackApi.onCustomViewHiddenFromInstances(this); + } + + @override + CustomViewCallback copy() { + return CustomViewCallback.detached( + binaryMessenger: _customViewCallbackApi.binaryMessenger, + instanceManager: _customViewCallbackApi.instanceManager, + ); + } +} + +/// Represents a request for HTTP authentication. +/// +/// Instances of this class are created by the [WebView] and passed to +/// [WebViewClient.onReceivedHttpAuthRequest]. The host application must call +/// either [HttpAuthHandler.proceed] or [HttpAuthHandler.cancel] to set the +/// WebView's response to the request. +class HttpAuthHandler extends OhosObject { + /// Constructs a [HttpAuthHandler]. + HttpAuthHandler({ + super.binaryMessenger, + super.instanceManager, + }) : super.detached(); + + /// Pigeon Host Api implementation for [HttpAuthHandler]. + @visibleForTesting + static HttpAuthHandlerHostApiImpl api = HttpAuthHandlerHostApiImpl(); + + /// Instructs the WebView to cancel the authentication request. + Future cancel() { + return api.cancelFromInstance(this); + } + + /// Instructs the WebView to proceed with the authentication with the provided + /// credentials. + Future proceed(String username, String password) { + return api.proceedFromInstance(this, username, password); + } + + /// Gets whether the credentials stored for the current host are suitable for + /// use. + /// + /// Credentials are not suitable if they have previously been rejected by the + /// server for the current request. + Future useHttpAuthUsernamePassword() { + return api.useHttpAuthUsernamePasswordFromInstance(this); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.g.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.g.dart new file mode 100644 index 0000000000000000000000000000000000000000..510ef95e109e0389905cf88013d9ffe183e84aab --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview.g.dart @@ -0,0 +1,3211 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +/// Mode of how to select files for a file chooser. +enum FileChooserMode { + /// Open single file and requires that the file exists before allowing the + /// user to pick it. + open, + + /// Similar to [open] but allows multiple files to be selected. + openMultiple, + + /// Allows picking a nonexistent file and saving it. + save, +} + +/// Indicates the type of message logged to the console. +/// +/// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel. +enum ConsoleMessageLevel { + /// Indicates a message is logged for debugging. + /// + /// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel#DEBUG. + debug, + + /// Indicates a message is provided as an error. + /// + /// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel#ERROR. + error, + + /// Indicates a message is provided as a basic log message. + /// + /// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel#LOG. + log, + + /// Indicates a message is provided as a tip. + /// + /// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel#TIP. + tip, + + /// Indicates a message is provided as a warning. + /// + /// See https://developer.android.com/reference/android/webkit/ConsoleMessage.MessageLevel#WARNING. + warning, + + /// Indicates a message with an unknown level. + /// + /// This does not represent an actual value provided by the platform and only + /// indicates a value was provided that isn't currently supported. + unknown, +} + +class WebResourceRequestData { + WebResourceRequestData({ + required this.url, + required this.isForMainFrame, + this.isRedirect, + required this.hasGesture, + required this.method, + required this.requestHeaders, + }); + + String url; + + bool isForMainFrame; + + bool? isRedirect; + + bool hasGesture; + + String method; + + Map requestHeaders; + + Object encode() { + return [ + url, + isForMainFrame, + isRedirect, + hasGesture, + method, + requestHeaders, + ]; + } + + static WebResourceRequestData decode(Object result) { + result as List; + return WebResourceRequestData( + url: result[0]! as String, + isForMainFrame: result[1]! as bool, + isRedirect: result[2] as bool?, + hasGesture: result[3]! as bool, + method: result[4]! as String, + requestHeaders: + (result[5] as Map?)!.cast(), + ); + } +} + +class WebResourceResponseData { + WebResourceResponseData({ + required this.statusCode, + }); + + int statusCode; + + Object encode() { + return [ + statusCode, + ]; + } + + static WebResourceResponseData decode(Object result) { + result as List; + return WebResourceResponseData( + statusCode: result[0]! as int, + ); + } +} + +class WebResourceErrorData { + WebResourceErrorData({ + required this.errorCode, + required this.description, + }); + + int errorCode; + + String description; + + Object encode() { + return [ + errorCode, + description, + ]; + } + + static WebResourceErrorData decode(Object result) { + result as List; + return WebResourceErrorData( + errorCode: result[0]! as int, + description: result[1]! as String, + ); + } +} + +class WebViewPoint { + WebViewPoint({ + required this.x, + required this.y, + }); + + int x; + + int y; + + Object encode() { + return [ + x, + y, + ]; + } + + static WebViewPoint decode(Object result) { + result as List; + return WebViewPoint( + x: result[0]! as int, + y: result[1]! as int, + ); + } +} + +/// Represents a JavaScript console message from WebCore. +/// +/// See https://developer.android.com/reference/android/webkit/ConsoleMessage +class ConsoleMessage { + ConsoleMessage({ + required this.lineNumber, + required this.message, + required this.level, + required this.sourceId, + }); + + int lineNumber; + + String message; + + ConsoleMessageLevel level; + + String sourceId; + + Object encode() { + return [ + lineNumber, + message, + level.index, + sourceId, + ]; + } + + static ConsoleMessage decode(Object result) { + result as List; + return ConsoleMessage( + lineNumber: result[0]! as int, + message: result[1]! as String, + level: ConsoleMessageLevel.values[result[2]! as int], + sourceId: result[3]! as String, + ); + } +} + +/// Host API for managing the native `InstanceManager`. +class InstanceManagerHostApi { + /// Constructor for [InstanceManagerHostApi]. 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. + InstanceManagerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Clear the native `InstanceManager`. + /// + /// This is typically only used after a hot restart. + Future clear() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.InstanceManagerHostApi.clear', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send(null) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Handles methods calls to the native TS Object class. +/// +/// Also handles calls to remove the reference to an instance with `dispose`. +class OhosObjectHostApi { + /// Constructor for [OhosObjectHostApi]. 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. + OhosObjectHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future dispose(int arg_identifier) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.OhosObjectHostApi.dispose', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_identifier]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Handles callbacks methods for the native TS Object class. +abstract class OhosObjectFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + void dispose(int identifier); + + static void setup(OhosObjectFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.OhosObjectFlutterApi.dispose', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.OhosObjectFlutterApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.OhosObjectFlutterApi.dispose was null, expected non-null int.'); + api.dispose(arg_identifier!); + return; + }); + } + } + } +} + +/// Host API for `CookieManager`. +/// +/// This class may handle instantiating and adding native object instances that +/// are attached to a Dart instance or handle method calls on the associated +/// native class or an instance of the class. +class CookieManagerHostApi { + /// Constructor for [CookieManagerHostApi]. 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. + CookieManagerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Handles attaching `CookieManager.instance` to a native instance. + Future attachInstance(int arg_instanceIdentifier) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.attachInstance', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceIdentifier]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// Handles Dart method `CookieManager.setCookie`. + Future setCookie( + int arg_identifier, String arg_url, String arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.setCookie', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_identifier, arg_url, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// Handles Dart method `CookieManager.removeAllCookies`. + Future removeAllCookies(int arg_identifier) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.removeAllCookies', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_identifier]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as bool?)!; + } + } + + /// Handles Dart method `CookieManager.setAcceptThirdPartyCookies`. + Future setAcceptThirdPartyCookies( + int arg_identifier, int arg_webViewIdentifier, bool arg_accept) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.setAcceptThirdPartyCookies', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_identifier, arg_webViewIdentifier, arg_accept]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +class _WebViewHostApiCodec extends StandardMessageCodec { + const _WebViewHostApiCodec(); + + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is WebViewPoint) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return WebViewPoint.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +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) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.create', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future loadData(int arg_instanceId, String arg_data, + String? arg_mimeType, String? arg_encoding) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadData', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send( + [arg_instanceId, arg_data, arg_mimeType, arg_encoding]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future loadDataWithBaseUrl( + int arg_instanceId, + String? arg_baseUrl, + String arg_data, + String? arg_mimeType, + String? arg_encoding, + String? arg_historyUrl) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadDataWithBaseUrl', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel.send([ + arg_instanceId, + arg_baseUrl, + arg_data, + arg_mimeType, + arg_encoding, + arg_historyUrl + ]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future loadUrl(int arg_instanceId, String arg_url, + Map arg_headers) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadUrl', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_url, arg_headers]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future postUrl( + int arg_instanceId, String arg_url, Uint8List arg_data) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.postUrl', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_url, arg_data]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future getUrl(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getUrl', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as String?); + } + } + + Future canGoBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.canGoBack', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as bool?)!; + } + } + + Future canGoForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.canGoForward', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as bool?)!; + } + } + + Future goBack(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.goBack', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future goForward(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.goForward', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future reload(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.reload', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future clearCache(int arg_instanceId, bool arg_includeDiskFiles) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.clearCache', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_includeDiskFiles]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future evaluateJavascript( + int arg_instanceId, String arg_javascriptString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.evaluateJavascript', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_javascriptString]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as String?); + } + } + + Future getTitle(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getTitle', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return (replyList[0] as String?); + } + } + + Future scrollTo(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.scrollTo', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_x, arg_y]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future scrollBy(int arg_instanceId, int arg_x, int arg_y) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.scrollBy', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_x, arg_y]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future getScrollX(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollX', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as int?)!; + } + } + + Future getScrollY(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollY', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as int?)!; + } + } + + Future getScrollPosition(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollPosition', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as WebViewPoint?)!; + } + } + + Future setWebContentsDebuggingEnabled(bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebContentsDebuggingEnabled', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_enabled]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setWebViewClient( + int arg_instanceId, int arg_webViewClientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebViewClient', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_webViewClientInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future addJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.addJavaScriptChannel', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future removeJavaScriptChannel( + int arg_instanceId, int arg_javaScriptChannelInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.removeJavaScriptChannel', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_javaScriptChannelInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setDownloadListener( + int arg_instanceId, int? arg_listenerInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setDownloadListener', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_listenerInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setWebChromeClient( + int arg_instanceId, int? arg_clientInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebChromeClient', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_clientInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Flutter API for `WebView`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +abstract class WebViewFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int identifier); + + void onScrollChanged( + int webViewInstanceId, int left, int top, int oldLeft, int oldTop); + + static void setup(WebViewFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.create was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.create was null, expected non-null int.'); + api.create(arg_identifier!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null.'); + final List args = (message as List?)!; + final int? arg_webViewInstanceId = (args[0] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null, expected non-null int.'); + final int? arg_left = (args[1] as int?); + assert(arg_left != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null, expected non-null int.'); + final int? arg_top = (args[2] as int?); + assert(arg_top != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null, expected non-null int.'); + final int? arg_oldLeft = (args[3] as int?); + assert(arg_oldLeft != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null, expected non-null int.'); + final int? arg_oldTop = (args[4] as int?); + assert(arg_oldTop != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.onScrollChanged was null, expected non-null int.'); + api.onScrollChanged(arg_webViewInstanceId!, arg_left!, arg_top!, + arg_oldLeft!, arg_oldTop!); + return; + }); + } + } + } +} + +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 = StandardMessageCodec(); + + Future create(int arg_instanceId, int arg_webViewInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId, arg_webViewInstanceId]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setDomStorageEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setDomStorageEnabled', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_flag]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setJavaScriptCanOpenWindowsAutomatically( + int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_flag]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSupportMultipleWindows( + int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setSupportMultipleWindows', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_support]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setBackgroundColor(int arg_instanceId, int arg_color) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setBackgroundColor', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_color]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setJavaScriptEnabled(int arg_instanceId, bool arg_flag) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setJavaScriptEnabled', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_flag]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setUserAgentString( + int arg_instanceId, String? arg_userAgentString) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setUserAgentString', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_userAgentString]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setMediaPlaybackRequiresUserGesture( + int arg_instanceId, bool arg_require) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_require]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSupportZoom(int arg_instanceId, bool arg_support) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setSupportZoom', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_support]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setLoadWithOverviewMode( + int arg_instanceId, bool arg_overview) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setLoadWithOverviewMode', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_overview]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setUseWideViewPort(int arg_instanceId, bool arg_use) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setUseWideViewPort', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_use]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setDisplayZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setDisplayZoomControls', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_enabled]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setBuiltInZoomControls( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setBuiltInZoomControls', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_enabled]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setAllowFileAccess(int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setAllowFileAccess', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_enabled]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setTextZoom(int arg_instanceId, int arg_textZoom) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setTextZoom', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_textZoom]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future getUserAgentString(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.getUserAgentString', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } +} + +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 = StandardMessageCodec(); + + Future create(int arg_instanceId, String arg_channelName) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.JavaScriptChannelHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_channelName]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +abstract class JavaScriptChannelFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + void postMessage(int instanceId, String message); + + static void setup(JavaScriptChannelFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.JavaScriptChannelFlutterApi.postMessage', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.JavaScriptChannelFlutterApi.postMessage was null, expected non-null String.'); + api.postMessage(arg_instanceId!, arg_message!); + return; + }); + } + } + } +} + +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 = StandardMessageCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForShouldOverrideUrlLoading( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientHostApi.setSynchronousReturnValueForShouldOverrideUrlLoading', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } 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 WebResourceResponseData) { + 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 WebResourceResponseData.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 onReceivedHttpError(int instanceId, int webViewInstanceId, + WebResourceRequestData request, WebResourceResponseData response); + + 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); + + void doUpdateVisitedHistory( + int instanceId, int webViewInstanceId, String url, bool isReload); + + void onReceivedHttpAuthRequest(int instanceId, int webViewInstanceId, + int httpAuthHandlerInstanceId, String host, String realm); + + static void setup(WebViewClientFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onPageStarted', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.onPageStarted was null, expected non-null String.'); + api.onPageStarted(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onPageFinished', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.onPageFinished was null, expected non-null String.'); + api.onPageFinished(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError 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.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError was null, expected non-null int.'); + final WebResourceRequestData? arg_request = + (args[2] as WebResourceRequestData?); + assert(arg_request != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError was null, expected non-null WebResourceRequestData.'); + final WebResourceResponseData? arg_response = + (args[3] as WebResourceResponseData?); + assert(arg_response != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError was null, expected non-null WebResourceResponseData.'); + api.onReceivedHttpError(arg_instanceId!, arg_webViewInstanceId!, + arg_request!, arg_response!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedRequestError', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedRequestError was null, expected non-null WebResourceErrorData.'); + api.onReceivedRequestError(arg_instanceId!, arg_webViewInstanceId!, + arg_request!, arg_error!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedError', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedError was null, expected non-null String.'); + api.onReceivedError(arg_instanceId!, arg_webViewInstanceId!, + arg_errorCode!, arg_description!, arg_failingUrl!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.requestLoading', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.requestLoading was null, expected non-null WebResourceRequestData.'); + api.requestLoading( + arg_instanceId!, arg_webViewInstanceId!, arg_request!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.urlLoading', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebViewClientFlutterApi.urlLoading was null, expected non-null String.'); + api.urlLoading(arg_instanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory 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.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory was null, expected non-null int.'); + final String? arg_url = (args[2] as String?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory was null, expected non-null String.'); + final bool? arg_isReload = (args[3] as bool?); + assert(arg_isReload != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory was null, expected non-null bool.'); + api.doUpdateVisitedHistory( + arg_instanceId!, arg_webViewInstanceId!, arg_url!, arg_isReload!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest 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.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest was null, expected non-null int.'); + final int? arg_httpAuthHandlerInstanceId = (args[2] as int?); + assert(arg_httpAuthHandlerInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest was null, expected non-null int.'); + final String? arg_host = (args[3] as String?); + assert(arg_host != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest was null, expected non-null String.'); + final String? arg_realm = (args[4] as String?); + assert(arg_realm != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest was null, expected non-null String.'); + api.onReceivedHttpAuthRequest(arg_instanceId!, arg_webViewInstanceId!, + arg_httpAuthHandlerInstanceId!, arg_host!, arg_realm!); + return; + }); + } + } + } +} + +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 = StandardMessageCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.DownloadListenerHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +abstract class DownloadListenerFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + void onDownloadStart(int instanceId, String url, String userAgent, + String contentDisposition, String mimetype, int contentLength); + + static void setup(DownloadListenerFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.DownloadListenerFlutterApi.onDownloadStart', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.DownloadListenerFlutterApi.onDownloadStart was null, expected non-null int.'); + api.onDownloadStart(arg_instanceId!, arg_url!, arg_userAgent!, + arg_contentDisposition!, arg_mimetype!, arg_contentLength!); + return; + }); + } + } + } +} + +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 = StandardMessageCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForOnShowFileChooser( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnShowFileChooser', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForOnConsoleMessage( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnConsoleMessage', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForOnJsAlert( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsAlert', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForOnJsConfirm( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsConfirm', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future setSynchronousReturnValueForOnJsPrompt( + int arg_instanceId, bool arg_value) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsPrompt', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_value]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +class FlutterAssetManagerHostApi { + /// Constructor for [FlutterAssetManagerHostApi]. 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. + FlutterAssetManagerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future> list(String arg_path) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.FlutterAssetManagerHostApi.list', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_path]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as List?)!.cast(); + } + } + + Future getAssetFilePathByName(String arg_name) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.FlutterAssetManagerHostApi.getAssetFilePathByName', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_name]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as String?)!; + } + } +} + +class _WebChromeClientFlutterApiCodec extends StandardMessageCodec { + const _WebChromeClientFlutterApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is ConsoleMessage) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return ConsoleMessage.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class WebChromeClientFlutterApi { + static const MessageCodec codec = _WebChromeClientFlutterApiCodec(); + + void onProgressChanged(int instanceId, int webViewInstanceId, int progress); + + Future> onShowFileChooser( + int instanceId, int webViewInstanceId, int paramsInstanceId); + + /// Callback to Dart function `WebChromeClient.onPermissionRequest`. + void onPermissionRequest(int instanceId, int requestInstanceId); + + /// Callback to Dart function `WebChromeClient.onShowCustomView`. + void onShowCustomView( + int instanceId, int viewIdentifier, int callbackIdentifier); + + /// Callback to Dart function `WebChromeClient.onHideCustomView`. + void onHideCustomView(int instanceId); + + /// Callback to Dart function `WebChromeClient.onGeolocationPermissionsShowPrompt`. + void onGeolocationPermissionsShowPrompt( + int instanceId, int paramsInstanceId, String origin); + + /// Callback to Dart function `WebChromeClient.onGeolocationPermissionsHidePrompt`. + void onGeolocationPermissionsHidePrompt(int identifier); + + /// Callback to Dart function `WebChromeClient.onConsoleMessage`. + void onConsoleMessage(int instanceId, ConsoleMessage message); + + Future onJsAlert(int instanceId, String url, String message); + + Future onJsConfirm(int instanceId, String url, String message); + + Future onJsPrompt( + int instanceId, String url, String message, String defaultValue); + + static void setup(WebChromeClientFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onProgressChanged', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.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.webview_flutter_ohos.WebChromeClientFlutterApi.onProgressChanged was null, expected non-null int.'); + api.onProgressChanged( + arg_instanceId!, arg_webViewInstanceId!, arg_progress!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser 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.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser was null, expected non-null int.'); + final int? arg_paramsInstanceId = (args[2] as int?); + assert(arg_paramsInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser was null, expected non-null int.'); + final List output = await api.onShowFileChooser( + arg_instanceId!, arg_webViewInstanceId!, arg_paramsInstanceId!); + return output; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onPermissionRequest', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onPermissionRequest 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.webview_flutter_ohos.WebChromeClientFlutterApi.onPermissionRequest was null, expected non-null int.'); + final int? arg_requestInstanceId = (args[1] as int?); + assert(arg_requestInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onPermissionRequest was null, expected non-null int.'); + api.onPermissionRequest(arg_instanceId!, arg_requestInstanceId!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView 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.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView was null, expected non-null int.'); + final int? arg_viewIdentifier = (args[1] as int?); + assert(arg_viewIdentifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView was null, expected non-null int.'); + final int? arg_callbackIdentifier = (args[2] as int?); + assert(arg_callbackIdentifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView was null, expected non-null int.'); + api.onShowCustomView( + arg_instanceId!, arg_viewIdentifier!, arg_callbackIdentifier!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onHideCustomView', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onHideCustomView 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.webview_flutter_ohos.WebChromeClientFlutterApi.onHideCustomView was null, expected non-null int.'); + api.onHideCustomView(arg_instanceId!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt 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.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt was null, expected non-null int.'); + final int? arg_paramsInstanceId = (args[1] as int?); + assert(arg_paramsInstanceId != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt was null, expected non-null int.'); + final String? arg_origin = (args[2] as String?); + assert(arg_origin != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt was null, expected non-null String.'); + api.onGeolocationPermissionsShowPrompt( + arg_instanceId!, arg_paramsInstanceId!, arg_origin!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsHidePrompt', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsHidePrompt was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsHidePrompt was null, expected non-null int.'); + api.onGeolocationPermissionsHidePrompt(arg_identifier!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onConsoleMessage', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onConsoleMessage 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.webview_flutter_ohos.WebChromeClientFlutterApi.onConsoleMessage was null, expected non-null int.'); + final ConsoleMessage? arg_message = (args[1] as ConsoleMessage?); + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onConsoleMessage was null, expected non-null ConsoleMessage.'); + api.onConsoleMessage(arg_instanceId!, arg_message!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert 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.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert was null, expected non-null int.'); + final String? arg_url = (args[1] as String?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert was null, expected non-null String.'); + final String? arg_message = (args[2] as String?); + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert was null, expected non-null String.'); + await api.onJsAlert(arg_instanceId!, arg_url!, arg_message!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm 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.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm was null, expected non-null int.'); + final String? arg_url = (args[1] as String?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm was null, expected non-null String.'); + final String? arg_message = (args[2] as String?); + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm was null, expected non-null String.'); + final bool output = + await api.onJsConfirm(arg_instanceId!, arg_url!, arg_message!); + return output; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt 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.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt was null, expected non-null int.'); + final String? arg_url = (args[1] as String?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt was null, expected non-null String.'); + final String? arg_message = (args[2] as String?); + assert(arg_message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt was null, expected non-null String.'); + final String? arg_defaultValue = (args[3] as String?); + assert(arg_defaultValue != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt was null, expected non-null String.'); + final String output = await api.onJsPrompt( + arg_instanceId!, arg_url!, arg_message!, arg_defaultValue!); + return output; + }); + } + } + } +} + +class WebStorageHostApi { + /// Constructor for [WebStorageHostApi]. 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. + WebStorageHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + Future create(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebStorageHostApi.create', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + Future deleteAllData(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.WebStorageHostApi.deleteAllData', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Handles callbacks methods for the native TS FileChooserParams class. +abstract class FileChooserParamsFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + void create(int instanceId, bool isCaptureEnabled, List acceptTypes, + FileChooserMode mode, String? filenameHint); + + static void setup(FileChooserParamsFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.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.webview_flutter_ohos.FileChooserParamsFlutterApi.create was null, expected non-null int.'); + final bool? arg_isCaptureEnabled = (args[1] as bool?); + assert(arg_isCaptureEnabled != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.create was null, expected non-null bool.'); + final List? arg_acceptTypes = + (args[2] as List?)?.cast(); + assert(arg_acceptTypes != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.create was null, expected non-null List.'); + final FileChooserMode? arg_mode = + args[3] == null ? null : FileChooserMode.values[args[3]! as int]; + assert(arg_mode != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.create was null, expected non-null FileChooserModeEnumData.'); + final String? arg_filenameHint = (args[4] as String?); + api.create(arg_instanceId!, arg_isCaptureEnabled!, arg_acceptTypes!, + arg_mode!, arg_filenameHint); + return; + }); + } + } + } +} + +/// Host API for `PermissionRequest`. +/// +/// This class may handle instantiating and adding native object instances that +/// are attached to a Dart instance or handle method calls on the associated +/// native class or an instance of the class. +class PermissionRequestHostApi { + /// Constructor for [PermissionRequestHostApi]. 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. + PermissionRequestHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Handles Dart method `PermissionRequest.grant`. + Future grant(int arg_instanceId, List arg_resources) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestHostApi.grant', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_resources]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// Handles Dart method `PermissionRequest.deny`. + Future deny(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestHostApi.deny', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Flutter API for `PermissionRequest`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +abstract class PermissionRequestFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int instanceId, List resources); + + static void setup(PermissionRequestFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestFlutterApi.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.webview_flutter_ohos.PermissionRequestFlutterApi.create was null, expected non-null int.'); + final List? arg_resources = + (args[1] as List?)?.cast(); + assert(arg_resources != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestFlutterApi.create was null, expected non-null List.'); + api.create(arg_instanceId!, arg_resources!); + return; + }); + } + } + } +} + +/// Host API for `CustomViewCallback`. +/// +/// This class may handle instantiating and adding native object instances that +/// are attached to a Dart instance or handle method calls on the associated +/// native class or an instance of the class. +/// +/// See https://developer.android.com/reference/android/webkit/WebChromeClient.CustomViewCallback. +class CustomViewCallbackHostApi { + /// Constructor for [CustomViewCallbackHostApi]. 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. + CustomViewCallbackHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Handles Dart method `CustomViewCallback.onCustomViewHidden`. + Future onCustomViewHidden(int arg_identifier) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackHostApi.onCustomViewHidden', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_identifier]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Flutter API for `CustomViewCallback`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +/// +/// See https://developer.android.com/reference/android/webkit/WebChromeClient.CustomViewCallback. +abstract class CustomViewCallbackFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int identifier); + + static void setup(CustomViewCallbackFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackFlutterApi.create was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackFlutterApi.create was null, expected non-null int.'); + api.create(arg_identifier!); + return; + }); + } + } + } +} + +/// Flutter API for `View`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +/// +/// See https://developer.android.com/reference/android/view/View. +abstract class ViewFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int identifier); + + static void setup(ViewFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.ViewFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.ViewFlutterApi.create was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.ViewFlutterApi.create was null, expected non-null int.'); + api.create(arg_identifier!); + return; + }); + } + } + } +} + +/// Host API for `GeolocationPermissionsCallback`. +/// +/// This class may handle instantiating and adding native object instances that +/// are attached to a Dart instance or handle method calls on the associated +/// native class or an instance of the class. +class GeolocationPermissionsCallbackHostApi { + /// Constructor for [GeolocationPermissionsCallbackHostApi]. 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. + GeolocationPermissionsCallbackHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Handles Dart method `GeolocationPermissionsCallback.invoke`. + Future invoke(int arg_instanceId, String arg_origin, bool arg_allow, + bool arg_retain) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.GeolocationPermissionsCallbackHostApi.invoke', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_origin, arg_allow, arg_retain]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Flutter API for `GeolocationPermissionsCallback`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +abstract class GeolocationPermissionsCallbackFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int instanceId); + + static void setup(GeolocationPermissionsCallbackFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.GeolocationPermissionsCallbackFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.GeolocationPermissionsCallbackFlutterApi.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.webview_flutter_ohos.GeolocationPermissionsCallbackFlutterApi.create was null, expected non-null int.'); + api.create(arg_instanceId!); + return; + }); + } + } + } +} + +/// Host API for `HttpAuthHandler`. +/// +/// This class may handle instantiating and adding native object instances that +/// are attached to a Dart instance or handle method calls on the associated +/// native class or an instance of the class. +/// +/// See https://developer.android.com/reference/android/webkit/HttpAuthHandler. +class HttpAuthHandlerHostApi { + /// Constructor for [HttpAuthHandlerHostApi]. 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. + HttpAuthHandlerHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = StandardMessageCodec(); + + /// Handles Dart method `HttpAuthHandler.useHttpAuthUsernamePassword`. + Future useHttpAuthUsernamePassword(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.useHttpAuthUsernamePassword', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as bool?)!; + } + } + + /// Handles Dart method `HttpAuthHandler.cancel`. + Future cancel(int arg_instanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.cancel', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send([arg_instanceId]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } + + /// Handles Dart method `HttpAuthHandler.proceed`. + Future proceed( + int arg_instanceId, String arg_username, String arg_password) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.proceed', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_username, arg_password]) + as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } +} + +/// Flutter API for `HttpAuthHandler`. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +/// +/// See https://developer.android.com/reference/android/webkit/HttpAuthHandler. +abstract class HttpAuthHandlerFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + /// Create a new Dart instance and add it to the `InstanceManager`. + void create(int instanceId); + + static void setup(HttpAuthHandlerFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerFlutterApi.create', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerFlutterApi.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.webview_flutter_ohos.HttpAuthHandlerFlutterApi.create was null, expected non-null int.'); + api.create(arg_instanceId!); + return; + }); + } + } + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_api_impls.dart new file mode 100644 index 0000000000000000000000000000000000000000..875b8986e7547a1478ee15af301d5015da1b1987 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_api_impls.dart @@ -0,0 +1,1606 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:ui'; + +import 'package:flutter/services.dart' show BinaryMessenger, Uint8List; + +import 'ohos_webview.dart'; +import 'ohos_webview.g.dart'; +import 'instance_manager.dart'; + +export 'ohos_webview.g.dart' + show ConsoleMessage, ConsoleMessageLevel, FileChooserMode; + +/// Converts [WebResourceRequestData] to [WebResourceRequest] +WebResourceRequest _toWebResourceRequest(WebResourceRequestData data) { + return WebResourceRequest( + url: data.url, + isForMainFrame: data.isForMainFrame, + isRedirect: data.isRedirect, + hasGesture: data.hasGesture, + method: data.method, + requestHeaders: data.requestHeaders.cast(), + ); +} + +/// Converts [WebResourceResponseData] to [WebResourceResponse] +WebResourceResponse _toWebResourceResponse(WebResourceResponseData data) { + return WebResourceResponse( + statusCode: data.statusCode, + ); +} + +/// Converts [WebResourceErrorData] to [WebResourceError]. +WebResourceError _toWebResourceError(WebResourceErrorData data) { + return WebResourceError( + errorCode: data.errorCode, + description: data.description, + ); +} + +/// Handles initialization of Flutter APIs for Ohos WebView. +class OhosWebViewFlutterApis { + /// Creates a [OhosWebViewFlutterApis]. + OhosWebViewFlutterApis({ + OhosObjectFlutterApiImpl? ohosObjectFlutterApi, + DownloadListenerFlutterApiImpl? downloadListenerFlutterApi, + WebViewClientFlutterApiImpl? webViewClientFlutterApi, + WebChromeClientFlutterApiImpl? webChromeClientFlutterApi, + JavaScriptChannelFlutterApiImpl? javaScriptChannelFlutterApi, + FileChooserParamsFlutterApiImpl? fileChooserParamsFlutterApi, + GeolocationPermissionsCallbackFlutterApiImpl? + geolocationPermissionsCallbackFlutterApi, + WebViewFlutterApiImpl? webViewFlutterApi, + PermissionRequestFlutterApiImpl? permissionRequestFlutterApi, + CustomViewCallbackFlutterApiImpl? customViewCallbackFlutterApi, + ViewFlutterApiImpl? viewFlutterApi, + HttpAuthHandlerFlutterApiImpl? httpAuthHandlerFlutterApi, + }) { + this.ohosObjectFlutterApi = + ohosObjectFlutterApi ?? OhosObjectFlutterApiImpl(); + this.downloadListenerFlutterApi = + downloadListenerFlutterApi ?? DownloadListenerFlutterApiImpl(); + this.webViewClientFlutterApi = + webViewClientFlutterApi ?? WebViewClientFlutterApiImpl(); + this.webChromeClientFlutterApi = + webChromeClientFlutterApi ?? WebChromeClientFlutterApiImpl(); + this.javaScriptChannelFlutterApi = + javaScriptChannelFlutterApi ?? JavaScriptChannelFlutterApiImpl(); + this.fileChooserParamsFlutterApi = + fileChooserParamsFlutterApi ?? FileChooserParamsFlutterApiImpl(); + this.geolocationPermissionsCallbackFlutterApi = + geolocationPermissionsCallbackFlutterApi ?? + GeolocationPermissionsCallbackFlutterApiImpl(); + this.webViewFlutterApi = webViewFlutterApi ?? WebViewFlutterApiImpl(); + this.permissionRequestFlutterApi = + permissionRequestFlutterApi ?? PermissionRequestFlutterApiImpl(); + this.customViewCallbackFlutterApi = + customViewCallbackFlutterApi ?? CustomViewCallbackFlutterApiImpl(); + this.viewFlutterApi = viewFlutterApi ?? ViewFlutterApiImpl(); + this.httpAuthHandlerFlutterApi = + httpAuthHandlerFlutterApi ?? HttpAuthHandlerFlutterApiImpl(); + } + + static bool _haveBeenSetUp = false; + + /// Mutable instance containing all Flutter Apis for Ohos WebView. + /// + /// This should only be changed for testing purposes. + static OhosWebViewFlutterApis instance = OhosWebViewFlutterApis(); + + /// Handles callbacks methods for the native TS Object class. + late final OhosObjectFlutterApi ohosObjectFlutterApi; + + /// Flutter Api for [DownloadListener]. + late final DownloadListenerFlutterApiImpl downloadListenerFlutterApi; + + /// Flutter Api for [WebViewClient]. + late final WebViewClientFlutterApiImpl webViewClientFlutterApi; + + /// Flutter Api for [WebChromeClient]. + late final WebChromeClientFlutterApiImpl webChromeClientFlutterApi; + + /// Flutter Api for [JavaScriptChannel]. + late final JavaScriptChannelFlutterApiImpl javaScriptChannelFlutterApi; + + /// Flutter Api for [FileChooserParams]. + late final FileChooserParamsFlutterApiImpl fileChooserParamsFlutterApi; + + /// Flutter Api for [GeolocationPermissionsCallback]. + late final GeolocationPermissionsCallbackFlutterApiImpl + geolocationPermissionsCallbackFlutterApi; + + /// Flutter Api for [WebView]. + late final WebViewFlutterApiImpl webViewFlutterApi; + + /// Flutter Api for [PermissionRequest]. + late final PermissionRequestFlutterApiImpl permissionRequestFlutterApi; + + /// Flutter Api for [CustomViewCallback]. + late final CustomViewCallbackFlutterApiImpl customViewCallbackFlutterApi; + + /// Flutter Api for [View]. + late final ViewFlutterApiImpl viewFlutterApi; + + /// Flutter Api for [HttpAuthHandler]. + late final HttpAuthHandlerFlutterApiImpl httpAuthHandlerFlutterApi; + + /// Ensures all the Flutter APIs have been setup to receive calls from native code. + void ensureSetUp() { + if (!_haveBeenSetUp) { + OhosObjectFlutterApi.setup(ohosObjectFlutterApi); + DownloadListenerFlutterApi.setup(downloadListenerFlutterApi); + WebViewClientFlutterApi.setup(webViewClientFlutterApi); + WebChromeClientFlutterApi.setup(webChromeClientFlutterApi); + JavaScriptChannelFlutterApi.setup(javaScriptChannelFlutterApi); + FileChooserParamsFlutterApi.setup(fileChooserParamsFlutterApi); + GeolocationPermissionsCallbackFlutterApi.setup( + geolocationPermissionsCallbackFlutterApi); + WebViewFlutterApi.setup(webViewFlutterApi); + PermissionRequestFlutterApi.setup(permissionRequestFlutterApi); + CustomViewCallbackFlutterApi.setup(customViewCallbackFlutterApi); + ViewFlutterApi.setup(viewFlutterApi); + HttpAuthHandlerFlutterApi.setup(httpAuthHandlerFlutterApi); + _haveBeenSetUp = true; + } + } +} + +/// Handles methods calls to the native TS Object class. +class OhosObjectHostApiImpl extends OhosObjectHostApi { + /// Constructs a [OhosObjectHostApiImpl]. + OhosObjectHostApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager, + super(binaryMessenger: binaryMessenger); + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; +} + +/// Handles callbacks methods for the native TS Object class. +class OhosObjectFlutterApiImpl implements OhosObjectFlutterApi { + /// Constructs a [OhosObjectFlutterApiImpl]. + OhosObjectFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void dispose(int identifier) { + instanceManager.remove(identifier); + } +} + +/// Host api implementation for [WebView]. +class WebViewHostApiImpl extends WebViewHostApi { + /// Constructs a [WebViewHostApiImpl]. + WebViewHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebView instance) { + return create(instanceManager.addDartCreatedInstance(instance)); + } + + /// Helper method to convert the instances ids to objects. + Future loadDataFromInstance( + WebView instance, + String data, + String? mimeType, + String? encoding, + ) { + return loadData( + instanceManager.getIdentifier(instance)!, + data, + mimeType, + encoding, + ); + } + + /// Helper method to convert instances ids to objects. + Future loadDataWithBaseUrlFromInstance( + WebView instance, + String? baseUrl, + String data, + String? mimeType, + String? encoding, + String? historyUrl, + ) { + return loadDataWithBaseUrl( + instanceManager.getIdentifier(instance)!, + baseUrl, + data, + mimeType, + encoding, + historyUrl, + ); + } + + /// Helper method to convert instances ids to objects. + Future loadUrlFromInstance( + WebView instance, + String url, + Map headers, + ) { + return loadUrl(instanceManager.getIdentifier(instance)!, url, headers); + } + + /// Helper method to convert instances ids to objects. + Future postUrlFromInstance( + WebView instance, + String url, + Uint8List data, + ) { + return postUrl(instanceManager.getIdentifier(instance)!, url, data); + } + + /// Helper method to convert instances ids to objects. + Future getUrlFromInstance(WebView instance) { + return getUrl(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoBackFromInstance(WebView instance) { + return canGoBack(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future canGoForwardFromInstance(WebView instance) { + return canGoForward(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goBackFromInstance(WebView instance) { + return goBack(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future goForwardFromInstance(WebView instance) { + return goForward(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future reloadFromInstance(WebView instance) { + return reload(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future clearCacheFromInstance(WebView instance, bool includeDiskFiles) { + return clearCache( + instanceManager.getIdentifier(instance)!, + includeDiskFiles, + ); + } + + /// Helper method to convert instances ids to objects. + Future evaluateJavascriptFromInstance( + WebView instance, + String javascriptString, + ) { + return evaluateJavascript( + instanceManager.getIdentifier(instance)!, + javascriptString, + ); + } + + /// Helper method to convert instances ids to objects. + Future getTitleFromInstance(WebView instance) { + return getTitle(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future scrollToFromInstance(WebView instance, int x, int y) { + return scrollTo(instanceManager.getIdentifier(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future scrollByFromInstance(WebView instance, int x, int y) { + return scrollBy(instanceManager.getIdentifier(instance)!, x, y); + } + + /// Helper method to convert instances ids to objects. + Future getScrollXFromInstance(WebView instance) { + return getScrollX(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future getScrollYFromInstance(WebView instance) { + return getScrollY(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instances ids to objects. + Future getScrollPositionFromInstance(WebView instance) async { + final WebViewPoint position = + await getScrollPosition(instanceManager.getIdentifier(instance)!); + return Offset(position.x.toDouble(), position.y.toDouble()); + } + + /// Helper method to convert instances ids to objects. + Future setWebViewClientFromInstance( + WebView instance, + WebViewClient webViewClient, + ) { + return setWebViewClient( + instanceManager.getIdentifier(instance)!, + instanceManager.getIdentifier(webViewClient)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future addJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return addJavaScriptChannel( + instanceManager.getIdentifier(instance)!, + instanceManager.getIdentifier(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future removeJavaScriptChannelFromInstance( + WebView instance, + JavaScriptChannel javaScriptChannel, + ) { + return removeJavaScriptChannel( + instanceManager.getIdentifier(instance)!, + instanceManager.getIdentifier(javaScriptChannel)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future setDownloadListenerFromInstance( + WebView instance, + DownloadListener? listener, + ) { + return setDownloadListener( + instanceManager.getIdentifier(instance)!, + listener != null ? instanceManager.getIdentifier(listener) : null, + ); + } + + /// Helper method to convert instances ids to objects. + Future setWebChromeClientFromInstance( + WebView instance, + WebChromeClient? client, + ) { + return setWebChromeClient( + instanceManager.getIdentifier(instance)!, + client != null ? instanceManager.getIdentifier(client) : null, + ); + } + +} + +/// Flutter API implementation for [WebView]. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +class WebViewFlutterApiImpl implements WebViewFlutterApi { + /// Constructs a [WebViewFlutterApiImpl]. + WebViewFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create(int identifier) { + instanceManager.addHostCreatedInstance(WebView.detached(), identifier); + } + + @override + void onScrollChanged( + int webViewInstanceId, int left, int top, int oldLeft, int oldTop) { + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + webViewInstance!.onScrollChanged?.call(left, top, oldLeft, oldTop); + } +} + +/// Host api implementation for [WebSettings]. +class WebSettingsHostApiImpl extends WebSettingsHostApi { + /// Constructs a [WebSettingsHostApiImpl]. + WebSettingsHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebSettings instance, WebView webView) { + return create( + instanceManager.addDartCreatedInstance(instance), + instanceManager.getIdentifier(webView)!, + ); + } + + /// Helper method to convert instances ids to objects. + Future setDomStorageEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setDomStorageEnabled(instanceManager.getIdentifier(instance)!, flag); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptCanOpenWindowsAutomaticallyFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptCanOpenWindowsAutomatically( + instanceManager.getIdentifier(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportMultipleWindowsFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportMultipleWindows( + instanceManager.getIdentifier(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setBackgroundColorFromInstance(WebSettings instance, int color) { + return setBackgroundColor(instanceManager.getIdentifier(instance)!, color); + } + + /// Helper method to convert instances ids to objects. + Future setJavaScriptEnabledFromInstance( + WebSettings instance, + bool flag, + ) { + return setJavaScriptEnabled( + instanceManager.getIdentifier(instance)!, + flag, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUserAgentStringFromInstance( + WebSettings instance, + String? userAgentString, + ) { + return setUserAgentString( + instanceManager.getIdentifier(instance)!, + userAgentString, + ); + } + + /// Helper method to convert instances ids to objects. + Future setMediaPlaybackRequiresUserGestureFromInstance( + WebSettings instance, + bool require, + ) { + return setMediaPlaybackRequiresUserGesture( + instanceManager.getIdentifier(instance)!, + require, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSupportZoomFromInstance( + WebSettings instance, + bool support, + ) { + return setSupportZoom(instanceManager.getIdentifier(instance)!, support); + } + + /// Helper method to convert instances ids to objects. + Future setSetTextZoomFromInstance( + WebSettings instance, + int textZoom, + ) { + return setTextZoom(instanceManager.getIdentifier(instance)!, textZoom); + } + + /// Helper method to convert instances ids to objects. + Future setLoadWithOverviewModeFromInstance( + WebSettings instance, + bool overview, + ) { + return setLoadWithOverviewMode( + instanceManager.getIdentifier(instance)!, + overview, + ); + } + + /// Helper method to convert instances ids to objects. + Future setUseWideViewPortFromInstance( + WebSettings instance, + bool use, + ) { + return setUseWideViewPort(instanceManager.getIdentifier(instance)!, use); + } + + /// Helper method to convert instances ids to objects. + Future setDisplayZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setDisplayZoomControls( + instanceManager.getIdentifier(instance)!, + enabled, + ); + } + + /// Helper method to convert instances ids to objects. + Future setBuiltInZoomControlsFromInstance( + WebSettings instance, + bool enabled, + ) { + return setBuiltInZoomControls( + instanceManager.getIdentifier(instance)!, + enabled, + ); + } + + /// Helper method to convert instances ids to objects. + Future setAllowFileAccessFromInstance( + WebSettings instance, + bool enabled, + ) { + return setAllowFileAccess( + instanceManager.getIdentifier(instance)!, + enabled, + ); + } + + /// Helper method to convert instances ids to objects. + Future getUserAgentStringFromInstance(WebSettings instance) { + return getUserAgentString(instanceManager.getIdentifier(instance)!); + } +} + +/// Host api implementation for [JavaScriptChannel]. +class JavaScriptChannelHostApiImpl extends JavaScriptChannelHostApi { + /// Constructs a [JavaScriptChannelHostApiImpl]. + JavaScriptChannelHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(JavaScriptChannel instance) async { + if (instanceManager.getIdentifier(instance) == null) { + final int identifier = instanceManager.addDartCreatedInstance(instance); + await create( + identifier, + instance.channelName, + ); + } + } +} + +/// Flutter api implementation for [JavaScriptChannel]. +class JavaScriptChannelFlutterApiImpl extends JavaScriptChannelFlutterApi { + /// Constructs a [JavaScriptChannelFlutterApiImpl]. + JavaScriptChannelFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void postMessage(int instanceId, String message) { + final JavaScriptChannel? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as JavaScriptChannel?; + assert( + instance != null, + 'InstanceManager does not contain a JavaScriptChannel with instanceId: $instanceId', + ); + instance!.postMessage(message); + } +} + +/// Host api implementation for [WebViewClient]. +class WebViewClientHostApiImpl extends WebViewClientHostApi { + /// Constructs a [WebViewClientHostApiImpl]. + WebViewClientHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebViewClient instance) async { + if (instanceManager.getIdentifier(instance) == null) { + final int identifier = instanceManager.addDartCreatedInstance(instance); + return create(identifier); + } + } + + /// Helper method to convert instances ids to objects. + Future setShouldOverrideUrlLoadingReturnValueFromInstance( + WebViewClient instance, + bool value, + ) { + return setSynchronousReturnValueForShouldOverrideUrlLoading( + instanceManager.getIdentifier(instance)!, + value, + ); + } +} + +/// Flutter api implementation for [WebViewClient]. +class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { + /// Constructs a [WebViewClientFlutterApiImpl]. + WebViewClientFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void onPageFinished(int instanceId, int webViewInstanceId, String url) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onPageFinished != null) { + instance.onPageFinished!(webViewInstance!, url); + } + } + + @override + void onPageStarted(int instanceId, int webViewInstanceId, String url) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onPageStarted != null) { + instance.onPageStarted!(webViewInstance!, url); + } + } + + @override + void onReceivedHttpError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceResponseData response, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain an WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain an WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onReceivedHttpError != null) { + instance.onReceivedHttpError!( + webViewInstance!, + _toWebResourceRequest(request), + _toWebResourceResponse(response), + ); + } + } + + @override + void onReceivedError( + int instanceId, + int webViewInstanceId, + int errorCode, + String description, + String failingUrl, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onReceivedError != null) { + instance.onReceivedError!( + webViewInstance!, + errorCode, + description, + failingUrl, + ); + } + } + + @override + void onReceivedRequestError( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + WebResourceErrorData error, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onReceivedRequestError != null) { + instance.onReceivedRequestError!( + webViewInstance!, + _toWebResourceRequest(request), + _toWebResourceError(error), + ); + } + } + + @override + void requestLoading( + int instanceId, + int webViewInstanceId, + WebResourceRequestData request, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.requestLoading != null) { + instance.requestLoading!( + webViewInstance!, + _toWebResourceRequest(request), + ); + } + } + + @override + void urlLoading( + int instanceId, + int webViewInstanceId, + String url, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.urlLoading != null) { + instance.urlLoading!(webViewInstance!, url); + } + } + + @override + void doUpdateVisitedHistory( + int instanceId, + int webViewInstanceId, + String url, + bool isReload, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.doUpdateVisitedHistory != null) { + instance.doUpdateVisitedHistory!(webViewInstance!, url, isReload); + } + } + + @override + void onReceivedHttpAuthRequest( + int instanceId, + int webViewInstanceId, + int httpAuthHandlerInstanceId, + String host, + String realm, + ) { + final WebViewClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebViewClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + final HttpAuthHandler? httpAuthHandlerInstance = + instanceManager.getInstanceWithWeakReference(httpAuthHandlerInstanceId) + as HttpAuthHandler?; + assert( + instance != null, + 'InstanceManager does not contain a WebViewClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + assert( + httpAuthHandlerInstance != null, + 'InstanceManager does not contain a HttpAuthHandler with instanceId: $httpAuthHandlerInstanceId', + ); + if (instance!.onReceivedHttpAuthRequest != null) { + return instance.onReceivedHttpAuthRequest!( + webViewInstance!, httpAuthHandlerInstance!, host, realm); + } + } +} + +/// Host api implementation for [DownloadListener]. +class DownloadListenerHostApiImpl extends DownloadListenerHostApi { + /// Constructs a [DownloadListenerHostApiImpl]. + DownloadListenerHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(DownloadListener instance) async { + if (instanceManager.getIdentifier(instance) == null) { + final int identifier = instanceManager.addDartCreatedInstance(instance); + return create(identifier); + } + } +} + +/// Flutter api implementation for [DownloadListener]. +class DownloadListenerFlutterApiImpl extends DownloadListenerFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + DownloadListenerFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void onDownloadStart( + int instanceId, + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + final DownloadListener? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as DownloadListener?; + assert( + instance != null, + 'InstanceManager does not contain a DownloadListener with instanceId: $instanceId', + ); + instance!.onDownloadStart( + url, + userAgent, + contentDisposition, + mimetype, + contentLength, + ); + } +} + +/// Host api implementation for [DownloadListener]. +class WebChromeClientHostApiImpl extends WebChromeClientHostApi { + /// Constructs a [WebChromeClientHostApiImpl]. + WebChromeClientHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebChromeClient instance) async { + if (instanceManager.getIdentifier(instance) == null) { + final int identifier = instanceManager.addDartCreatedInstance(instance); + return create(identifier); + } + } + + /// Helper method to convert instances ids to objects. + Future setSynchronousReturnValueForOnShowFileChooserFromInstance( + WebChromeClient instance, + bool value, + ) { + return setSynchronousReturnValueForOnShowFileChooser( + instanceManager.getIdentifier(instance)!, + value, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSynchronousReturnValueForOnConsoleMessageFromInstance( + WebChromeClient instance, + bool value, + ) { + return setSynchronousReturnValueForOnConsoleMessage( + instanceManager.getIdentifier(instance)!, + value, + ); + } + + /// Helper method to convert instances ids to objects. + Future setSynchronousReturnValueForOnJsAlertFromInstance( + WebChromeClient instance, + bool value, + ) { + return setSynchronousReturnValueForOnJsAlert( + instanceManager.getIdentifier(instance)!, value); + } + + /// Helper method to convert instances ids to objects. + Future setSynchronousReturnValueForOnJsConfirmFromInstance( + WebChromeClient instance, + bool value, + ) { + return setSynchronousReturnValueForOnJsConfirm( + instanceManager.getIdentifier(instance)!, value); + } + + /// Helper method to convert instances ids to objects. + Future setSynchronousReturnValueForOnJsPromptFromInstance( + WebChromeClient instance, + bool value, + ) { + return setSynchronousReturnValueForOnJsPrompt( + instanceManager.getIdentifier(instance)!, value); + } +} + +/// Flutter api implementation for [DownloadListener]. +class WebChromeClientFlutterApiImpl extends WebChromeClientFlutterApi { + /// Constructs a [DownloadListenerFlutterApiImpl]. + WebChromeClientFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void onProgressChanged(int instanceId, int webViewInstanceId, int progress) { + final WebChromeClient? instance = instanceManager + .getInstanceWithWeakReference(instanceId) as WebChromeClient?; + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + instance != null, + 'InstanceManager does not contain a WebChromeClient with instanceId: $instanceId', + ); + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + if (instance!.onProgressChanged != null) { + instance.onProgressChanged!(webViewInstance!, progress); + } + } + + @override + Future> onShowFileChooser( + int instanceId, + int webViewInstanceId, + int paramsInstanceId, + ) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + if (instance.onShowFileChooser != null) { + return instance.onShowFileChooser!( + instanceManager.getInstanceWithWeakReference(webViewInstanceId)! + as WebView, + instanceManager.getInstanceWithWeakReference(paramsInstanceId)! + as FileChooserParams, + ); + } + + return Future>.value(const []); + } + + @override + void onGeolocationPermissionsShowPrompt( + int instanceId, int paramsInstanceId, String origin) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + final GeolocationPermissionsCallback callback = + instanceManager.getInstanceWithWeakReference(paramsInstanceId)! + as GeolocationPermissionsCallback; + final GeolocationPermissionsShowPrompt? onShowPrompt = + instance.onGeolocationPermissionsShowPrompt; + if (onShowPrompt != null) { + onShowPrompt(origin, callback); + } + } + + @override + void onGeolocationPermissionsHidePrompt(int identifier) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(identifier)!; + final GeolocationPermissionsHidePrompt? onHidePrompt = + instance.onGeolocationPermissionsHidePrompt; + if (onHidePrompt != null) { + return onHidePrompt(instance); + } + } + + @override + void onPermissionRequest( + int instanceId, + int requestInstanceId, + ) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + if (instance.onPermissionRequest != null) { + instance.onPermissionRequest!( + instance, + instanceManager.getInstanceWithWeakReference(requestInstanceId)!, + ); + } else { + // The method requires calling grant or deny if the TS method is + // overridden, so this calls deny by default if `onPermissionRequest` is + // null. + final PermissionRequest request = + instanceManager.getInstanceWithWeakReference(requestInstanceId)!; + request.deny(); + } + } + + @override + void onShowCustomView( + int instanceId, + int viewIdentifier, + int callbackIdentifier, + ) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + if (instance.onShowCustomView != null) { + return instance.onShowCustomView!( + instance, + instanceManager.getInstanceWithWeakReference(viewIdentifier)!, + instanceManager.getInstanceWithWeakReference(callbackIdentifier)!, + ); + } + } + + @override + void onHideCustomView(int instanceId) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + if (instance.onHideCustomView != null) { + return instance.onHideCustomView!( + instance, + ); + } + } + + @override + void onConsoleMessage(int instanceId, ConsoleMessage message) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + instance.onConsoleMessage?.call(instance, message); + } + + @override + Future onJsAlert(int instanceId, String url, String message) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + + return instance.onJsAlert!(url, message); + } + + @override + Future onJsConfirm(int instanceId, String url, String message) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + + return instance.onJsConfirm!(url, message); + } + + @override + Future onJsPrompt( + int instanceId, String url, String message, String defaultValue) { + final WebChromeClient instance = + instanceManager.getInstanceWithWeakReference(instanceId)!; + + return instance.onJsPrompt!(url, message, defaultValue); + } +} + +/// Host api implementation for [WebStorage]. +class WebStorageHostApiImpl extends WebStorageHostApi { + /// Constructs a [WebStorageHostApiImpl]. + WebStorageHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future createFromInstance(WebStorage instance) async { + if (instanceManager.getIdentifier(instance) == null) { + final int identifier = instanceManager.addDartCreatedInstance(instance); + return create(identifier); + } + } + + /// Helper method to convert instances ids to objects. + Future deleteAllDataFromInstance(WebStorage instance) { + return deleteAllData(instanceManager.getIdentifier(instance)!); + } +} + +/// Flutter api implementation for [FileChooserParams]. +class FileChooserParamsFlutterApiImpl extends FileChooserParamsFlutterApi { + /// Constructs a [FileChooserParamsFlutterApiImpl]. + FileChooserParamsFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void create( + int instanceId, + bool isCaptureEnabled, + List acceptTypes, + FileChooserMode mode, + String? filenameHint, + ) { + instanceManager.addHostCreatedInstance( + FileChooserParams.detached( + isCaptureEnabled: isCaptureEnabled, + acceptTypes: acceptTypes.cast(), + mode: mode, + filenameHint: filenameHint, + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + instanceId, + ); + } +} + +/// Host api implementation for [GeolocationPermissionsCallback]. +class GeolocationPermissionsCallbackHostApiImpl + extends GeolocationPermissionsCallbackHostApi { + /// Constructs a [GeolocationPermissionsCallbackHostApiImpl]. + GeolocationPermissionsCallbackHostApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager, + super(binaryMessenger: binaryMessenger); + + /// Sends binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + /// Helper method to convert instances ids to objects. + Future invokeFromInstances( + GeolocationPermissionsCallback instance, + String origin, + bool allow, + bool retain, + ) { + return invoke( + instanceManager.getIdentifier(instance)!, + origin, + allow, + retain, + ); + } +} + +/// Flutter API implementation for [GeolocationPermissionsCallback]. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +class GeolocationPermissionsCallbackFlutterApiImpl + implements GeolocationPermissionsCallbackFlutterApi { + /// Constructs a [GeolocationPermissionsCallbackFlutterApiImpl]. + GeolocationPermissionsCallbackFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create(int instanceId) { + instanceManager.addHostCreatedInstance( + GeolocationPermissionsCallback.detached( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + instanceId, + ); + } +} + +/// Host api implementation for [PermissionRequest]. +class PermissionRequestHostApiImpl extends PermissionRequestHostApi { + /// Constructs a [PermissionRequestHostApiImpl]. + PermissionRequestHostApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager, + super(binaryMessenger: binaryMessenger); + + /// Sends binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + /// Helper method to convert instance ids to objects. + Future grantFromInstances( + PermissionRequest instance, + List resources, + ) { + return grant(instanceManager.getIdentifier(instance)!, resources); + } + + /// Helper method to convert instance ids to objects. + Future denyFromInstances(PermissionRequest instance) { + return deny(instanceManager.getIdentifier(instance)!); + } +} + +/// Flutter API implementation for [PermissionRequest]. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +class PermissionRequestFlutterApiImpl implements PermissionRequestFlutterApi { + /// Constructs a [PermissionRequestFlutterApiImpl]. + PermissionRequestFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create( + int identifier, + List resources, + ) { + instanceManager.addHostCreatedInstance( + PermissionRequest.detached( + resources: resources.cast(), + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + identifier, + ); + } +} + +/// Host api implementation for [CustomViewCallback]. +class CustomViewCallbackHostApiImpl extends CustomViewCallbackHostApi { + /// Constructs a [CustomViewCallbackHostApiImpl]. + CustomViewCallbackHostApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager, + super(binaryMessenger: binaryMessenger); + + /// Sends binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + /// Helper method to convert instance ids to objects. + Future onCustomViewHiddenFromInstances(CustomViewCallback instance) { + return onCustomViewHidden(instanceManager.getIdentifier(instance)!); + } +} + +/// Flutter API implementation for [CustomViewCallback]. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +class CustomViewCallbackFlutterApiImpl implements CustomViewCallbackFlutterApi { + /// Constructs a [CustomViewCallbackFlutterApiImpl]. + CustomViewCallbackFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create(int identifier) { + instanceManager.addHostCreatedInstance( + CustomViewCallback.detached( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + identifier, + ); + } +} + +/// Flutter API implementation for [View]. +/// +/// This class may handle instantiating and adding Dart instances that are +/// attached to a native instance or receiving callback methods from an +/// overridden native class. +class ViewFlutterApiImpl implements ViewFlutterApi { + /// Constructs a [ViewFlutterApiImpl]. + ViewFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create(int identifier) { + instanceManager.addHostCreatedInstance( + View.detached( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + identifier, + ); + } +} + +/// Host api implementation for [CookieManager]. +class CookieManagerHostApiImpl extends CookieManagerHostApi { + /// Constructs a [CookieManagerHostApiImpl]. + CookieManagerHostApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager, + super(binaryMessenger: binaryMessenger); + + /// Sends binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + /// Helper method to convert instance ids to objects. + CookieManager attachInstanceFromInstances(CookieManager instance) { + attachInstance(instanceManager.addDartCreatedInstance(instance)); + return instance; + } + + /// Helper method to convert instance ids to objects. + Future setCookieFromInstances( + CookieManager instance, + String url, + String value, + ) { + return setCookie( + instanceManager.getIdentifier(instance)!, + url, + value, + ); + } + + /// Helper method to convert instance ids to objects. + Future removeAllCookiesFromInstances(CookieManager instance) { + return removeAllCookies(instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instance ids to objects. + Future setAcceptThirdPartyCookiesFromInstances( + CookieManager instance, + WebView webView, + bool accept, + ) { + return setAcceptThirdPartyCookies( + instanceManager.getIdentifier(instance)!, + instanceManager.getIdentifier(webView)!, + accept, + ); + } +} + +/// Host api implementation for [HttpAuthHandler]. +class HttpAuthHandlerHostApiImpl extends HttpAuthHandlerHostApi { + /// Constructs a [HttpAuthHandlerHostApiImpl]. + HttpAuthHandlerHostApiImpl({ + super.binaryMessenger, + InstanceManager? instanceManager, + }) : _instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager _instanceManager; + + /// Helper method to convert instance ids to objects. + Future cancelFromInstance(HttpAuthHandler instance) { + return cancel(_instanceManager.getIdentifier(instance)!); + } + + /// Helper method to convert instance ids to objects. + Future proceedFromInstance( + HttpAuthHandler instance, + String username, + String password, + ) { + return proceed( + _instanceManager.getIdentifier(instance)!, + username, + password, + ); + } + + /// Helper method to convert instance ids to objects. + Future useHttpAuthUsernamePasswordFromInstance( + HttpAuthHandler instance, + ) { + return useHttpAuthUsernamePassword( + _instanceManager.getIdentifier(instance)!, + ); + } +} + +/// Flutter API implementation for [HttpAuthHandler]. +class HttpAuthHandlerFlutterApiImpl extends HttpAuthHandlerFlutterApi { + /// Constructs a [HttpAuthHandlerFlutterApiImpl]. + HttpAuthHandlerFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : instanceManager = instanceManager ?? OhosObject.globalInstanceManager; + + /// Receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used which routes to + /// the host platform. + final BinaryMessenger? binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final InstanceManager instanceManager; + + @override + void create(int instanceId) { + instanceManager.addHostCreatedInstance( + HttpAuthHandler(), + instanceId, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_controller.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_controller.dart new file mode 100644 index 0000000000000000000000000000000000000000..1fb885e8d508cb0ed58559948486b181d29f96b2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_controller.dart @@ -0,0 +1,1543 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; + +import 'ohos_proxy.dart'; +import 'ohos_webview.dart' as ohos_webview; +import 'ohos_webview_api_impls.dart'; +import 'instance_manager.dart'; +import 'platform_views_service_proxy.dart'; +import 'weak_reference_utils.dart'; + +/// Object specifying creation parameters for creating a [OhosWebViewController]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebViewControllerCreationParams] for +/// more information. +@immutable +class OhosWebViewControllerCreationParams + extends PlatformWebViewControllerCreationParams { + /// Creates a new [OhosWebViewControllerCreationParams] instance. + OhosWebViewControllerCreationParams({ + @visibleForTesting this.ohosWebViewProxy = const OhosWebViewProxy(), + @visibleForTesting ohos_webview.WebStorage? ohosWebStorage, + }) : ohosWebStorage = + ohosWebStorage ?? ohos_webview.WebStorage.instance, + super(); + + /// Creates a [OhosWebViewControllerCreationParams] instance based on [PlatformWebViewControllerCreationParams]. + factory OhosWebViewControllerCreationParams.fromPlatformWebViewControllerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebViewControllerCreationParams params, { + @visibleForTesting + OhosWebViewProxy ohosWebViewProxy = const OhosWebViewProxy(), + @visibleForTesting ohos_webview.WebStorage? ohosWebStorage, + }) { + return OhosWebViewControllerCreationParams( + ohosWebViewProxy: ohosWebViewProxy, + ohosWebStorage: + ohosWebStorage ?? ohos_webview.WebStorage.instance, + ); + } + + /// Handles constructing objects and calling static methods for the Ohos WebView + /// native library. + @visibleForTesting + final OhosWebViewProxy ohosWebViewProxy; + + /// Manages the JavaScript storage APIs provided by the [ohos_webview.WebView]. + @visibleForTesting + final ohos_webview.WebStorage ohosWebStorage; +} + +/// Ohos-specific resources that can require permissions. +class OhosWebViewPermissionResourceType + extends WebViewPermissionResourceType { + const OhosWebViewPermissionResourceType._(super.name); + + /// A resource that will allow sysex messages to be sent to or received from + /// MIDI devices. + static const OhosWebViewPermissionResourceType midiSysex = + OhosWebViewPermissionResourceType._('midiSysex'); + + /// A resource that belongs to a protected media identifier. + static const OhosWebViewPermissionResourceType protectedMediaId = + OhosWebViewPermissionResourceType._('protectedMediaId'); +} + +/// Implementation of the [PlatformWebViewController] with the Ohos WebView API. +class OhosWebViewController extends PlatformWebViewController { + /// Creates a new [OhosWebViewController]. + OhosWebViewController(PlatformWebViewControllerCreationParams params) + : super.implementation(params is OhosWebViewControllerCreationParams + ? params + : OhosWebViewControllerCreationParams + .fromPlatformWebViewControllerCreationParams(params)) { + _webView.settings.setDomStorageEnabled(true); + _webView.settings.setJavaScriptCanOpenWindowsAutomatically(true); + _webView.settings.setSupportMultipleWindows(true); + _webView.settings.setLoadWithOverviewMode(true); + _webView.settings.setUseWideViewPort(true); + _webView.settings.setDisplayZoomControls(false); + _webView.settings.setBuiltInZoomControls(true); + + _webView.setWebChromeClient(_webChromeClient); + } + + OhosWebViewControllerCreationParams get _ohosWebViewParams => + params as OhosWebViewControllerCreationParams; + + /// The native [ohos_webview.WebView] being controlled. + late final ohos_webview.WebView _webView = + _ohosWebViewParams.ohosWebViewProxy.createOhosWebView( + onScrollChanged: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (int left, int top, int oldLeft, int oldTop) async { + final void Function(ScrollPositionChange)? callback = + weakReference.target?._onScrollPositionChangedCallback; + callback?.call(ScrollPositionChange(left.toDouble(), top.toDouble())); + }; + })); + + late final ohos_webview.WebChromeClient _webChromeClient = + _ohosWebViewParams.ohosWebViewProxy.createOhosWebChromeClient( + onProgressChanged: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (ohos_webview.WebView webView, int progress) { + if (weakReference.target?._currentNavigationDelegate?._onProgress != + null) { + weakReference + .target!._currentNavigationDelegate!._onProgress!(progress); + } + }; + }), + onGeolocationPermissionsShowPrompt: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (String origin, + ohos_webview.GeolocationPermissionsCallback callback) async { + final OnGeolocationPermissionsShowPrompt? onShowPrompt = + weakReference.target?._onGeolocationPermissionsShowPrompt; + if (onShowPrompt != null) { + final GeolocationPermissionsResponse response = await onShowPrompt( + GeolocationPermissionsRequestParams(origin: origin), + ); + return callback.invoke(origin, response.allow, response.retain); + } else { + // default don't allow + return callback.invoke(origin, false, false); + } + }; + }), + onGeolocationPermissionsHidePrompt: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (ohos_webview.WebChromeClient instance) { + final OnGeolocationPermissionsHidePrompt? onHidePrompt = + weakReference.target?._onGeolocationPermissionsHidePrompt; + if (onHidePrompt != null) { + onHidePrompt(); + } + }; + }), + onShowCustomView: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (_, ohos_webview.View view, + ohos_webview.CustomViewCallback callback) { + final OhosWebViewController? webViewController = + weakReference.target; + if (webViewController == null) { + callback.onCustomViewHidden(); + return; + } + final OnShowCustomWidgetCallback? onShowCallback = + webViewController._onShowCustomWidgetCallback; + if (onShowCallback == null) { + callback.onCustomViewHidden(); + return; + } + onShowCallback( + OhosCustomViewWidget.private( + controller: webViewController, + customView: view, + ), + () => callback.onCustomViewHidden(), + ); + }; + }), + onHideCustomView: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (ohos_webview.WebChromeClient instance) { + final OnHideCustomWidgetCallback? onHideCustomViewCallback = + weakReference.target?._onHideCustomWidgetCallback; + if (onHideCustomViewCallback != null) { + onHideCustomViewCallback(); + } + }; + }), + onShowFileChooser: withWeakReferenceTo( + this, + (WeakReference weakReference) { + return (ohos_webview.WebView webView, + ohos_webview.FileChooserParams params) async { + if (weakReference.target?._onShowFileSelectorCallback != null) { + return weakReference.target!._onShowFileSelectorCallback!( + FileSelectorParams._fromFileChooserParams(params), + ); + } + return []; + }; + }, + ), + onConsoleMessage: withWeakReferenceTo( + this, + (WeakReference weakReference) { + return (ohos_webview.WebChromeClient webChromeClient, + ohos_webview.ConsoleMessage consoleMessage) async { + final void Function(JavaScriptConsoleMessage)? callback = + weakReference.target?._onConsoleLogCallback; + if (callback != null) { + JavaScriptLogLevel logLevel; + switch (consoleMessage.level) { + // Android maps `console.debug` to `MessageLevel.TIP`, it seems + // `MessageLevel.DEBUG` if not being used. + case ConsoleMessageLevel.debug: + case ConsoleMessageLevel.tip: + logLevel = JavaScriptLogLevel.debug; + case ConsoleMessageLevel.error: + logLevel = JavaScriptLogLevel.error; + case ConsoleMessageLevel.warning: + logLevel = JavaScriptLogLevel.warning; + case ConsoleMessageLevel.unknown: + case ConsoleMessageLevel.log: + logLevel = JavaScriptLogLevel.log; + } + + callback(JavaScriptConsoleMessage( + level: logLevel, + message: consoleMessage.message, + )); + } + }; + }, + ), + onPermissionRequest: withWeakReferenceTo( + this, + (WeakReference weakReference) { + return (_, ohos_webview.PermissionRequest request) async { + final void Function(PlatformWebViewPermissionRequest)? callback = + weakReference.target?._onPermissionRequestCallback; + if (callback == null) { + return request.deny(); + } else { + final Set types = request.resources + .map((String type) { + switch (type) { + case ohos_webview.PermissionRequest.videoCapture: + return WebViewPermissionResourceType.camera; + case ohos_webview.PermissionRequest.audioCapture: + return WebViewPermissionResourceType.microphone; + case ohos_webview.PermissionRequest.midiSysex: + return OhosWebViewPermissionResourceType.midiSysex; + case ohos_webview.PermissionRequest.protectedMediaId: + return OhosWebViewPermissionResourceType + .protectedMediaId; + } + + // Type not supported. + return null; + }) + .whereType() + .toSet(); + + // If the request didn't contain any permissions recognized by the + // implementation, deny by default. + if (types.isEmpty) { + return request.deny(); + } + + callback(OhosWebViewPermissionRequest._( + types: types, + request: request, + )); + } + }; + }, + ), + onJsAlert: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (String url, String message) async { + final Future Function(JavaScriptAlertDialogRequest)? callback = + weakReference.target?._onJavaScriptAlert; + if (callback != null) { + final JavaScriptAlertDialogRequest request = + JavaScriptAlertDialogRequest(message: message, url: url); + + await callback.call(request); + } + return; + }; + }), + onJsConfirm: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (String url, String message) async { + final Future Function(JavaScriptConfirmDialogRequest)? callback = + weakReference.target?._onJavaScriptConfirm; + if (callback != null) { + final JavaScriptConfirmDialogRequest request = + JavaScriptConfirmDialogRequest(message: message, url: url); + final bool result = await callback.call(request); + return result; + } + return false; + }; + }), + onJsPrompt: withWeakReferenceTo(this, + (WeakReference weakReference) { + return (String url, String message, String defaultValue) async { + final Future Function(JavaScriptTextInputDialogRequest)? + callback = weakReference.target?._onJavaScriptPrompt; + if (callback != null) { + final JavaScriptTextInputDialogRequest request = + JavaScriptTextInputDialogRequest( + message: message, url: url, defaultText: defaultValue); + final String result = await callback.call(request); + return result; + } + return ''; + }; + }), + ); + + /// The native [ohos_webview.FlutterAssetManager] allows managing assets. + late final ohos_webview.FlutterAssetManager _flutterAssetManager = + _ohosWebViewParams.ohosWebViewProxy.createFlutterAssetManager(); + + final Map _javaScriptChannelParams = + {}; + + OhosNavigationDelegate? _currentNavigationDelegate; + + Future> Function(FileSelectorParams)? + _onShowFileSelectorCallback; + + OnGeolocationPermissionsShowPrompt? _onGeolocationPermissionsShowPrompt; + + OnGeolocationPermissionsHidePrompt? _onGeolocationPermissionsHidePrompt; + + OnShowCustomWidgetCallback? _onShowCustomWidgetCallback; + + OnHideCustomWidgetCallback? _onHideCustomWidgetCallback; + + void Function(PlatformWebViewPermissionRequest)? _onPermissionRequestCallback; + + void Function(JavaScriptConsoleMessage consoleMessage)? _onConsoleLogCallback; + + Future Function(JavaScriptAlertDialogRequest request)? + _onJavaScriptAlert; + Future Function(JavaScriptConfirmDialogRequest request)? + _onJavaScriptConfirm; + Future Function(JavaScriptTextInputDialogRequest request)? + _onJavaScriptPrompt; + + void Function(ScrollPositionChange scrollPositionChange)? + _onScrollPositionChangedCallback; + + /// Whether to enable the platform's webview content debugging tools. + /// + /// Defaults to false. + static Future enableDebugging( + bool enabled, { + @visibleForTesting + OhosWebViewProxy webViewProxy = const OhosWebViewProxy(), + }) { + return webViewProxy.setWebContentsDebuggingEnabled(enabled); + } + + /// Identifier used to retrieve the underlying native `WKWebView`. + /// + /// This is typically used by other plugins to retrieve the native `WebView` + /// from an `InstanceManager`. + /// + /// See TS method `WebViewFlutterPlugin.getWebView`. + int get webViewIdentifier => + // ignore: invalid_use_of_visible_for_testing_member + ohos_webview.WebView.api.instanceManager.getIdentifier(_webView)!; + + @override + Future loadFile( + String absoluteFilePath, + ) { + final String url = absoluteFilePath.startsWith('file://') + ? absoluteFilePath + : Uri.file(absoluteFilePath).toString(); + + _webView.settings.setAllowFileAccess(true); + return _webView.loadUrl(url, {}); + } + + @override + Future loadFlutterAsset( + String key, + ) async { + final String assetFilePath = + await _flutterAssetManager.getAssetFilePathByName(key); + final List pathElements = assetFilePath.split('/'); + final String fileName = pathElements.removeLast(); + final List paths = + await _flutterAssetManager.list(pathElements.join('/')); + + if (!paths.contains(fileName)) { + throw ArgumentError( + 'Asset for key "$key" not found.', + 'key', + ); + } + _webView.settings.setAllowFileAccess(true); + final String url = "resources/rawfile/" + assetFilePath; + return _webView.loadUrl(url, {}); + } + + @override + Future loadHtmlString( + String html, { + String? baseUrl, + }) { + return _webView.loadDataWithBaseUrl( + baseUrl: baseUrl, data: html, mimeType: 'text/html', encoding: 'UTF-8'); + } + + @override + Future loadRequest( + LoadRequestParams params, + ) { + if (!params.uri.hasScheme) { + throw ArgumentError('WebViewRequest#uri is required to have a scheme.'); + } + switch (params.method) { + case LoadRequestMethod.get: + return _webView.loadUrl(params.uri.toString(), params.headers); + case LoadRequestMethod.post: + return _webView.postUrl( + params.uri.toString(), params.body ?? Uint8List(0)); + } + // The enum comes from a different package, which could get a new value at + // any time, so a fallback case is necessary. Since there is no reasonable + // default behavior, throw to alert the client that they need an updated + // version. This is deliberately outside the switch rather than a `default` + // so that the linter will flag the switch as needing an update. + // ignore: dead_code + throw UnimplementedError( + 'This version of `OhosWebViewController` currently has no ' + 'implementation for HTTP method ${params.method.serialize()} in ' + 'loadRequest.'); + } + + @override + Future currentUrl() => _webView.getUrl(); + + @override + Future canGoBack() => _webView.canGoBack(); + + @override + Future canGoForward() => _webView.canGoForward(); + + @override + Future goBack() => _webView.goBack(); + + @override + Future goForward() => _webView.goForward(); + + @override + Future reload() => _webView.reload(); + + @override + Future clearCache() => _webView.clearCache(true); + + @override + Future clearLocalStorage() => + _ohosWebViewParams.ohosWebStorage.deleteAllData(); + + @override + Future setPlatformNavigationDelegate( + covariant OhosNavigationDelegate handler) async { + _currentNavigationDelegate = handler; + await Future.wait(>[ + handler.setOnLoadRequest(loadRequest), + _webView.setWebViewClient(handler.ohosWebViewClient), + _webView.setDownloadListener(handler.ohosDownloadListener), + ]); + } + + @override + Future runJavaScript(String javaScript) { + return _webView.evaluateJavascript(javaScript); + } + + @override + Future runJavaScriptReturningResult(String javaScript) async { + final String? result = await _webView.evaluateJavascript(javaScript); + + if (result == null) { + return ''; + } else if (result == 'true') { + return true; + } else if (result == 'false') { + return false; + } + + return num.tryParse(result) ?? result; + } + + @override + Future addJavaScriptChannel( + JavaScriptChannelParams javaScriptChannelParams, + ) { + final OhosJavaScriptChannelParams ohosJavaScriptParams = + javaScriptChannelParams is OhosJavaScriptChannelParams + ? javaScriptChannelParams + : OhosJavaScriptChannelParams.fromJavaScriptChannelParams( + javaScriptChannelParams); + + // When JavaScript channel with the same name exists make sure to remove it + // before registering the new channel. + if (_javaScriptChannelParams.containsKey(ohosJavaScriptParams.name)) { + _webView.removeJavaScriptChannel(ohosJavaScriptParams._javaScriptChannel); + } + + _javaScriptChannelParams[ohosJavaScriptParams.name] = ohosJavaScriptParams; + + return _webView + .addJavaScriptChannel(ohosJavaScriptParams._javaScriptChannel); + } + + @override + Future removeJavaScriptChannel(String javaScriptChannelName) async { + final OhosJavaScriptChannelParams? javaScriptChannelParams = + _javaScriptChannelParams[javaScriptChannelName]; + if (javaScriptChannelParams == null) { + return; + } + + _javaScriptChannelParams.remove(javaScriptChannelName); + return _webView + .removeJavaScriptChannel(javaScriptChannelParams._javaScriptChannel); + } + + @override + Future getTitle() => _webView.getTitle(); + + @override + Future scrollTo(int x, int y) => _webView.scrollTo(x, y); + + @override + Future scrollBy(int x, int y) => _webView.scrollBy(x, y); + + @override + Future getScrollPosition() { + return _webView.getScrollPosition(); + } + + @override + Future enableZoom(bool enabled) => + _webView.settings.setSupportZoom(enabled); + + @override + Future setBackgroundColor(Color color) => + _webView.settings.setBackgroundColor(color); + + @override + Future setJavaScriptMode(JavaScriptMode javaScriptMode) => + _webView.settings + .setJavaScriptEnabled(javaScriptMode == JavaScriptMode.unrestricted); + + @override + Future setUserAgent(String? userAgent) => + _webView.settings.setUserAgentString(userAgent); + + @override + Future setOnScrollPositionChange( + void Function(ScrollPositionChange scrollPositionChange)? + onScrollPositionChange) async { + _onScrollPositionChangedCallback = onScrollPositionChange; + } + + /// Sets the restrictions that apply on automatic media playback. + Future setMediaPlaybackRequiresUserGesture(bool require) { + return _webView.settings.setMediaPlaybackRequiresUserGesture(require); + } + + /// Sets the text zoom of the page in percent. + /// + /// The default is 100. + Future setTextZoom(int textZoom) => + _webView.settings.setTextZoom(textZoom); + + /// Sets the callback that is invoked when the client should show a file + /// selector. + Future setOnShowFileSelector( + Future> Function(FileSelectorParams params)? + onShowFileSelector, + ) { + _onShowFileSelectorCallback = onShowFileSelector; + return _webChromeClient.setSynchronousReturnValueForOnShowFileChooser( + onShowFileSelector != null, + ); + } + + /// Sets a callback that notifies the host application that web content is + /// requesting permission to access the specified resources. + /// + /// Only invoked on Ohos versions 21+. + @override + Future setOnPlatformPermissionRequest( + void Function( + PlatformWebViewPermissionRequest request, + ) onPermissionRequest, + ) async { + _onPermissionRequestCallback = onPermissionRequest; + } + + /// Sets the callback that is invoked when the client request handle geolocation permissions. + /// + /// Param [onShowPrompt] notifies the host application that web content from the specified origin is attempting to use the Geolocation API, + /// but no permission state is currently set for that origin. + /// + /// The host application should invoke the specified callback with the desired permission state. + /// See GeolocationPermissions for details. + /// + /// Note that for applications targeting Ohos N and later SDKs (API level > Build.VERSION_CODES.M) + /// this method is only called for requests originating from secure origins such as https. + /// On non-secure origins geolocation requests are automatically denied. + /// + /// Param [onHidePrompt] notifies the host application that a request for Geolocation permissions, + /// made with a previous call to onGeolocationPermissionsShowPrompt() has been canceled. + /// Any related UI should therefore be hidden. + Future setGeolocationPermissionsPromptCallbacks({ + OnGeolocationPermissionsShowPrompt? onShowPrompt, + OnGeolocationPermissionsHidePrompt? onHidePrompt, + }) async { + _onGeolocationPermissionsShowPrompt = onShowPrompt; + _onGeolocationPermissionsHidePrompt = onHidePrompt; + } + + /// Sets the callbacks that are invoked when the host application wants to + /// show or hide a custom widget. + /// + /// The most common use case these methods are invoked a video element wants + /// to be displayed in fullscreen. + /// + /// The [onShowCustomWidget] notifies the host application that web content + /// from the specified origin wants to be displayed in a custom widget. After + /// this call, web content will no longer be rendered in the `WebViewWidget`, + /// but will instead be rendered in the custom widget. The application may + /// explicitly exit fullscreen mode by invoking `onCustomWidgetHidden` in the + /// [onShowCustomWidget] callback (ex. when the user presses the back + /// button). However, this is generally not necessary as the web page will + /// often show its own UI to close out of fullscreen. Regardless of how the + /// WebView exits fullscreen mode, WebView will invoke [onHideCustomWidget], + /// signaling for the application to remove the custom widget. If this value + /// is `null` when passed to an `AndroidWebViewWidget`, a default handler + /// will be set. + /// + /// The [onHideCustomWidget] notifies the host application that the custom + /// widget must be hidden. After this call, web content will render in the + /// original `WebViewWidget` again. + Future setCustomWidgetCallbacks({ + required OnShowCustomWidgetCallback? onShowCustomWidget, + required OnHideCustomWidgetCallback? onHideCustomWidget, + }) async { + _onShowCustomWidgetCallback = onShowCustomWidget; + _onHideCustomWidgetCallback = onHideCustomWidget; + } + + /// Sets a callback that notifies the host application of any log messages + /// written to the JavaScript console. + @override + Future setOnConsoleMessage( + void Function(JavaScriptConsoleMessage consoleMessage) + onConsoleMessage) async { + _onConsoleLogCallback = onConsoleMessage; + + return _webChromeClient.setSynchronousReturnValueForOnConsoleMessage( + _onConsoleLogCallback != null); + } + + @override + Future getUserAgent() => _webView.settings.getUserAgentString(); + + @override + Future setOnJavaScriptAlertDialog( + Future Function(JavaScriptAlertDialogRequest request) + onJavaScriptAlertDialog) async { + _onJavaScriptAlert = onJavaScriptAlertDialog; + return _webChromeClient.setSynchronousReturnValueForOnJsAlert(true); + } + + @override + Future setOnJavaScriptConfirmDialog( + Future Function(JavaScriptConfirmDialogRequest request) + onJavaScriptConfirmDialog) async { + _onJavaScriptConfirm = onJavaScriptConfirmDialog; + return _webChromeClient.setSynchronousReturnValueForOnJsConfirm(true); + } + + @override + Future setOnJavaScriptTextInputDialog( + Future Function(JavaScriptTextInputDialogRequest request) + onJavaScriptTextInputDialog) async { + _onJavaScriptPrompt = onJavaScriptTextInputDialog; + return _webChromeClient.setSynchronousReturnValueForOnJsPrompt(true); + } +} + +/// Ohos implementation of [PlatformWebViewPermissionRequest]. +class OhosWebViewPermissionRequest extends PlatformWebViewPermissionRequest { + const OhosWebViewPermissionRequest._({ + required super.types, + required ohos_webview.PermissionRequest request, + }) : _request = request; + + final ohos_webview.PermissionRequest _request; + + @override + Future grant() { + return _request + .grant(types.map((WebViewPermissionResourceType type) { + switch (type) { + case WebViewPermissionResourceType.camera: + return ohos_webview.PermissionRequest.videoCapture; + case WebViewPermissionResourceType.microphone: + return ohos_webview.PermissionRequest.audioCapture; + case OhosWebViewPermissionResourceType.midiSysex: + return ohos_webview.PermissionRequest.midiSysex; + case OhosWebViewPermissionResourceType.protectedMediaId: + return ohos_webview.PermissionRequest.protectedMediaId; + } + + throw UnsupportedError( + 'Resource of type `${type.name}` is not supported.', + ); + }).toList()); + } + + @override + Future deny() { + return _request.deny(); + } +} + +/// Signature for the `setGeolocationPermissionsPromptCallbacks` callback responsible for request the Geolocation API. +typedef OnGeolocationPermissionsShowPrompt + = Future Function( + GeolocationPermissionsRequestParams request); + +/// Signature for the `setGeolocationPermissionsPromptCallbacks` callback responsible for request the Geolocation API is cancel. +typedef OnGeolocationPermissionsHidePrompt = void Function(); + +/// Signature for the `setCustomWidgetCallbacks` callback responsible for showing the custom view. +typedef OnShowCustomWidgetCallback = void Function( + Widget widget, void Function() onCustomWidgetHidden); + +/// Signature for the `setCustomWidgetCallbacks` callback responsible for hiding the custom view. +typedef OnHideCustomWidgetCallback = void Function(); + +/// A request params used by the host application to set the Geolocation permission state for an origin. +@immutable +class GeolocationPermissionsRequestParams { + /// [origin]: The origin for which permissions are set. + const GeolocationPermissionsRequestParams({ + required this.origin, + }); + + /// [origin]: The origin for which permissions are set. + final String origin; +} + +/// A response used by the host application to set the Geolocation permission state for an origin. +@immutable +class GeolocationPermissionsResponse { + /// [allow]: Whether or not the origin should be allowed to use the Geolocation API. + /// + /// [retain]: Whether the permission should be retained beyond the lifetime of + /// a page currently being displayed by a WebView. + const GeolocationPermissionsResponse({ + required this.allow, + required this.retain, + }); + + /// Whether or not the origin should be allowed to use the Geolocation API. + final bool allow; + + /// Whether the permission should be retained beyond the lifetime of + /// a page currently being displayed by a WebView. + final bool retain; +} + +/// Mode of how to select files for a file chooser. +enum FileSelectorMode { + /// Open single file and requires that the file exists before allowing the + /// user to pick it. + open, + + /// Similar to [open] but allows multiple files to be selected. + openMultiple, + + /// Allows picking a nonexistent file and saving it. + save, +} + +/// Parameters received when the `WebView` should show a file selector. +@immutable +class FileSelectorParams { + /// Constructs a [FileSelectorParams]. + const FileSelectorParams({ + required this.isCaptureEnabled, + required this.acceptTypes, + this.filenameHint, + required this.mode, + }); + + factory FileSelectorParams._fromFileChooserParams( + ohos_webview.FileChooserParams params, + ) { + final FileSelectorMode mode; + switch (params.mode) { + case ohos_webview.FileChooserMode.open: + mode = FileSelectorMode.open; + case ohos_webview.FileChooserMode.openMultiple: + mode = FileSelectorMode.openMultiple; + case ohos_webview.FileChooserMode.save: + mode = FileSelectorMode.save; + } + + return FileSelectorParams( + isCaptureEnabled: params.isCaptureEnabled, + acceptTypes: params.acceptTypes, + mode: mode, + filenameHint: params.filenameHint, + ); + } + + /// Preference for a live media captured value (e.g. Camera, Microphone). + final bool isCaptureEnabled; + + /// A list of acceptable MIME types. + final List acceptTypes; + + /// The file name of a default selection if specified, or null. + final String? filenameHint; + + /// Mode of how to select files for a file selector. + final FileSelectorMode mode; +} + +/// An implementation of [JavaScriptChannelParams] with the Ohos WebView API. +/// +/// See [OhosWebViewController.addJavaScriptChannel]. +@immutable +class OhosJavaScriptChannelParams extends JavaScriptChannelParams { + /// Constructs a [OhosJavaScriptChannelParams]. + OhosJavaScriptChannelParams({ + required super.name, + required super.onMessageReceived, + @visibleForTesting OhosWebViewProxy webViewProxy = const OhosWebViewProxy(), + }) : assert(name.isNotEmpty), + _javaScriptChannel = webViewProxy.createJavaScriptChannel( + name, + postMessage: withWeakReferenceTo( + onMessageReceived, + (WeakReference weakReference) { + return ( + String message, + ) { + if (weakReference.target != null) { + weakReference.target!( + JavaScriptMessage(message: message), + ); + } + }; + }, + ), + ); + + /// Constructs a [OhosJavaScriptChannelParams] using a + /// [JavaScriptChannelParams]. + OhosJavaScriptChannelParams.fromJavaScriptChannelParams( + JavaScriptChannelParams params, { + @visibleForTesting OhosWebViewProxy webViewProxy = const OhosWebViewProxy(), + }) : this( + name: params.name, + onMessageReceived: params.onMessageReceived, + webViewProxy: webViewProxy, + ); + + final ohos_webview.JavaScriptChannel _javaScriptChannel; +} + +/// Object specifying creation parameters for creating a [OhosWebViewWidget]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebViewWidgetCreationParams] for +/// more information. +@immutable +class OhosWebViewWidgetCreationParams + extends PlatformWebViewWidgetCreationParams { + /// Creates [OhosWebWidgetCreationParams]. + OhosWebViewWidgetCreationParams({ + super.key, + required super.controller, + super.layoutDirection, + super.gestureRecognizers, + this.displayWithHybridComposition = false, + @visibleForTesting InstanceManager? instanceManager, + @visibleForTesting + this.platformViewsServiceProxy = const PlatformViewsServiceProxy(), + }) : instanceManager = + instanceManager ?? ohos_webview.OhosObject.globalInstanceManager; + + /// Constructs a [WebKitWebViewWidgetCreationParams] using a + /// [PlatformWebViewWidgetCreationParams]. + OhosWebViewWidgetCreationParams.fromPlatformWebViewWidgetCreationParams( + PlatformWebViewWidgetCreationParams params, { + bool displayWithHybridComposition = false, + @visibleForTesting InstanceManager? instanceManager, + @visibleForTesting PlatformViewsServiceProxy platformViewsServiceProxy = + const PlatformViewsServiceProxy(), + }) : this( + key: params.key, + controller: params.controller, + layoutDirection: params.layoutDirection, + gestureRecognizers: params.gestureRecognizers, + displayWithHybridComposition: displayWithHybridComposition, + instanceManager: instanceManager, + platformViewsServiceProxy: platformViewsServiceProxy, + ); + + /// Maintains instances used to communicate with the native objects they + /// represent. + /// + /// This field is exposed for testing purposes only and should not be used + /// outside of tests. + @visibleForTesting + final InstanceManager instanceManager; + + /// Proxy that provides access to the platform views service. + /// + /// This service allows creating and controlling platform-specific views. + @visibleForTesting + final PlatformViewsServiceProxy platformViewsServiceProxy; + + /// Whether the [WebView] will be displayed using the Hybrid Composition + /// PlatformView implementation. + /// + /// For most use cases, this flag should be set to false. Hybrid Composition + /// can have performance costs but doesn't have the limitation of rendering to + /// an Ohos SurfaceTexture. See + /// * https://flutter.dev/docs/development/platform-integration/platform-views#performance + /// * https://github.com/flutter/flutter/issues/104889 + /// * https://github.com/flutter/flutter/issues/116954 + /// + /// Defaults to false. + final bool displayWithHybridComposition; + + @override + int get hashCode => Object.hash( + controller, + layoutDirection, + displayWithHybridComposition, + platformViewsServiceProxy, + instanceManager, + ); + + @override + bool operator ==(Object other) { + return other is OhosWebViewWidgetCreationParams && + controller == other.controller && + layoutDirection == other.layoutDirection && + displayWithHybridComposition == other.displayWithHybridComposition && + platformViewsServiceProxy == other.platformViewsServiceProxy && + instanceManager == other.instanceManager; + } +} + +/// An implementation of [PlatformWebViewWidget] with the Ohos WebView API. +class OhosWebViewWidget extends PlatformWebViewWidget { + /// Constructs a [WebKitWebViewWidget]. + OhosWebViewWidget(PlatformWebViewWidgetCreationParams params) + : super.implementation( + params is OhosWebViewWidgetCreationParams + ? params + : OhosWebViewWidgetCreationParams + .fromPlatformWebViewWidgetCreationParams(params), + ); + + OhosWebViewWidgetCreationParams get _ohosParams => + params as OhosWebViewWidgetCreationParams; + + @override + Widget build(BuildContext context) { + _trySetDefaultOnShowCustomWidgetCallbacks(context); + return PlatformViewLink( + // Setting a default key using `params` ensures the `PlatformViewLink` + // recreates the PlatformView when changes are made. + key: _ohosParams.key ?? + ValueKey( + params as OhosWebViewWidgetCreationParams), + viewType: 'plugins.flutter.io/webview', + surfaceFactory: ( + BuildContext context, + PlatformViewController controller, + ) { + return OhosViewSurface( + controller: controller as OhosViewController, + gestureRecognizers: _ohosParams.gestureRecognizers, + hitTestBehavior: PlatformViewHitTestBehavior.opaque, + ); + }, + onCreatePlatformView: (PlatformViewCreationParams params) { + return _initOhosView( + params, + displayWithHybridComposition: + _ohosParams.displayWithHybridComposition, + ) + ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) + ..create(); + }, + ); + } + + OhosViewController _initOhosView( + PlatformViewCreationParams params, { + required bool displayWithHybridComposition, + }) { + if (displayWithHybridComposition) { + return _ohosParams.platformViewsServiceProxy.initExpensiveOhosView( + id: params.id, + viewType: 'plugins.flutter.io/webview', + layoutDirection: _ohosParams.layoutDirection, + creationParams: _ohosParams.instanceManager.getIdentifier( + (_ohosParams.controller as OhosWebViewController)._webView), + creationParamsCodec: const StandardMessageCodec(), + ); + } else { + return _ohosParams.platformViewsServiceProxy.initSurfaceOhosView( + id: params.id, + viewType: 'plugins.flutter.io/webview', + layoutDirection: _ohosParams.layoutDirection, + creationParams: _ohosParams.instanceManager.getIdentifier( + (_ohosParams.controller as OhosWebViewController)._webView), + creationParamsCodec: const StandardMessageCodec(), + ); + } + } + + + // Attempt to handle custom views with a default implementation if it has not + // been set. + void _trySetDefaultOnShowCustomWidgetCallbacks(BuildContext context) { + final OhosWebViewController controller = + _ohosParams.controller as OhosWebViewController; + + if (controller._onShowCustomWidgetCallback == null) { + controller.setCustomWidgetCallbacks( + onShowCustomWidget: + (Widget widget, OnHideCustomWidgetCallback callback) { + Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => widget, + fullscreenDialog: true, + )); + }, + onHideCustomWidget: () { + Navigator.of(context).pop(); + }, + ); + } + } +} + +/// Represents a Flutter implementation of the Android [View](https://developer.android.com/reference/android/view/View) +/// that is created by the host platform when web content needs to be displayed +/// in fullscreen mode. +/// +/// The [OhosCustomViewWidget] cannot be manually instantiated and is +/// provided to the host application through the callbacks specified using the +/// [OhosWebViewController.setCustomWidgetCallbacks] method. +/// +/// The [OhosCustomViewWidget] is initialized internally and should only be +/// exposed as a [Widget] externally. The type [OhosCustomViewWidget] is +/// visible for testing purposes only and should never be called externally. +@visibleForTesting +class OhosCustomViewWidget extends StatelessWidget { + /// Creates a [OhosCustomViewWidget]. + /// + /// The [OhosCustomViewWidget] should only be instantiated internally. + /// This constructor is visible for testing purposes only and should + /// never be called externally. + @visibleForTesting + OhosCustomViewWidget.private({ + super.key, + required this.controller, + required this.customView, + @visibleForTesting InstanceManager? instanceManager, + @visibleForTesting + this.platformViewsServiceProxy = const PlatformViewsServiceProxy(), + }) : instanceManager = + instanceManager ?? ohos_webview.OhosObject.globalInstanceManager; + + /// The reference to the Android native view that should be shown. + final ohos_webview.View customView; + + /// The [PlatformWebViewController] that allows controlling the native web + /// view. + final PlatformWebViewController controller; + + /// Maintains instances used to communicate with the native objects they + /// represent. + /// + /// This field is exposed for testing purposes only and should not be used + /// outside of tests. + @visibleForTesting + final InstanceManager instanceManager; + + /// Proxy that provides access to the platform views service. + /// + /// This service allows creating and controlling platform-specific views. + @visibleForTesting + final PlatformViewsServiceProxy platformViewsServiceProxy; + + OhosWebViewWidgetCreationParams get _ohosParams => + controller.params as OhosWebViewWidgetCreationParams; + + @override + Widget build(BuildContext context) { + return OhosView( + key: _ohosParams.key ?? + ValueKey(_ohosParams), + viewType: 'plugins.flutter.io/webview', + layoutDirection: _ohosParams.layoutDirection, + creationParams: _ohosParams.instanceManager.getIdentifier( + (_ohosParams.controller as OhosWebViewController)._webView), + creationParamsCodec: const StandardMessageCodec(), + gestureRecognizers: _ohosParams.gestureRecognizers, + ); + } + +} + +/// Signature for the `loadRequest` callback responsible for loading the [url] +/// after a navigation request has been approved. +typedef LoadRequestCallback = Future Function(LoadRequestParams params); + +/// Error returned in `WebView.onWebResourceError` when a web resource loading error has occurred. +@immutable +class OhosWebResourceError extends WebResourceError { + /// Creates a new [OhosWebResourceError]. + OhosWebResourceError._({ + required super.errorCode, + required super.description, + super.isForMainFrame, + super.url, + }) : failingUrl = url, + super( + errorType: _errorCodeToErrorType(errorCode), + ); + + /// Gets the URL for which the failing resource request was made. + @Deprecated('Please use `url`.') + final String? failingUrl; + + static WebResourceErrorType? _errorCodeToErrorType(int errorCode) { + switch (errorCode) { + case ohos_webview.WebViewClient.errorAuthentication: + return WebResourceErrorType.authentication; + case ohos_webview.WebViewClient.errorBadUrl: + return WebResourceErrorType.badUrl; + case ohos_webview.WebViewClient.errorConnect: + return WebResourceErrorType.connect; + case ohos_webview.WebViewClient.errorFailedSslHandshake: + return WebResourceErrorType.failedSslHandshake; + case ohos_webview.WebViewClient.errorFile: + return WebResourceErrorType.file; + case ohos_webview.WebViewClient.errorFileNotFound: + return WebResourceErrorType.fileNotFound; + case ohos_webview.WebViewClient.errorHostLookup: + return WebResourceErrorType.hostLookup; + case ohos_webview.WebViewClient.errorIO: + return WebResourceErrorType.io; + case ohos_webview.WebViewClient.errorProxyAuthentication: + return WebResourceErrorType.proxyAuthentication; + case ohos_webview.WebViewClient.errorRedirectLoop: + return WebResourceErrorType.redirectLoop; + case ohos_webview.WebViewClient.errorTimeout: + return WebResourceErrorType.timeout; + case ohos_webview.WebViewClient.errorTooManyRequests: + return WebResourceErrorType.tooManyRequests; + case ohos_webview.WebViewClient.errorUnknown: + return WebResourceErrorType.unknown; + case ohos_webview.WebViewClient.errorUnsafeResource: + return WebResourceErrorType.unsafeResource; + case ohos_webview.WebViewClient.errorUnsupportedAuthScheme: + return WebResourceErrorType.unsupportedAuthScheme; + case ohos_webview.WebViewClient.errorUnsupportedScheme: + return WebResourceErrorType.unsupportedScheme; + } + + if (errorCode < 0) { + return WebResourceErrorType.unknown; + } + + throw ArgumentError( + 'Could not find a WebResourceErrorType for errorCode: $errorCode', + ); + } +} + +/// Object specifying creation parameters for creating a [OhosNavigationDelegate]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformNavigationDelegateCreationParams] for +/// more information. +@immutable +class OhosNavigationDelegateCreationParams + extends PlatformNavigationDelegateCreationParams { + /// Creates a new [OhosNavigationDelegateCreationParams] instance. + const OhosNavigationDelegateCreationParams._({ + @visibleForTesting this.ohosWebViewProxy = const OhosWebViewProxy(), + }) : super(); + + /// Creates a [OhosNavigationDelegateCreationParams] instance based on [PlatformNavigationDelegateCreationParams]. + factory OhosNavigationDelegateCreationParams.fromPlatformNavigationDelegateCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformNavigationDelegateCreationParams params, { + @visibleForTesting + OhosWebViewProxy ohosWebViewProxy = const OhosWebViewProxy(), + }) { + return OhosNavigationDelegateCreationParams._( + ohosWebViewProxy: ohosWebViewProxy, + ); + } + + /// Handles constructing objects and calling static methods for the Ohos WebView + /// native library. + @visibleForTesting + final OhosWebViewProxy ohosWebViewProxy; +} + +/// Ohos details of the change to a web view's url. +class OhosUrlChange extends UrlChange { + /// Constructs an [OhosUrlChange]. + const OhosUrlChange({required super.url, required this.isReload}); + + /// Whether the url is being reloaded. + final bool isReload; +} + +/// A place to register callback methods responsible to handle navigation events +/// triggered by the [ohos_webview.WebView]. +class OhosNavigationDelegate extends PlatformNavigationDelegate { + /// Creates a new [OhosNavigationDelegate]. + OhosNavigationDelegate(PlatformNavigationDelegateCreationParams params) + : super.implementation(params is OhosNavigationDelegateCreationParams + ? params + : OhosNavigationDelegateCreationParams + .fromPlatformNavigationDelegateCreationParams(params)) { + final WeakReference weakThis = + WeakReference(this); + + _webViewClient = (this.params as OhosNavigationDelegateCreationParams) + .ohosWebViewProxy + .createOhosWebViewClient( + onPageFinished: (ohos_webview.WebView webView, String url) { + final PageEventCallback? callback = weakThis.target?._onPageFinished; + if (callback != null) { + callback(url); + } + }, + onPageStarted: (ohos_webview.WebView webView, String url) { + final PageEventCallback? callback = weakThis.target?._onPageStarted; + if (callback != null) { + callback(url); + } + }, + onReceivedHttpError: ( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceResponse response, + ) { + if (weakThis.target?._onHttpError != null) { + weakThis.target!._onHttpError!( + HttpResponseError( + request: WebResourceRequest( + uri: Uri.parse(request.url), + ), + response: WebResourceResponse( + uri: null, + statusCode: response.statusCode, + ), + ), + ); + } + }, + onReceivedRequestError: ( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ohos_webview.WebResourceError error, + ) { + final WebResourceErrorCallback? callback = + weakThis.target?._onWebResourceError; + if (callback != null) { + callback(OhosWebResourceError._( + errorCode: error.errorCode, + description: error.description, + url: request.url, + isForMainFrame: request.isForMainFrame, + )); + } + }, + onReceivedError: ( + ohos_webview.WebView webView, + int errorCode, + String description, + String failingUrl, + ) { + final WebResourceErrorCallback? callback = + weakThis.target?._onWebResourceError; + if (callback != null) { + callback(OhosWebResourceError._( + errorCode: errorCode, + description: description, + url: failingUrl, + isForMainFrame: true, + )); + } + }, + requestLoading: ( + ohos_webview.WebView webView, + ohos_webview.WebResourceRequest request, + ) { + weakThis.target?._handleNavigation( + request.url, + headers: request.requestHeaders, + isForMainFrame: request.isForMainFrame, + ); + }, + urlLoading: (ohos_webview.WebView webView, String url) { + weakThis.target?._handleNavigation(url, isForMainFrame: true); + }, + doUpdateVisitedHistory: ( + ohos_webview.WebView webView, + String url, + bool isReload, + ) { + final UrlChangeCallback? callback = weakThis.target?._onUrlChange; + if (callback != null) { + callback(OhosUrlChange(url: url, isReload: isReload)); + } + }, + onReceivedHttpAuthRequest: ( + ohos_webview.WebView webView, + ohos_webview.HttpAuthHandler httpAuthHandler, + String host, + String realm, + ) { + final void Function(HttpAuthRequest)? callback = + weakThis.target?._onHttpAuthRequest; + if (callback != null) { + callback( + HttpAuthRequest( + onProceed: (WebViewCredential credential) { + httpAuthHandler.proceed(credential.user, credential.password); + }, + onCancel: () { + httpAuthHandler.cancel(); + }, + host: host, + realm: realm, + ), + ); + } else { + httpAuthHandler.cancel(); + } + }, + ); + + _downloadListener = (this.params as OhosNavigationDelegateCreationParams) + .ohosWebViewProxy + .createDownloadListener( + onDownloadStart: ( + String url, + String userAgent, + String contentDisposition, + String mimetype, + int contentLength, + ) { + if (weakThis.target != null) { + weakThis.target?._handleNavigation(url, isForMainFrame: true); + } + }, + ); + } + + OhosNavigationDelegateCreationParams get _ohosParams => + params as OhosNavigationDelegateCreationParams; + + late final ohos_webview.WebChromeClient _webChromeClient = + _ohosParams.ohosWebViewProxy.createOhosWebChromeClient(); + + /// Gets the native [ohos_webview.WebChromeClient] that is bridged by this [OhosNavigationDelegate]. + /// + /// Used by the [OhosWebViewController] to set the `ohos_webview.WebView.setWebChromeClient`. + @Deprecated( + 'This value is not used by `OhosWebViewController` and has no effect on the `WebView`.', + ) + ohos_webview.WebChromeClient get ohosWebChromeClient => _webChromeClient; + + late final ohos_webview.WebViewClient _webViewClient; + + /// Gets the native [ohos_webview.WebViewClient] that is bridged by this [OhosNavigationDelegate]. + /// + /// Used by the [OhosWebViewController] to set the `ohos_webview.WebView.setWebViewClient`. + ohos_webview.WebViewClient get ohosWebViewClient => _webViewClient; + + late final ohos_webview.DownloadListener _downloadListener; + + /// Gets the native [ohos_webview.DownloadListener] that is bridged by this [OhosNavigationDelegate]. + /// + /// Used by the [OhosWebViewController] to set the `ohos_webview.WebView.setDownloadListener`. + ohos_webview.DownloadListener get ohosDownloadListener => _downloadListener; + + PageEventCallback? _onPageFinished; + PageEventCallback? _onPageStarted; + HttpResponseErrorCallback? _onHttpError; + ProgressCallback? _onProgress; + WebResourceErrorCallback? _onWebResourceError; + NavigationRequestCallback? _onNavigationRequest; + LoadRequestCallback? _onLoadRequest; + UrlChangeCallback? _onUrlChange; + HttpAuthRequestCallback? _onHttpAuthRequest; + + void _handleNavigation( + String url, { + required bool isForMainFrame, + Map headers = const {}, + }) { + final LoadRequestCallback? onLoadRequest = _onLoadRequest; + final NavigationRequestCallback? onNavigationRequest = _onNavigationRequest; + + // The client is only allowed to stop navigations that target the main frame because + // overridden URLs are passed to `loadUrl` and `loadUrl` cannot load a subframe. + if (!isForMainFrame || + onNavigationRequest == null || + onLoadRequest == null) { + return; + } + + final FutureOr returnValue = onNavigationRequest( + NavigationRequest( + url: url, + isMainFrame: isForMainFrame, + ), + ); + + if (returnValue is NavigationDecision && + returnValue == NavigationDecision.navigate) { + onLoadRequest(LoadRequestParams( + uri: Uri.parse(url), + headers: headers, + )); + } else if (returnValue is Future) { + returnValue.then((NavigationDecision shouldLoadUrl) { + if (shouldLoadUrl == NavigationDecision.navigate) { + onLoadRequest(LoadRequestParams( + uri: Uri.parse(url), + headers: headers, + )); + } + }); + } + } + + /// Invoked when loading the url after a navigation request is approved. + Future setOnLoadRequest( + LoadRequestCallback onLoadRequest, + ) async { + _onLoadRequest = onLoadRequest; + } + + @override + Future setOnNavigationRequest( + NavigationRequestCallback onNavigationRequest, + ) async { + _onNavigationRequest = onNavigationRequest; + return _webViewClient + .setSynchronousReturnValueForShouldOverrideUrlLoading(true); + } + + @override + Future setOnPageStarted( + PageEventCallback onPageStarted, + ) async { + _onPageStarted = onPageStarted; + } + + @override + Future setOnPageFinished( + PageEventCallback onPageFinished, + ) async { + _onPageFinished = onPageFinished; + } + + @override + Future setOnHttpError( + HttpResponseErrorCallback onHttpError, + ) async { + _onHttpError = onHttpError; + } + + @override + Future setOnProgress( + ProgressCallback onProgress, + ) async { + _onProgress = onProgress; + } + + @override + Future setOnWebResourceError( + WebResourceErrorCallback onWebResourceError, + ) async { + _onWebResourceError = onWebResourceError; + } + + @override + Future setOnUrlChange(UrlChangeCallback onUrlChange) async { + _onUrlChange = onUrlChange; + } + + @override + Future setOnHttpAuthRequest( + HttpAuthRequestCallback onHttpAuthRequest, + ) async { + _onHttpAuthRequest = onHttpAuthRequest; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_cookie_manager.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_cookie_manager.dart new file mode 100644 index 0000000000000000000000000000000000000000..be2312bd66a9e0ec19928eea9b1735d51d2f545c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_cookie_manager.dart @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flutter/foundation.dart'; +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; + +import 'ohos_webview.dart'; +import 'ohos_webview_controller.dart'; + +/// Object specifying creation parameters for creating a [OhosWebViewCookieManager]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebViewCookieManagerCreationParams] for +/// more information. +@immutable +class OhosWebViewCookieManagerCreationParams + extends PlatformWebViewCookieManagerCreationParams { + /// Creates a new [OhosWebViewCookieManagerCreationParams] instance. + const OhosWebViewCookieManagerCreationParams._( + // This parameter prevents breaking changes later. + // ignore: avoid_unused_constructor_parameters + PlatformWebViewCookieManagerCreationParams params, + ) : super(); + + /// Creates a [OhosWebViewCookieManagerCreationParams] instance based on [PlatformWebViewCookieManagerCreationParams]. + factory OhosWebViewCookieManagerCreationParams.fromPlatformWebViewCookieManagerCreationParams( + PlatformWebViewCookieManagerCreationParams params) { + return OhosWebViewCookieManagerCreationParams._(params); + } +} + +/// Handles all cookie operations for the Ohos platform. +class OhosWebViewCookieManager extends PlatformWebViewCookieManager { + /// Creates a new [OhosWebViewCookieManager]. + OhosWebViewCookieManager( + PlatformWebViewCookieManagerCreationParams params, { + CookieManager? cookieManager, + }) : _cookieManager = cookieManager ?? CookieManager.instance, + super.implementation( + params is OhosWebViewCookieManagerCreationParams + ? params + : OhosWebViewCookieManagerCreationParams + .fromPlatformWebViewCookieManagerCreationParams(params), + ); + + final CookieManager _cookieManager; + + @override + Future clearCookies() { + return _cookieManager.removeAllCookies(); + } + + @override + Future setCookie(WebViewCookie cookie) { + if (!_isValidPath(cookie.path)) { + throw ArgumentError( + 'The path property for the provided cookie was not given a legal value.'); + } + return _cookieManager.setCookie( + cookie.domain, + '${Uri.encodeComponent(cookie.name)}=${Uri.encodeComponent(cookie.value)}; path=${cookie.path}', + ); + } + + bool _isValidPath(String path) { + // Permitted ranges based on RFC6265bis: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.1 + for (final int char in path.codeUnits) { + if ((char < 0x20 || char > 0x3A) && (char < 0x3C || char > 0x7E)) { + return false; + } + } + return true; + } + + /// Sets whether the WebView should allow third party cookies to be set. + /// + /// Apps that target `Build.VERSION_CODES.KITKAT` or below default to allowing + /// third party cookies. Apps targeting `Build.VERSION_CODES.LOLLIPOP` or + /// later default to disallowing third party cookies. + Future setAcceptThirdPartyCookies( + OhosWebViewController controller, + bool accept, + ) { + // ignore: invalid_use_of_visible_for_testing_member + final WebView webView = WebView.api.instanceManager + .getInstanceWithWeakReference(controller.webViewIdentifier)!; + return _cookieManager.setAcceptThirdPartyCookies(webView, accept); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_platform.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_platform.dart new file mode 100644 index 0000000000000000000000000000000000000000..a9d820cda1e770e541bb8c3422bfea780a9c882b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/ohos_webview_platform.dart @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart'; + +import 'ohos_webview_controller.dart'; +import 'ohos_webview_cookie_manager.dart'; + +/// Implementation of [WebViewPlatform] using the WebKit API. +class OhosWebViewPlatform extends WebViewPlatform { + /// Registers this class as the default instance of [WebViewPlatform]. + static void registerWith() { + WebViewPlatform.instance = OhosWebViewPlatform(); + } + + @override + OhosWebViewController createPlatformWebViewController( + PlatformWebViewControllerCreationParams params, + ) { + return OhosWebViewController(params); + } + + @override + OhosNavigationDelegate createPlatformNavigationDelegate( + PlatformNavigationDelegateCreationParams params, + ) { + return OhosNavigationDelegate(params); + } + + @override + OhosWebViewWidget createPlatformWebViewWidget( + PlatformWebViewWidgetCreationParams params, + ) { + return OhosWebViewWidget(params); + } + + @override + OhosWebViewCookieManager createPlatformCookieManager( + PlatformWebViewCookieManagerCreationParams params, + ) { + return OhosWebViewCookieManager(params); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/platform_views_service_proxy.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/platform_views_service_proxy.dart new file mode 100644 index 0000000000000000000000000000000000000000..8afb6920dc0c63ecfc504f81d75d823979af585f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/platform_views_service_proxy.dart @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +/// Proxy that provides access to the platform views service. +/// +/// This service allows creating and controlling platform-specific views. +@immutable +class PlatformViewsServiceProxy { + /// Constructs a [PlatformViewsServiceProxy]. + const PlatformViewsServiceProxy(); + + /// Proxy method for [PlatformViewsService.initExpensiveAndroidView]. + ExpensiveOhosViewController initExpensiveOhosView({ + required int id, + required String viewType, + required TextDirection layoutDirection, + dynamic creationParams, + MessageCodec? creationParamsCodec, + VoidCallback? onFocus, + }) { + return PlatformViewsService.initExpensiveOhosView( + id: id, + viewType: viewType, + layoutDirection: layoutDirection, + creationParams: creationParams, + creationParamsCodec: creationParamsCodec, + onFocus: onFocus, + ); + } + + /// Proxy method for [PlatformViewsService.initSurfaceAndroidView]. + SurfaceOhosViewController initSurfaceOhosView({ + required int id, + required String viewType, + required TextDirection layoutDirection, + dynamic creationParams, + MessageCodec? creationParamsCodec, + VoidCallback? onFocus, + }) { + return PlatformViewsService.initSurfaceOhosView( + id: id, + viewType: viewType, + layoutDirection: layoutDirection, + creationParams: creationParams, + creationParamsCodec: creationParamsCodec, + onFocus: onFocus, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/weak_reference_utils.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/weak_reference_utils.dart new file mode 100644 index 0000000000000000000000000000000000000000..d75a50d175d02a5fc7dd6d8e285381e72ae254a8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/weak_reference_utils.dart @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// Helper method for creating callbacks methods with a weak reference. +/// +/// Example: +/// ``` +/// final JavascriptChannelRegistry javascriptChannelRegistry = ... +/// +/// final WKScriptMessageHandler handler = WKScriptMessageHandler( +/// didReceiveScriptMessage: withWeakReferenceTo( +/// javascriptChannelRegistry, +/// (WeakReference weakReference) { +/// return ( +/// WKUserContentController userContentController, +/// WKScriptMessage message, +/// ) { +/// weakReference.target?.onJavascriptChannelMessage( +/// message.name, +/// message.body!.toString(), +/// ); +/// }; +/// }, +/// ), +/// ); +/// ``` +S withWeakReferenceTo( + T reference, + S Function(WeakReference weakReference) onCreate, +) { + final WeakReference weakReference = WeakReference(reference); + return onCreate(weakReference); +} diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/src/webview_flutter_ohos_legacy.dart b/packages/webview_flutter/webview_flutter_ohos/lib/src/webview_flutter_ohos_legacy.dart new file mode 100644 index 0000000000000000000000000000000000000000..8a24d7039607573abe0f4007ab6f4b13769b6a0f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/src/webview_flutter_ohos_legacy.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'legacy/webview_ohos.dart'; +export 'legacy/webview_ohos_cookie_manager.dart'; +export 'legacy/webview_surface_ohos.dart'; diff --git a/packages/webview_flutter/webview_flutter_ohos/lib/webview_flutter_ohos.dart b/packages/webview_flutter/webview_flutter_ohos/lib/webview_flutter_ohos.dart new file mode 100644 index 0000000000000000000000000000000000000000..2c91bfde3457af0f8bf6c8a7d8a37d4e68fe00f7 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/lib/webview_flutter_ohos.dart @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export 'src/ohos_webview_controller.dart'; +export 'src/ohos_webview_cookie_manager.dart'; +export 'src/ohos_webview_platform.dart'; diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/.gitignore b/packages/webview_flutter/webview_flutter_ohos/ohos/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6f7b4f89c49a6abadc383d9665d3b4c171d466bc --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/.gitignore @@ -0,0 +1,17 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test + +/entry/libs/arm64-v8a/libflutter.so +/entry/src/main/resources/rawfile/flutter_assets +**.har +**/oh-package-lock.json5 +BuildProfile.ets diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/Index.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..8e2fcd6e4f1234f2b6c65865bd54f436ecae7070 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/Index.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { WebViewFlutterPlugin } from './src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterPlugin' + +export default WebViewFlutterPlugin \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/build-profile.json5 b/packages/webview_flutter/webview_flutter_ohos/ohos/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..989c850d90269886e5bbab58d829e9ba7257ebe1 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/build-profile.json5 @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "targets": [ + { + "name": "default" + } + ] +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/consumer-rules.txt b/packages/webview_flutter/webview_flutter_ohos/ohos/consumer-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/hvigorfile.ts b/packages/webview_flutter/webview_flutter_ohos/ohos/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..d3aba127d60569f70f3bc6eacc9db994eb9af8f6 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/hvigorfile.ts @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/obfuscation-rules.txt b/packages/webview_flutter/webview_flutter_ohos/ohos/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..985b2aeb7658286b17bd26eab8f217c3fe75ea8b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/obfuscation-rules.txt @@ -0,0 +1,18 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/oh-package.json5 b/packages/webview_flutter/webview_flutter_ohos/ohos/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b1720bc0af4c031a90920ebfdad3d1bf40c4cdef --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/oh-package.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "webview_flutter_ohos", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:libs/flutter.har" + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CookieManagerHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CookieManagerHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..b7130258041111c85a92bb33c68eacc740879088 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CookieManagerHostApiImpl.ets @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { Result } from './GeneratedOhosWebView' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { InstanceManager } from './InstanceManager' +import { CookieManagerHostApi } from './GeneratedOhosWebView'; +import web_webview from '@ohos.web.webview' +export class CookieManagerHostApiImpl extends CookieManagerHostApi { + private binaryMessenger: BinaryMessenger; + private instanceManager: InstanceManager; + + constructor(binaryMessenger: BinaryMessenger , instanceManager: InstanceManager ) { + super() + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + private getCookieManagerInstance(identifier: number): ESObject { + const cookieManagerInstance: ESObject = this.instanceManager.getInstance(identifier) + if (cookieManagerInstance) { + return cookieManagerInstance + } + else { + throw new Error("getCookieManagerInstance, no such instance") + } + } + attachInstance(instanceIdentifier: number) { + + } + + setCookie(identifier: number, url: string, value: string) { + web_webview.WebCookieManager.setCookie(url, value); + } + + setAcceptThirdPartyCookies(identifier: number, accept: boolean) { + web_webview.WebCookieManager.putAcceptThirdPartyCookieEnabled(accept); + } + + removeAllCookies(identifier: number, result: Result ) { + web_webview.WebCookieManager.clearAllCookiesSync() + result.success(true) + } + +} + +export interface cookieManager { + removeAllCookies(identifier: number, result: Result | null): void + + putAcceptThirdPartyCookieEnabled(accept: boolean): void + + setCookie(url: string, value: string): void +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..e02187624e6d0ab32f32b2b7980d948fb5c709b2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackFlutterApiImpl.ets @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { CustomViewCallback, CustomViewCallbackFlutterApi, Reply } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager' + +export class CustomViewCallbackFlutterApiImpl { + binaryMessenger: BinaryMessenger; + instanceManager: InstanceManager; + api: CustomViewCallbackFlutterApi; + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new CustomViewCallbackFlutterApi(binaryMessenger); + } + + create(instance: CustomViewCallback, callback: Reply) { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), callback); + } + } + + setApi(api: CustomViewCallbackFlutterApi) { + this.api = api; + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..61c519fa3c304e8700a1e7246e0b1d4cebc68937 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/CustomViewCallbackHostApiImpl.ets @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { CustomViewCallback, CustomViewCallbackHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager' + +export class CustomViewCallbackHostApiImpl extends CustomViewCallbackHostApi { + // To ease adding additional methods, this value is added prematurely. + + binaryMessenger: BinaryMessenger; + + instanceManager: InstanceManager; + + /** + * Constructs a {@link CustomViewCallbackHostApiImpl}. + * + * @param binaryMessenger used to communicate with Dart over asynchronous messages + * @param instanceManager maintains instances stored to communicate with attached Dart objects + */ + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super() + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + onCustomViewHidden(identifier: number) { + this.getCustomViewCallbackInstance(identifier).onCustomViewHidden(); + } + + getCustomViewCallbackInstance(identifier: number) : CustomViewCallback { + return this.instanceManager.getInstance(identifier); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DisplayListenerProxy.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DisplayListenerProxy.ets new file mode 100644 index 0000000000000000000000000000000000000000..9b9fdba56ae43b3157b8c23569155b4ffcdc1729 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DisplayListenerProxy.ets @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import display from '@ohos.display'; + +export class DisplayListenerProxy { + private static TAG = "DisplayListenerProxy"; + + private listenersBeforeWebView: mDisplay[] = new Array(); + + async onPreWebViewInitialization(): Promise { + this.listenersBeforeWebView = (await this.yoinkDisplayListeners()) as mDisplay[]; + } + + private async yoinkDisplayListeners(): Promise { + const res = await display.getAllDisplays() + return res + } + + async onPostWebViewInitialization() { + let webViewListeners: mDisplay[] = (await this.yoinkDisplayListeners()) as mDisplay[]; + + webViewListeners = webViewListeners.filter((item: ESObject) => this.listenersBeforeWebView.indexOf(item) === -1) + + if (webViewListeners.length === 0) { + return; + } + + const onDisplayAdded = (displayId: number) => { + for (let display of webViewListeners) { + display.addCallback(displayId); + } + } + + const onDisplayRemoved = (displayId: number) => { + for (let display of webViewListeners) { + display.removeCallback(displayId); + } + } + + const onDisplayChanged = (displayId: number) => { + if (webViewListeners.filter(item => item.id === displayId).length === 0) { + return; + } + for (let display of webViewListeners) { + display.changeCallback(displayId); + } + } + + for (let display of webViewListeners) { + display.changeCallback = onDisplayChanged; + display.addCallback = onDisplayAdded; + display.removeCallback = onDisplayRemoved + } + + for (let display of webViewListeners) { + display.off("remove"); + display.off("add"); + display.off("change"); + + display.on("remove", onDisplayRemoved) + display.on("add", onDisplayAdded) + display.on("change", onDisplayChanged) + } + } +} + +interface mDisplay extends display.Display { + on: ESObject, + off: ESObject, + changeCallback, + removeCallback, + addCallback, +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..16c6a7540e9835d089f24a5b0f75c12b2a787017 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerFlutterApiImpl.ets @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { InstanceManager } from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { Reply, DownloadListenerFlutterApi, FileChooserMode } from "./GeneratedOhosWebView" + +export class DownloadListenerFlutterApiImpl extends DownloadListenerFlutterApi { + private instanceManager: InstanceManager; + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + } + + /** Passes arguments from {@link DownloadListener#onDownloadStart} to Dart. */ + onDownloadStart( + downloadListener: WebviewController | ESObject, + url: string, + userAgent: string, + contentDisposition: string, + mimetype: string, contentLength: number, callback: Reply + ) { + super.onDownloadStartT( + this.getIdentifierForListener(downloadListener), + url, + userAgent, + contentDisposition, + mimetype, + contentLength, + callback + ); + } + + getIdentifierForListener(listener: DownloadListener): number { + const identifier = this.instanceManager.getIdentifier(listener); + if (identifier == null) { + throw new Error("Could not find identifier for DownloadListener."); + } + return identifier; + } +} + +export interface DownloadListener { + onDownloadStart(url: string, userAgent: string, contentDisposition: string, mimeType: string, contentLength: number): void; +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..f3ff5f466f4caea9f8d7c34996d1f95797482264 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DownloadListenerHostApiImpl.ets @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { DownloadListenerFlutterApiImpl } from './DownloadListenerFlutterApiImpl'; +import { DownloadListenerHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; + +export class DownloadListenerHostApiImpl extends DownloadListenerHostApi { + private instanceManager: InstanceManager; + + private downloadListenerCreator: DownloadListenerCreator; + + private flutterApi: DownloadListenerFlutterApiImpl; + + constructor( + instanceManager: InstanceManager, downloadListenerCreator: DownloadListenerCreator, + flutterApi: DownloadListenerFlutterApiImpl + ) { + super() + this.instanceManager = instanceManager; + this.downloadListenerCreator = downloadListenerCreator; + this.flutterApi = flutterApi; + } + + create(instanceId: number) { + const downloadListener = DownloadListenerHostApiImpl.createDownloadListener(this.flutterApi); + this.instanceManager.addDartCreatedInstance(downloadListener, instanceId); + } + + static createDownloadListener(flutterApi: DownloadListenerFlutterApiImpl): DownloadListenerImpl { + return new DownloadListenerImpl(flutterApi); + } +} + +export class DownloadListenerCreator { + createDownloadListener(flutterApi: DownloadListenerFlutterApiImpl): DownloadListenerImpl { + return new DownloadListenerImpl(flutterApi); + } +} + +class DownloadListenerImpl implements DownloadListener { + private flutterApi: DownloadListenerFlutterApiImpl; + + constructor(flutterApi: DownloadListenerFlutterApiImpl) { + this.flutterApi = flutterApi; + } + + onDownloadStart(url: string, userAgent: string, contentDisposition: string, mimetype: string, contentLength: number) { + this.flutterApi.onDownloadStart( + this, url, userAgent, contentDisposition, mimetype, contentLength, { reply: () => { + } } + ); + } +} + +export interface DownloadListener { + onDownloadStart(url: string, userAgent: string, contentDisposition: string, mimeType: string, contentLength: number): void; +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DynamicUtils.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DynamicUtils.ets new file mode 100644 index 0000000000000000000000000000000000000000..e22d5a867eb6f4a9266779fb11504e8b26c58d81 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/DynamicUtils.ets @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { DVModelParameters } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView' + +export class DynamicUtils { + static getParams(params: DVModelParameters, element: string): string | ESObject { + let params2 = params as Record; + return params2[element]; + } + + static setParams(params: DVModelParameters, key: string, element: ESObject): void { + let params2 = params as Record; + params2[key] = element; + } +} + +export class DVModelJson { + compType: string + children: Array + attributes: ESObject + events: ESObject + build: ESObject + + constructor(compType: string, children: Array, attributes: ESObject, events: ESObject, build?: ESObject) { + this.compType = compType + this.children = children + this.attributes = attributes + this.events = events; + this.build = build; + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FileChooserParamsFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FileChooserParamsFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..ade29b90b1737f38fab58b2b1874c5f179a5c177 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FileChooserParamsFlutterApiImpl.ets @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { InstanceManager } from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { Reply, FileChooserParamsFlutterApi, FileChooserMode } from "./GeneratedOhosWebView" + +export class FileChooserParamsFlutterApiImpl extends FileChooserParamsFlutterApi { + private instanceManager: InstanceManager; + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + } + + private toFileChooserEnumData(mode: number): FileChooserMode { + switch (mode) { + case FileSelectorMode.FileOpenMode: + return FileChooserMode.OPEN; + + case FileSelectorMode.FileOpenMultipleMode: + return FileChooserMode.OPEN_MULTIPLE; + + case FileSelectorMode.FileSaveMode: + return FileChooserMode.SAVE; + + default: + throw new Error(`Unsupported FileChooserMode: ${mode}`); + } + } + + /** + * Stores the FileChooserParams instance and notifies Dart to create a new FileChooserParams + * instance that is attached to this one. + */ + + create(instance: FileSelectorParam, callback: Reply) { + if (!this.instanceManager.containsInstance(instance)) { + super.tCreate( + this.instanceManager.addHostCreatedInstance(instance), + instance.isCapture(), + instance.getAcceptType(), + this.toFileChooserEnumData(instance.getMode()), + //instance.getFilenameHint(), + callback + ); + } + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManager.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..1aed89fbaf66e09b8528cd33f88035b62ce606ca --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManager.ets @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import resourceManager from '@ohos.resourceManager'; +import { FlutterAssets } from "@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin" + +export abstract class FlutterAssetManager { + private resourceManager: resourceManager.ResourceManager; + + constructor(resourceManager: resourceManager.ResourceManager) { + this.resourceManager = resourceManager; + } + + abstract getAssetFilePathByName(name: string) + + async list(path: string): Promise { + return await this.resourceManager.getRawFileList(path); + } +} + +export class PluginBindingFlutterAssetManager extends FlutterAssetManager { + flutterAssets: FlutterAssets; + + constructor(resourceManager: resourceManager.ResourceManager, flutterAssets: FlutterAssets) { + super(resourceManager); + this.flutterAssets = flutterAssets; + } + + getAssetFilePathByName(name: string): string { + return this.flutterAssets.getAssetFilePathByName(name); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManagerHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManagerHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..5c335ba7ace0f753f30a190ba3d7dbc79fadc986 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterAssetManagerHostApiImpl.ets @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterAssetManager } from './FlutterAssetManager'; +import { FlutterAssetManagerHostApi } from './GeneratedOhosWebView'; +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; + +const TAG:string = "FlutterAssetManagerHostApiImpl" +export class FlutterAssetManagerHostApiImpl extends FlutterAssetManagerHostApi { + private flutterAssetManager: FlutterAssetManager; + + constructor(flutterAssetManager: FlutterAssetManager) { + super() + this.flutterAssetManager = flutterAssetManager; + } + + async list(path: string): Promise { + try { + let paths: string[] = await this.flutterAssetManager.list(path); + if (paths.length == 0) { + return []; + } + return paths; + } catch (err) { + Log.e(TAG, "mkdirSync failed err:" + err); + } + return []; + } + + getAssetFilePathByName(name: string): string { + return this.flutterAssetManager.getAssetFilePathByName(name) + } +} + diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterViewFactory.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterViewFactory.ets new file mode 100644 index 0000000000000000000000000000000000000000..4d615b514522e86ac4e3152cc4d126708067968a --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/FlutterViewFactory.ets @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import common from '@ohos.app.ability.common'; +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; +import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; +import PlatformViewFactory from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory'; +import { InstanceManager } from './InstanceManager'; + +const TAG :string = "FlutterViewFactory"; +export class FlutterViewFactory extends PlatformViewFactory { + private instanceManager:InstanceManager; + + constructor(instanceManager:InstanceManager) { + super(StandardMessageCodec.INSTANCE); + this.instanceManager = instanceManager; + } + + create(context: common.Context, viewId: number, args: ESObject): PlatformView { + Log.i(TAG, "params " + args) + const identifier : number = args; + if (identifier == null) { + throw new Error("An identifier is required to retrieve WebView instance."); + } + const view : PlatformView = this.instanceManager.getInstance(identifier); + if (view == null) { + throw new Error("Unable to find WebView instance: " + args); + } + return view; + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeneratedOhosWebView.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeneratedOhosWebView.ets new file mode 100644 index 0000000000000000000000000000000000000000..43d9331982879e50f8fd63f15e32760e169fb5b2 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeneratedOhosWebView.ets @@ -0,0 +1,3730 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import ArrayList from '@ohos.util.ArrayList'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; +import { ByteBuffer } from '@ohos/flutter_ohos/src/main/ets/util/ByteBuffer'; +import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec'; +import { BinaryMessenger } from "@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger" +import BasicMessageChannel, { MessageHandler } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BasicMessageChannel'; +import { CookieManagerHostApiImpl } from './CookieManagerHostApiImpl'; + +export default class GeneratedOhosWebView { + static wrapError(exception: Error): ArrayList { + const errorList: ArrayList = new ArrayList(); + if (exception instanceof FlutterError) { + const error = exception; + errorList.add(error.code); + errorList.add(error.message); + errorList.add(error.details); + } else { + errorList.add(exception.name); + errorList.add(exception.message); + errorList.add(exception.stack); + } + return errorList; + } +} + +export class FlutterError extends Error { + code: string; + + details: ESObject; + + constructor(code: string, message: string, details: ESObject) { + super(message); + this.code = code; + this.details = details; + } +} + +export interface Result { + success: (result: T) => void; + error: (error: Error) => void; +} + +class ResultBuilder { + success: (result: T) => void; + error: (error: Error) => void; + + constructor(success: (result: T) => void, error: (error: Error) => void) { + this.success = success + this.error = error + } +} + +export enum FileChooserMode { + OPEN, + OPEN_MULTIPLE, + SAVE +} + +interface FileChooserModeEnumDataBuilder { + value: FileChooserMode; + setValue: (setterArg: FileChooserMode) => FileChooserModeEnumDataBuilder; + build: () => FileChooserModeEnumData; +} + +export class FileChooserModeEnumData { + private value: FileChooserMode = 0; + + private constructor() { + } + + getValue(): FileChooserMode { + return this.value; + } + + setValue(setterArg: FileChooserMode) { + if (setterArg == null) { + throw new Error("Nonnull field \"value\" is null.") + } + this.value = setterArg; + } + + public static Builder(): FileChooserModeEnumDataBuilder { + const builder: FileChooserModeEnumDataBuilder = { + value: FileChooserMode.OPEN, + setValue(setterArg: FileChooserMode): FileChooserModeEnumDataBuilder { + builder.value = setterArg; + return builder; + }, + build(): FileChooserModeEnumData { + const pigeonReturn = new FileChooserModeEnumData(); + pigeonReturn.setValue(builder.value); + return pigeonReturn; + } + } + + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.value); + return toArrayResult; + } + + static fromArray(list: Array): FileChooserModeEnumData { + const pigeonResult = new FileChooserModeEnumData(); + const value: number = list[0]; + pigeonResult.setValue(value); + return pigeonResult; + } +} + +interface WebViewPointBuilder { + x: number; + y: number; + setX: (setterArg: number) => WebViewPointBuilder; + setY: (setterArg: number) => WebViewPointBuilder; + build: () => WebViewPoint; +} + +export class WebViewPoint { + private x: number = 0; + + private y: number = 0; + + getX(): number { + return this.x; + } + + setX(setterArg: number): void { + if (setterArg == null) { + throw new Error("Nonnull field \"x\" is null.") + } + this.x = setterArg; + } + + getY(): number { + return this.y; + } + + setY(setterArg: number): void { + if (setterArg == null) { + throw new Error("Nonnull field \"y\" is null.") + } + this.y = setterArg; + } + + private constructor() { + } + + public static Builder(): WebViewPointBuilder { + const builder: WebViewPointBuilder = { + x: 0, + y: 0, + setX(setterArg: number): WebViewPointBuilder { + builder.x = setterArg; + return builder; + }, + + setY(setterArg: number): WebViewPointBuilder { + builder.x = setterArg; + return builder; + }, + build(): WebViewPoint { + const pigeonReturn = new WebViewPoint(); + pigeonReturn.setX(builder.x); + pigeonReturn.setY(builder.y); + return pigeonReturn; + } + }; + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.x); + toArrayResult.push(this.y); + return toArrayResult; + } + + static fromArray(list: Array): WebViewPoint { + const pigeonResult = new WebViewPoint(); + const x: number = list[0]; + pigeonResult.setX(x); + const y: number = list[1]; + pigeonResult.setY(y); + return pigeonResult; + } +} + +class WebViewHostApiCodec extends StandardMessageCodec { + public static INSTANCE: WebViewHostApiCodec = new WebViewHostApiCodec(); + + private constructor() { + super(); + } + + readValueOfType(type: number, buffer: ByteBuffer): ESObject { + switch (type) { + case 128: + return WebViewPoint.fromArray(this.readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + writeValue(stream: ByteBuffer, value: ESObject): ESObject { + if (value instanceof WebViewPoint) { + stream.writeInt8(128); + super.writeValue(stream, value.toArray()); + } else { + super.writeValue(stream, value); + } + } +} + +export abstract class WebViewHostApi { + abstract create(instanceId: number): void; + + abstract loadData( + instanceId: number, + data: string, + mimeType: string, + encoding: string + ): void; + + abstract loadDataWithBaseUrl( + instanceId: number, + baseUrl: string, + data: string, + mimeType: string, + encoding: string, + historyUrl: string + ): void; + + abstract loadUrl( + instanceId: number, + url: string, + headers: Map + ): void; + + abstract postUrl( + instanceId: number, + url: string, + data: Uint8Array + ): void; + + abstract getUrl(instanceId: number): string; + + abstract canGoBack(instanceId: number): boolean; + + abstract canGoForward(instanceId: number): boolean; + + abstract goBack(instanceId: number): void; + + abstract goForward(instanceId: number): void; + + abstract reload(instanceId: number): void; + + abstract clearCache(instanceId: number, includeDiskFiles: boolean): void; + + abstract evaluateJavascript( + instanceId: number, javascriptString: string, result: Result + ): void; + + abstract getTitle(instanceId: number): string; + + abstract scrollTo(instanceId: number, x: number, y: number): void; + + abstract scrollBy(instanceId: number, x: number, y: number): void; + + abstract getScrollX(instanceId: number): number; + + abstract getScrollY(instanceId: number): number; + + abstract getScrollPosition(instanceId: number): WebViewPoint; + + abstract setWebContentsDebuggingEnabled(enabled: boolean): void; + + abstract setWebViewClient(instanceId: number, webViewClientInstanceId: number): void; + + abstract addJavaScriptChannel(instanceId: number, javaScriptChannelInstanceId: number): void; + + abstract removeJavaScriptChannel(instanceId: number, javaScriptChannelInstanceId: number): void; + + abstract setDownloadListener(instanceId: number, listenerInstanceId: number); + + abstract setWebChromeClient(instanceId: number, clientInstanceId: number); + + static getCodec(): MessageCodec { + return WebViewHostApiCodec.INSTANCE; + } + + static setup(binaryMessenger: BinaryMessenger, api: WebViewHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.create", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.create(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadData", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const dataArg: string = args[1]; + const mimeTypeArg: string = args[2]; + const encodingArg: string = args[3]; + try { + api.loadData(instanceIdArg, dataArg, mimeTypeArg, encodingArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadDataWithBaseUrl", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const baseUrlArg: string = args[1]; + const dataArg: string = args[2]; + const mimeTypeArg: string = args[3]; + const encodingArg: string = args[4]; + const historyUrlArg: string = args[5]; + try { + api.loadDataWithBaseUrl( + instanceIdArg, + baseUrlArg, + dataArg, + mimeTypeArg, + encodingArg, + historyUrlArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.loadUrl", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const urlArg: string = args[1]; + const headersArg: Map = args[2]; + try { + api.loadUrl( + instanceIdArg, + urlArg, + headersArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.postUrl", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const urlArg: string = args[1]; + const dataArg: Uint8Array = args[2]; + try { + api.postUrl(instanceIdArg, urlArg, dataArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getUrl", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: string = api.getUrl(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.canGoBack", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: boolean = api.canGoBack(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.canGoForward", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: boolean = api.canGoForward(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.goBack", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.goBack(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.goForward", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.goForward(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.reload", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.reload(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.clearCache", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const includeDiskFilesArg: boolean = args[1]; + try { + api.clearCache(instanceIdArg, includeDiskFilesArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.evaluateJavascript", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const javascriptStringArg: string = args[1]; + const resultCallback: Result = + { + success: (result: string): void => { + wrapped.insert(result, 0); + reply.reply(wrapped.convertToArray()); + }, + + error: (error: Error): void => { + const wrappedError: ArrayList + = GeneratedOhosWebView.wrapError(error); + reply.reply(wrappedError.convertToArray()); + } + }; + api.evaluateJavascript(instanceIdArg, javascriptStringArg, resultCallback); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getTitle", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: string = api.getTitle(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.scrollTo", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const xArg: number = args[1]; + const yArg: number = args[2]; + try { + api.scrollTo( + instanceIdArg, + xArg, + yArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.scrollBy", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const xArg: number = args[1]; + const yArg: number = args[2]; + try { + api.scrollBy( + instanceIdArg, + xArg, + yArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollX", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: number = api.getScrollX(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollY", WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: number = api.getScrollY(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.getScrollPosition", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + const output: WebViewPoint = api.getScrollPosition(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebContentsDebuggingEnabled", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const enabledArg: boolean = args[0]; + try { + api.setWebContentsDebuggingEnabled(enabledArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebViewClient", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const webViewClientInstanceIdArg: number = args[1]; + try { + api.setWebViewClient( + instanceIdArg, + webViewClientInstanceIdArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.addJavaScriptChannel", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const javaScriptChannelInstanceIdArg: number = args[1]; + try { + api.addJavaScriptChannel( + instanceIdArg, + javaScriptChannelInstanceIdArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.removeJavaScriptChannel", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const javaScriptChannelInstanceIdArg: number = args[1]; + try { + api.removeJavaScriptChannel( + instanceIdArg, + javaScriptChannelInstanceIdArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setDownloadListener", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const listenerInstanceIdArg: number = args[1]; + try { + api.setDownloadListener( + instanceIdArg, + listenerInstanceIdArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewHostApi.setWebChromeClient", + WebViewHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const clientInstanceIdArg: number = args[1]; + try { + api.setWebChromeClient( + instanceIdArg, + clientInstanceIdArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + } +} + +export interface Reply { + /** + * Handles the specified message reply. + * + * @param reply the reply, possibly null. + */ + reply: (reply: T | null) => void; +} + +export class WebViewFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(argBinaryMessenger: BinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(identifierArg: number, callback: Reply): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewFlutterApi.create", + WebViewFlutterApi.getCodec() + ); + channel.send( + [identifierArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onScrollChanged( + webViewInstanceIdArg: number, + leftArg: number, + topArg: number, + oldLeftArg: number, + oldTopArg: number, + callback: Reply, + ) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_android.WebViewFlutterApi.onScrollChanged", + WebViewFlutterApi.getCodec()); + channel.send( + [webViewInstanceIdArg, leftArg, topArg, oldLeftArg, oldTopArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export enum ConsoleMessageLevel { + DEBUG, + ERROR, + LOG, + TIP, + WARNING, + UNKNOWN +} + +interface ConsoleMessageBuilder { + lineNumber: number; + message: string; + level: ConsoleMessageLevel; + sourceId: string; + setLineNumber: (setterArg: number) => ConsoleMessageBuilder; + setMessage: (setterArg: string) => ConsoleMessageBuilder; + setLevel: (setterArg: ConsoleMessageLevel) => ConsoleMessageBuilder; + setSourceId: (setterArg: string) => ConsoleMessageBuilder; + build: () => ConsoleMessage; +} + +export class ConsoleMessage { + private lineNumber: number = 0; + + getLineNumber(): number { + return this.lineNumber; + } + + setLineNumber(setterArg: number): void { + if (setterArg == null) { + throw new Error("Nonnull field \"lineNumber\" is null.") + } + this.lineNumber = setterArg; + } + + private message: string = ""; + + getMessage(): string { + return this.message; + } + + setMessage(setterArg: string): void { + if (setterArg == null) { + throw new Error("Nonnull field \"message\" is null.") + } + this.message = setterArg; + } + + private level: ConsoleMessageLevel = 0; + + getLevel(): ConsoleMessageLevel { + return this.level; + } + + setLevel(setterArg: ConsoleMessageLevel): void { + if (setterArg == null) { + throw new Error("Nonnull field \"level\" is null.") + } + this.level = setterArg; + } + + private sourceId: string = ""; + + getSourceId(): string { + return this.sourceId; + } + + setSourceId(setterArg: string): void { + if (setterArg == null) { + throw new Error("Nonnull field \"sourceId\" is null.") + } + this.sourceId = setterArg; + } + + private constructor() { + } + + public static Builder(): ConsoleMessageBuilder { + const builder: ConsoleMessageBuilder = { + lineNumber: 0, + message: "", + level: ConsoleMessageLevel.DEBUG, + sourceId: "", + setLineNumber(setterArg: number): ConsoleMessageBuilder { + builder.lineNumber = setterArg; + return builder; + }, + setMessage(setterArg: string): ConsoleMessageBuilder { + builder.message = setterArg; + return builder; + }, + setLevel(setterArg: ConsoleMessageLevel): ConsoleMessageBuilder { + builder.level = setterArg; + return builder; + }, + setSourceId(setterArg: string): ConsoleMessageBuilder { + builder.sourceId = setterArg; + return builder; + }, + build(): ConsoleMessage { + const pigeonReturn = new ConsoleMessage(); + pigeonReturn.setLineNumber(builder.lineNumber); + pigeonReturn.setMessage(builder.message); + pigeonReturn.setLevel(builder.level); + pigeonReturn.setSourceId(builder.sourceId); + return pigeonReturn; + } + }; + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.lineNumber); + toArrayResult.push(this.message); + toArrayResult.push(this.level); + toArrayResult.push(this.sourceId); + return toArrayResult; + } + + static fromArray(array: Array): ConsoleMessage { + const pigeonResult = new ConsoleMessage(); + const lineNumber: number = array[0]; + pigeonResult.setLineNumber(lineNumber); + const message: string = array[1]; + pigeonResult.setMessage(message); + const level: ConsoleMessageLevel = array[2]; + pigeonResult.setLevel(level); + const sourceId: string = array[3]; + pigeonResult.setSourceId(sourceId); + return pigeonResult; + } +} + +class WebChromeClientFlutterApiCodec extends StandardMessageCodec { + public static INSTANCE: WebChromeClientFlutterApiCodec = new WebChromeClientFlutterApiCodec(); + + private constructor() { + super(); + } + + readValueOfType(type: number, buffer: ByteBuffer): ESObject { + switch (type) { + case 128: + return ConsoleMessage.fromArray(this.readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + writeValue(stream: ByteBuffer, value: ESObject): ESObject { + if (value instanceof ConsoleMessage) { + stream.writeInt8(128); + super.writeValue(stream, value.toArray()); + } else { + super.writeValue(stream, value); + } + } +} + +export abstract class WebChromeClientFlutterApi { + protected binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return WebChromeClientFlutterApiCodec.INSTANCE; + } + + onProgressChanged( + instanceIdArg: number, + webViewInstanceIdArg: number, + progressArg: number, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onProgressChanged", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, webViewInstanceIdArg, progressArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onShowFileChooser( + instanceIdArg: number, + webViewInstanceIdArg: number, + paramsInstanceIdArg: number, + callback: Reply> + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowFileChooser", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, webViewInstanceIdArg, paramsInstanceIdArg], + (channelReply: ESObject) => { + const output: Array = channelReply; + callback.reply(output); + } + ); + } + + onPermissionRequest( + instanceIdArg: number, + requestInstanceIdArg: number, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onPermissionRequest", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, requestInstanceIdArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onShowCustomView( + instanceIdArg: number, + viewIdentifierArg: number, + callbackIdentifierArg: number, + callback: Reply + ) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onShowCustomView", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, viewIdentifierArg, callbackIdentifierArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onHideCustomView( + instanceIdArg: number, + callback: Reply + ) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onHideCustomView", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onGeolocationPermissionsShowPrompt( + instanceIdArg: number, + paramsInstanceIdArg: number, + originArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsShowPrompt", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, paramsInstanceIdArg, originArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onGeolocationPermissionsHidePrompt( + instanceIdArg: number, callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onGeolocationPermissionsHidePrompt", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onConsoleMessage( + instanceIdArg: number, + messageArg: ConsoleMessage, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onConsoleMessage", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, messageArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onJsAlert( + instanceIdArg: number, + urlArg: string, + messageArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsAlert", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, urlArg, messageArg], + (channelReply: ESObject) => { + callback.reply(null); + } + ); + } + + onJsConfirm( + instanceIdArg: number, + urlArg: string, + messageArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsConfirm", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, urlArg, messageArg], + (channelReply: ESObject) => { + let output: boolean = channelReply as boolean; + callback.reply(output); + } + ); + } + + onJsPrompt( + instanceIdArg: number, + urlArg: string, + messageArg: string, + defaultValueArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientFlutterApi.onJsPrompt", + WebChromeClientFlutterApi.getCodec() + ) + channel.send( + [instanceIdArg, urlArg, messageArg, defaultValueArg], + (channelReply: ESObject) => { + let output: string = channelReply as string; + callback.reply(output); + } + ); + } +} + +export abstract class WebChromeClientHostApi { + abstract create(instanceId: number): void; + + abstract setSynchronousReturnValueForOnShowFileChooser(instanceId: number, value: boolean): void; + + abstract setSynchronousReturnValueForOnConsoleMessage(instanceId: number, value: boolean): void; + + abstract setSynchronousReturnValueForOnJsAlert(instanceId: number, value: boolean): void; + + abstract setSynchronousReturnValueForOnJsConfirm(instanceId: number, value: boolean): void; + + abstract setSynchronousReturnValueForOnJsPrompt(instanceId: number, value: boolean): void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: WebChromeClientHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.create", + WebChromeClientHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.create(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnShowFileChooser", + WebChromeClientHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForOnShowFileChooser( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnConsoleMessage", + WebChromeClientHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForOnConsoleMessage( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsAlert", + WebChromeClientHostApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForOnJsAlert( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + }); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsConfirm", + WebChromeClientHostApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForOnJsConfirm( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + }); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebChromeClientHostApi.setSynchronousReturnValueForOnJsPrompt", + WebChromeClientHostApi.getCodec()); + if (api != null) { + channel.setMessageHandler({ + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForOnJsPrompt( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + }); + } else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class WebViewClientHostApi { + abstract create(instanceId: number): void; + + abstract setSynchronousReturnValueForShouldOverrideUrlLoading(instanceId: number, value: boolean): void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: WebViewClientHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientHostApi.create", + WebViewClientHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.create(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientHostApi.setSynchronousReturnValueForShouldOverrideUrlLoading", + WebViewClientHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const valueArg: boolean = args[1]; + try { + api.setSynchronousReturnValueForShouldOverrideUrlLoading( + instanceIdArg, valueArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + } +} + +interface WebResourceErrorDataBuilder { + errorCode: number; + setErrorCode: (setterArg: number) => WebResourceErrorDataBuilder; + description: string; + setDescription: (setterArg: string) => WebResourceErrorDataBuilder; + build: () => WebResourceErrorData; +} + +export class WebResourceErrorData { + private errorCode: number = 0; + + private constructor() { + } + + getErrorCode(): number { + return this.errorCode; + } + + setErrorCode(setterArg: number) { + if (setterArg == null) { + throw new Error("Nonnull field \"errorCode\" is null.") + } + this.errorCode = setterArg; + } + + private description: string = ""; + + getDescription(): string { + return this.description; + } + + setDescription(setterArg: string) { + if (setterArg == null) { + throw new Error("Nonnull field \"description\" is null.") + } + this.description = setterArg; + } + + public static Builder(): WebResourceErrorDataBuilder { + const builder: WebResourceErrorDataBuilder = { + errorCode: 0, + setErrorCode(setterArg: number): WebResourceErrorDataBuilder { + builder.errorCode = setterArg; + return builder; + }, + description: "", + setDescription(setterArg: string): WebResourceErrorDataBuilder { + builder.description = setterArg; + return builder; + }, + build(): WebResourceErrorData { + const pigeonReturn = new WebResourceErrorData(); + pigeonReturn.setErrorCode(builder.errorCode); + pigeonReturn.setDescription(builder.description); + return pigeonReturn; + } + } + + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.errorCode); + toArrayResult.push(this.description); + return toArrayResult; + } + + static fromArray(list: Array): WebResourceErrorData { + const pigeonResult = new WebResourceErrorData(); + const errorCode: number = list[0]; + pigeonResult.setErrorCode(errorCode); + const description: string = list[1]; + pigeonResult.setDescription(description); + return pigeonResult; + } +} + +interface WebResourceRequestDataBuilder { + url: string; + setUrl: (setterArg: string) => WebResourceRequestDataBuilder; + isForMainFrame: boolean; + setIsForMainFrame: (setterArg: boolean) => WebResourceRequestDataBuilder; + isRedirect: boolean; + setIsRedirect: (setterArg: boolean) => WebResourceRequestDataBuilder; + hasGesture: boolean; + setHasGesture: (setterArg: boolean) => WebResourceRequestDataBuilder; + method: string; + setMethod: (setterArg: string) => WebResourceRequestDataBuilder; + requestHeaders: Map; + setRequestHeaders: (setterArg: Map) => WebResourceRequestDataBuilder; + build: () => WebResourceRequestData; +} + +export class WebResourceRequestData { + private url: string = ""; + + private constructor() { + } + + getUrl(): string { + return this.url; + } + + setUrl(setterArg: string) { + if (setterArg == null) { + throw new Error("Nonnull field \"url\" is null.") + } + this.url = setterArg; + } + + private isForMainFrame: boolean = false; + + getIsForMainFrame(): boolean { + return this.isForMainFrame; + } + + setIsForMainFrame(setterArg: boolean) { + if (setterArg == null) { + throw new Error("Nonnull field \"isForMainFrame\" is null.") + } + this.isForMainFrame = setterArg; + } + + private isRedirect: boolean = false; + + getIsRedirect(): boolean { + return this.isRedirect; + } + + setIsRedirect(setterArg: boolean) { + if (setterArg == null) { + throw new Error("Nonnull field \"isRedirect\" is null.") + } + this.isRedirect = setterArg; + } + + private hasGesture: boolean = false; + + getHasGesture(): boolean { + return this.hasGesture; + } + + setHasGesture(setterArg: boolean) { + if (setterArg == null) { + throw new Error("Nonnull field \"hasGesture\" is null.") + } + this.hasGesture = setterArg; + } + + private method: string = ""; + + getMethod(): string { + return this.method; + } + + setMethod(setterArg: string) { + if (setterArg == null) { + throw new Error("Nonnull field \"method\" is null.") + } + this.method = setterArg; + } + + private requestHeaders: Map = new Map(); + + getRequestHeaders(): Map { + return this.requestHeaders; + } + + setRequestHeaders(setterArg: Map) { + if (setterArg == null) { + throw new Error("Nonnull field \"requestHeaders\" is null.") + } + this.requestHeaders = setterArg; + } + + public static Builder(): WebResourceRequestDataBuilder { + const builder: WebResourceRequestDataBuilder = { + url: "", + setUrl(setterArg: string): WebResourceRequestDataBuilder { + builder.url = setterArg; + return builder; + }, + isForMainFrame: false, + setIsForMainFrame(setterArg: boolean): WebResourceRequestDataBuilder { + builder.isForMainFrame = setterArg; + return builder; + }, + isRedirect: false, + setIsRedirect(setterArg: boolean): WebResourceRequestDataBuilder { + builder.isRedirect = setterArg; + return builder; + }, + hasGesture: false, + setHasGesture(setterArg: boolean): WebResourceRequestDataBuilder { + builder.hasGesture = setterArg; + return builder; + }, + method: "", + setMethod(setterArg: string): WebResourceRequestDataBuilder { + builder.method = setterArg; + return builder; + }, + requestHeaders: new Map(), + setRequestHeaders(setterArg: Map): WebResourceRequestDataBuilder { + builder.requestHeaders = setterArg; + return builder; + }, + build(): WebResourceRequestData { + const pigeonReturn = new WebResourceRequestData(); + pigeonReturn.setUrl(builder.url); + pigeonReturn.setIsForMainFrame(builder.isForMainFrame); + pigeonReturn.setIsRedirect(builder.isRedirect); + pigeonReturn.setHasGesture(builder.hasGesture); + pigeonReturn.setMethod(builder.method); + pigeonReturn.setRequestHeaders(builder.requestHeaders); + return pigeonReturn; + } + } + + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.url); + toArrayResult.push(this.isForMainFrame); + toArrayResult.push(this.isRedirect); + toArrayResult.push(this.hasGesture); + toArrayResult.push(this.method); + toArrayResult.push(this.requestHeaders); + return toArrayResult; + } + + static fromArray(list: Array): WebResourceRequestData { + const pigeonResult = new WebResourceRequestData(); + const url: string = list[0]; + pigeonResult.setUrl(url); + const isForMainFrame: boolean = list[1]; + pigeonResult.setIsForMainFrame(isForMainFrame); + const isRedirect: boolean = list[2]; + pigeonResult.setIsRedirect(isRedirect); + const hasGesture: boolean = list[3]; + pigeonResult.setHasGesture(hasGesture); + const method: string = list[4]; + pigeonResult.setMethod(method); + const requestHeaders: Map = list[5]; + pigeonResult.setRequestHeaders(requestHeaders); + return pigeonResult; + } +} + +class WebViewClientFlutterApiCodec extends StandardMessageCodec { + public static INSTANCE: WebViewClientFlutterApiCodec = new WebViewClientFlutterApiCodec(); + + private constructor() { + super(); + } + + readValueOfType(type: number, buffer: ByteBuffer): ESObject { + switch (type) { + case 128: + return WebResourceErrorData.fromArray(this.readValue(buffer)); + case 129: + return WebResourceRequestData.fromArray(this.readValue(buffer)); + case 130: + return WebResourceResponseData.fromArray(this.readValue(buffer)); + default: + return super.readValueOfType(type, buffer); + } + } + + writeValue(stream: ByteBuffer, value: ESObject): ESObject { + if (value instanceof WebResourceErrorData) { + stream.writeInt8(128); + super.writeValue(stream, value.toArray()); + } else if (value instanceof WebResourceRequestData) { + stream.writeInt8(129); + super.writeValue(stream, value.toArray()); + } else if (value instanceof WebResourceResponseData) { + stream.writeInt8(130); + super.writeValue(stream, value.toArray()); + } else { + super.writeValue(stream, value); + } + } +} + +export abstract class WebViewClientFlutterApi { + protected binaryMessenger: BinaryMessenger; + + constructor(argBinaryMessenger: BinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + static getCodec(): MessageCodec { + return WebViewClientFlutterApiCodec.INSTANCE; + } + + onPageStarted( + instanceIdArg: number, + webViewInstanceIdArg: number, + urlArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onPageStarted", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, urlArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onPageFinished( + instanceIdArg: number, + webViewInstanceIdArg: number, + urlArg: string, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onPageFinished", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, urlArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onReceivedHttpError( + instanceIdArg: number, + webViewInstanceIdArg: number, + requestArg: WebResourceRequestData, + responseArg: WebResourceResponseData, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpError", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, requestArg, responseArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onReceivedRequestError( + instanceIdArg: number, + webViewInstanceIdArg: number, + requestArg: WebResourceRequestData, + errorArg: WebResourceErrorData, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedRequestError", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, requestArg, errorArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + requestLoading( + instanceIdArg: number, + webViewInstanceIdArg: number, + requestArg: WebResourceRequestData, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.requestLoading", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, requestArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + doUpdateVisitedHistory( + instanceIdArg: number, + webViewInstanceIdArg: number, + urlArg: string, + isReloadArg: boolean, + callback: Reply + ): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.doUpdateVisitedHistory", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, urlArg, isReloadArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + + onReceivedHttpAuthRequest( + instanceIdArg: number, + webViewInstanceIdArg: number, + httpAuthHandlerInstanceIdArg: number, + hostArg: string, + realmArg: string, + callback: Reply + ) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebViewClientFlutterApi.onReceivedHttpAuthRequest", + WebViewClientFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, webViewInstanceIdArg, httpAuthHandlerInstanceIdArg, hostArg, realmArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export abstract class WebSettingsHostApi { + abstract create(instanceId: number, webViewInstanceId: number): void; + + abstract setDomStorageEnabled(instanceId: number, flag: boolean): void; + + abstract setJavaScriptCanOpenWindowsAutomatically(instanceId: number, flag: boolean): void; + + abstract setSupportMultipleWindows(instanceId: number, support: boolean): void; + + abstract setBackgroundColor(instanceId: number, color: number); + + abstract setJavaScriptEnabled(instanceId: number, flag: boolean): void; + + abstract setUserAgentString(instanceId: number, userAgentString: string): void; + + abstract setMediaPlaybackRequiresUserGesture(instanceId: number, require: boolean): void; + + abstract setSupportZoom(instanceId: number, support: boolean): void; + + abstract setLoadWithOverviewMode(instanceId: number, overview: boolean): void; + + abstract setUseWideViewPort(instanceId: number, use: boolean): void; + + abstract setDisplayZoomControls(instanceId: number, enabled: boolean): void; + + abstract setBuiltInZoomControls(instanceId: number, enabled: boolean): void; + + abstract setAllowFileAccess(instanceId: number, enabled: boolean): void; + + abstract setTextZoom(instanceId: number, textZoom: number): void; + + abstract getUserAgentString(instanceId: number): Promise; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: WebSettingsHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.create", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const webViewInstanceIdArg: number = args[1]; + try { + api.create(instanceIdArg, webViewInstanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setDomStorageEnabled", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const flagArg: boolean = args[1]; + try { + api.setDomStorageEnabled( + instanceIdArg, flagArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const flagArg: boolean = args[1]; + try { + api.setJavaScriptCanOpenWindowsAutomatically( + instanceIdArg, flagArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setSupportMultipleWindows", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const supportArg: boolean = args[1]; + try { + api.setSupportMultipleWindows( + instanceIdArg, supportArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setBackgroundColor", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const colorArg: number = args[1]; + try { + api.setBackgroundColor( + instanceIdArg, + colorArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setJavaScriptEnabled", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const flagArg: boolean = args[1]; + try { + api.setJavaScriptEnabled( + instanceIdArg, flagArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setUserAgentString", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const userAgentStringArg: string = args[1]; + try { + api.setUserAgentString( + instanceIdArg, userAgentStringArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const requireArg: boolean = args[1]; + try { + api.setMediaPlaybackRequiresUserGesture( + instanceIdArg, requireArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setSupportZoom", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const supportArg: boolean = args[1]; + try { + api.setSupportZoom( + instanceIdArg, supportArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setLoadWithOverviewMode", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const overviewArg: boolean = args[1]; + try { + api.setLoadWithOverviewMode( + instanceIdArg, overviewArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setUseWideViewPort", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const useArg: boolean = args[1]; + try { + api.setUseWideViewPort( + instanceIdArg, useArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setDisplayZoomControls", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const enabledArg: boolean = args[1]; + try { + api.setDisplayZoomControls( + instanceIdArg, enabledArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setBuiltInZoomControls", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const enabledArg: boolean = args[1]; + try { + api.setBuiltInZoomControls( + instanceIdArg, enabledArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setAllowFileAccess", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const enabledArg: boolean = args[1]; + try { + api.setAllowFileAccess( + instanceIdArg, enabledArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.setTextZoom", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const textZoomArg: number = args[1]; + try { + api.setTextZoom( + instanceIdArg, textZoomArg + ); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebSettingsHostApi.getUserAgentString", + WebSettingsHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: async (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + let output = await api.getUserAgentString(instanceIdArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class WebStorageHostApi { + abstract create(instanceId: number): void; + + abstract deleteAllData(instanceId: number): void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: WebStorageHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.WebStorageHostApi.create", + WebStorageHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.create(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.WebStorageHostApi.deleteAllData", + WebStorageHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.deleteAllData(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ); + } else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class GeolocationPermissionsCallbackHostApi { + abstract invoke(instanceId: number, origin: string, allow: Boolean, retain: Boolean); + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: GeolocationPermissionsCallbackHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.GeolocationPermissionsCallbackHostApi.invoke", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const originArg: string = args[1]; + const allowArg: boolean = args[2]; + const retainArg: boolean = args[3]; + try { + api.invoke(instanceIdArg, originArg, allowArg, retainArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + } +} + +export class GeolocationPermissionsCallbackFlutterApi { + private binaryMessenger: BinaryMessenger; + + // + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(instanceIdArg: number, callback: Reply): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.GeolocationPermissionsCallbackFlutterApi.create", + GeolocationPermissionsCallbackFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg], + (channelReply: ESObject) => callback.reply(null) + ); + + } +} + +export abstract class HttpAuthHandlerHostApi { + abstract useHttpAuthUsernamePassword(instanceId: number): boolean; + + abstract cancel(instanceId: number): void; + + abstract proceed(instanceId: number, username: string, password: string): void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: HttpAuthHandlerHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.useHttpAuthUsernamePassword", + HttpAuthHandlerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdentifierArg: number = args[0]; + try { + let output: boolean = api.useHttpAuthUsernamePassword(instanceIdentifierArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.cancel", + HttpAuthHandlerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdentifierArg: number = args[0]; + try { + api.cancel(instanceIdentifierArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerHostApi.proceed", + HttpAuthHandlerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdentifierArg: number = args[0] as number; + const usernameArg: string = args[1] as string; + const passwordArg: string = args[2] as string; + try { + api.proceed(instanceIdentifierArg, usernameArg, passwordArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } else { + channel.setMessageHandler(null); + } + } + } +} + +export class HttpAuthHandlerFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(instanceIdArg: number, callback: Reply): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.HttpAuthHandlerFlutterApi.create", + HttpAuthHandlerHostApi.getCodec() + ); + channel.send( + [instanceIdArg], + (channelReply: ESObject) => callback.reply(null) + ); + } + +} + +export abstract class CookieManagerHostApi { + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + abstract attachInstance(instanceIdentifier: number); + + abstract setCookie(identifier: number, url: string, value: string); + + abstract removeAllCookies(identifier: number, result: Result); + + abstract setAcceptThirdPartyCookies(identifier: number, accept: boolean); + + static setup(binaryMessenger: BinaryMessenger, api: CookieManagerHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.attachInstance", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdentifierArg: number = args[0]; + try { + api.attachInstance(instanceIdentifierArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.setCookie", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const identifierArg: number = args[0]; + const urlArg: string = args[1]; + const valueArg: string = args[2]; + try { + api.setCookie(identifierArg, urlArg, valueArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.removeAllCookies", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const identifierArg: number = args[0]; + const resultCallback: Result = new ResultBuilder( + (result: Boolean) => { + wrapped.insert(result, 0); + reply.reply(wrapped.convertToArray()); + }, (err) => { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + reply.reply(wrappedError.convertToArray()); + } + ) + api.removeAllCookies(identifierArg, resultCallback) + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CookieManagerHostApi.setAcceptThirdPartyCookies", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const identifierArg: number = args[0]; + const webViewIdentifierArg: number = args[1]; + const acceptArg: boolean = args[2]; + try { + api.setAcceptThirdPartyCookies(identifierArg, acceptArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + } +} + +class MessageHandlerBuilder { + onMessage: (message: ESObject, reply: Reply) => void + + constructor(onMessage: (message: ESObject, reply: Reply) => void) { + this.onMessage = onMessage + } +} + +export class PermissionRequestFlutterApi { + private binaryMessenger: BinaryMessenger; + + // + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(instanceIdArg: number, resourcesArg: string[], callback: Reply): void { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestFlutterApi.create", + PermissionRequestFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, resourcesArg], + (channelReply: ESObject) => callback.reply(null) + ); + + } +} + +export abstract class CustomViewCallbackHostApi { + abstract onCustomViewHidden(identifier: number): void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: CustomViewCallbackHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackHostApi.onCustomViewHidden", + CustomViewCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const resourcesArg: string[] = args[1]; + try { + api.onCustomViewHidden(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + } +} + +export interface HttpAuthHandler { + cancel(): void; + + proceed(username: string, password: string): void; + + useHttpAuthUsernamePassword(): boolean; +} + +export interface CustomViewCallback { + onCustomViewHidden(): void; +} + +export class CustomViewCallbackFlutterApi { + binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(identifierArg: number, callback: Reply) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.CustomViewCallbackFlutterApi.create", + CustomViewCallbackFlutterApi.getCodec() + ); + channel.send( + [identifierArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export class ViewFlutterApi { + binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + create(identifierArg: number, callback: Reply) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.ViewFlutterApi.create", + ViewFlutterApi.getCodec() + ); + channel.send( + [identifierArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export abstract class PermissionRequestHostApi { + abstract grant(instanceId: number, resources: string[]); + + abstract deny(instanceId: number); + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: PermissionRequestHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestHostApi.grant", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const resourcesArg: string[] = args[1]; + try { + api.grant(instanceIdArg, resourcesArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.PermissionRequestHostApi.deny", + GeolocationPermissionsCallbackHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.deny(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + } +} + +export class FileChooserParamsFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + tCreate( + instanceIdArg: number, + isCaptureEnabledArg: boolean, + acceptTypesArg: string[], + modeArg: FileChooserMode, + //filenameHintArg:string, + callback: Reply + ) { + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.FileChooserParamsFlutterApi.create", + FileChooserParamsFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, isCaptureEnabledArg, acceptTypesArg, modeArg, + //filenameHintArg + ], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export class JavaScriptChannelFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + postMessageT( + instanceIdArg: number, messageArg: string, callback: Reply + ) { + + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.JavaScriptChannelFlutterApi.postMessage", + JavaScriptChannelFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, messageArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export class DownloadListenerFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + onDownloadStartT( + instanceIdArg: number, urlArg: string, userAgentArg: string, contentDispositionArg: string, mimetypeArg: string, + contentLengthArg: number, callback: Reply + ) { + + const channel: BasicMessageChannel = new BasicMessageChannel( + this.binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.DownloadListenerFlutterApi.onDownloadStart", + DownloadListenerFlutterApi.getCodec() + ); + channel.send( + [instanceIdArg, urlArg, userAgentArg, contentDispositionArg, mimetypeArg, contentLengthArg], + (channelReply: ESObject) => callback.reply(null) + ); + } +} + +export abstract class DownloadListenerHostApi { + abstract create(instanceId: number); + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: DownloadListenerHostApi) { + { + const channel: BasicMessageChannel = new BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_ohos.DownloadListenerHostApi.create", + DownloadListenerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + new MessageHandlerBuilder((message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + try { + api.create(instanceIdArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + }) + ) + } + else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class FlutterAssetManagerHostApi { + abstract list(path: string); + + abstract getAssetFilePathByName(name: string); + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: FlutterAssetManagerHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.FlutterAssetManagerHostApi.list", + FlutterAssetManagerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: async (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const pathArg: string = args[0]; + try { + let output: ESObject = await api.list(pathArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.FlutterAssetManagerHostApi.getAssetFilePathByName", + FlutterAssetManagerHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const nameArg: string = args[0]; + try { + let output: ESObject = api.getAssetFilePathByName(nameArg); + wrapped.insert(output, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class JavaScriptChannelHostApi { + abstract create(instanceId: number, channelName: string); + + static getCodec(): MessageCodec { + return WebChromeClientFlutterApiCodec.INSTANCE; + } + + static setup(binaryMessenger: BinaryMessenger, api: JavaScriptChannelHostApi) { + { + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.JavaScriptChannelHostApi.create", + JavaScriptChannelHostApi.getCodec() + ); + if (api != null) { + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const instanceIdArg: number = args[0]; + const channelNameArg: string = args[1]; + try { + api.create(instanceIdArg, channelNameArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + } else { + channel.setMessageHandler(null); + } + } + } +} + +export abstract class OhosObjectHostApi { + abstract dispose(identifier: number); + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + static setup(binaryMessenger: BinaryMessenger, api: OhosObjectHostApi) { + { + + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.OhosObjectHostApi.dispose", + OhosObjectHostApi.getCodec() + ); + + if (api != null) { + + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + const args: Array = message; + const identifierArg: number = args[0]; + try { + api.dispose(identifierArg); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + + } + else { + channel.setMessageHandler(null); + } + } + } +} + +export class OhosObjectFlutterApi { + private binaryMessenger: BinaryMessenger; + + constructor(binaryMessenger: BinaryMessenger) { + this.binaryMessenger = binaryMessenger; + } + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + dispose(identifierArg: number, callback: Reply) { + + const channel: BasicMessageChannel = + new BasicMessageChannel( + this.binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.OhosObjectFlutterApi.dispose", + OhosObjectFlutterApi.getCodec() + ); + + channel.send( + [identifierArg], + (channelReply: ESObject) => callback.reply(null) + ); + + } +} + +export interface InstanceManagerApi { + clear: () => void; +} + +export abstract class InstanceManagerHostApi { + abstract clear: () => void; + + static getCodec(): MessageCodec { + return new StandardMessageCodec(); + } + + /** + * Sets up an instance of `InstanceManagerHostApi` to handle messages through the + * `binaryMessenger`. + */ + + static setup(binaryMessenger: BinaryMessenger, api: InstanceManagerApi) { + { + + const channel: BasicMessageChannel = + new BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.webview_flutter_ohos.InstanceManagerHostApi.clear", OhosObjectHostApi.getCodec() + ); + + if (api != null) { + + channel.setMessageHandler( + { + onMessage: (message: ESObject, reply: Reply) => { + let wrapped: ArrayList = new ArrayList(); + + try { + api.clear(); + wrapped.insert(null, 0); + } catch (err) { + const wrappedError: ArrayList = GeneratedOhosWebView.wrapError(err); + wrapped = wrappedError; + } + reply.reply(wrapped.convertToArray()); + } + } + ) + + } + else { + channel.setMessageHandler(null); + } + } + } +} + +interface WebResourceResponseDataBuilder { + statusCode: number; + setStatusCode: (setterArg: number) => WebResourceResponseDataBuilder; + build: () => WebResourceResponseData; +} + +export class WebResourceResponseData { + private statusCode: number | null = 0; + + private constructor() { + } + + getStatusCode(): number | null { + return this.statusCode; + } + + setStatusCode(setterArg: number | null) { + if (setterArg == null) { + throw new Error("Nonnull field \"statusCode\" is null.") + } + this.statusCode = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + WebResourceResponseData() { + } + + public static Builder(): WebResourceResponseDataBuilder { + const builder: WebResourceResponseDataBuilder = { + statusCode: 0, + setStatusCode(setterArg: number): WebResourceResponseDataBuilder { + builder.statusCode = setterArg; + return builder; + }, + build(): WebResourceResponseData { + const pigeonReturn = new WebResourceResponseData(); + pigeonReturn.setStatusCode(builder.statusCode); + return pigeonReturn; + } + } + return builder; + } + + toArray(): Array { + const toArrayResult: Array = new Array(); + toArrayResult.push(this.statusCode); + return toArrayResult; + } + + static fromArray(list: Array): WebResourceResponseData { + const pigeonResult = new WebResourceResponseData(); + const statusCode: number | null = list[0]; + //pigeonResult.setStatusCode((statusCode == null) ? null : ((statusCode instanceof Integer) ? (Integer) statusCode : (number) statusCode));. + pigeonResult.setStatusCode((statusCode == null) ? null : statusCode); + return pigeonResult; + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..f3abd0a4e52c950a96fe0cf71e4ab909d3e099b0 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackFlutterApiImpl.ets @@ -0,0 +1,38 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { InstanceManager } from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { Reply, GeolocationPermissionsCallbackFlutterApi } from "./GeneratedOhosWebView" + +export class GeolocationPermissionsCallbackFlutterApiImpl { + private binaryMessenger: BinaryMessenger; + + private instanceManager: InstanceManager; + + private api: GeolocationPermissionsCallbackFlutterApi; + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new GeolocationPermissionsCallbackFlutterApi(binaryMessenger); + } + + create(instance: JsGeolocation, callback: Reply): void { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), callback); + } + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..0df80b39e82594f4ad6152358d0f9fc6bdc3af9d --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/GeolocationPermissionsCallbackHostApiImpl.ets @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import {InstanceManager} from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import {GeolocationPermissionsCallbackHostApi} from "./GeneratedOhosWebView" +export class GeolocationPermissionsCallbackHostApiImpl extends GeolocationPermissionsCallbackHostApi { + private binaryMessenger:BinaryMessenger ; + + private instanceManager:InstanceManager; + + constructor(binaryMessenger:BinaryMessenger, instanceManager:InstanceManager) { + super() + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + invoke(instanceId:number,origin:string,allow:boolean,retain:boolean):void { + this.getGeolocationPermissionsCallbackInstance(instanceId).invoke(origin, allow, retain); + } + + private getGeolocationPermissionsCallbackInstance(identifier:number):JsGeolocation{ + return this.instanceManager.getInstance(identifier); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..13b7200157745d6938180211cce25998e8ebb887 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerFlutterApiImpl.ets @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { HttpAuthHandlerFlutterApi, Reply } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager' + +/** + * Flutter API implementation for {@link HttpAuthHandler}. + * + *

This class may handle adding native instances that are attached to a Dart instance or passing + * arguments of callbacks methods to a Dart instance. + */ +export class HttpAuthHandlerFlutterApiImpl { + // To ease adding additional methods, this value is added prematurely. + binaryMessenger: BinaryMessenger; + + instanceManager: InstanceManager; + + api: HttpAuthHandlerFlutterApi; + + /** + * Constructs a {@link HttpAuthHandlerFlutterApiImpl}. + * + * @param binaryMessenger used to communicate with Dart over asynchronous messages + * @param instanceManager maintains instances stored to communicate with attached Dart objects + */ + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new HttpAuthHandlerFlutterApi(binaryMessenger); + } + + /** + * Stores the `HttpAuthHandler` instance and notifies Dart to create and store a new + * `HttpAuthHandler` instance that is attached to this one. If `instance` has already been added, + * this method does nothing. + */ + create(instance: ESObject, callback: Reply) { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), callback); + } + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..7435db6cf24d52302a661cbd5ef6a33788ae8f2b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/HttpAuthHandlerHostApiImpl.ets @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { HttpAuthHandlerHostApi, HttpAuthHandler } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager' + +/** + * Host api implementation for {@link HttpAuthHandler}. + * + *

Handles creating {@link HttpAuthHandler}s that intercommunicate with a paired Dart object. + */ +export class HttpAuthHandlerHostApiImpl extends HttpAuthHandlerHostApi { + // To ease adding additional methods, this value is added prematurely. + binaryMessenger: BinaryMessenger; + + instanceManager: InstanceManager; + + /** + * Constructs a {@link HttpAuthHandlerHostApiImpl}. + * + * @param binaryMessenger used to communicate with Dart over asynchronous messages + * @param instanceManager maintains instances stored to communicate with attached Dart objects + */ + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(); + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + useHttpAuthUsernamePassword(instanceId: number): boolean { + return this.getHttpAuthHandlerInstance(instanceId).useHttpAuthUsernamePassword(); + } + + cancel(instanceId: number) { + this.getHttpAuthHandlerInstance(instanceId).cancel(); + } + + proceed(instanceId: number, username: string, password: string) { + this.getHttpAuthHandlerInstance(instanceId).proceed(username, password); + } + + getHttpAuthHandlerInstance(instanceId: number): HttpAuthHandler { + return this.instanceManager.getInstance(instanceId); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/InstanceManager.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/InstanceManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..32e6c16b7e32d0510b821911f720570112c2ef82 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/InstanceManager.ets @@ -0,0 +1,142 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; + +export class InstanceManager { + private MIN_HOST_CREATED_IDENTIFIER = 65536; + + private CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000; + + private TAG = "InstanceManager"; + + private finalizationListener: FinalizationListener; + + private identifiers: Map = new Map(); + + private Instances: Map = new Map(); + + private firstIdentifier: number = 0; + + private nextIdentifier: number = this.MIN_HOST_CREATED_IDENTIFIER; + + private releaseTimer: ESObject = null; + + private hasFinalizationListenerStopped: boolean = false; + + public create(finalizationListener: FinalizationListener): InstanceManager { + return new InstanceManager(finalizationListener); + } + + public fHasFinalizationListenerStopped(): boolean { + return this.hasFinalizationListenerStopped; + } + + constructor(finalizationListener: FinalizationListener) { + this.finalizationListener = finalizationListener; + this.releaseTimer = setTimeout(() => { + this.releaseAllFinalizedInstances() + }, this.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL) + } + + public remove(identifier: number): ESObject | null { + this.logWarningIfFinalizationListenerHasStopped(); + + return this.Instances.delete(identifier) as ESObject | null; + } + + getInstance(identifier: number): ESObject { + this.logWarningIfFinalizationListenerHasStopped(); + return this.Instances.get(identifier); + } + + clear() { + this.Instances.clear(); + this.identifiers.clear() + } + + private releaseAllFinalizedInstances(): void { + if (this.fHasFinalizationListenerStopped()) { + return; + } + // this.Instances.clear(); + // this.identifiers.clear() + // this.finalizationListener.onFinalize(this.firstIdentifier) + this.releaseTimer = setTimeout(() => { + this.releaseAllFinalizedInstances() + }, this.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL) + } + + stopFinalizationListener() { + if (this.releaseTimer) { + clearTimeout(this.releaseTimer); + } + this.hasFinalizationListenerStopped = true; + } + + + private addInstance(instance: ESObject, identifier: number) { + if (identifier < 0) { + throw Error(`Identifier must be >= 0: ${identifier}`); + } + if (this.Instances.has(identifier)) { + throw new Error(`Identifier has already been added: ${identifier}`); + } + if (this.Instances.size === 0) { + this.firstIdentifier = identifier + } + + this.identifiers.set(instance, identifier); + this.Instances.set(identifier, instance); + } + + getIdentifier(instance: Object): number { + this.logWarningIfFinalizationListenerHasStopped(); + const identifier: number = this.identifiers.get(instance) ?? -1; + return identifier; + } + + private logWarningIfFinalizationListenerHasStopped() { + if (this.fHasFinalizationListenerStopped()) { + Log.w(this.TAG, "The manager was used after calls to the FinalizationListener have been stopped."); + } + } + + public containsInstance(instance: ESObject): boolean { + this.logWarningIfFinalizationListenerHasStopped(); + return this.identifiers.has(instance); + } + + public addHostCreatedInstance(instance: ESObject): number { + this.logWarningIfFinalizationListenerHasStopped(); + + if (this.containsInstance(instance)) { + throw new Error( + `Instance of ${instance.constructor.name} has already been added.`); + } + const identifier = this.nextIdentifier++; + this.addInstance(instance, identifier); + return identifier; + } + + addDartCreatedInstance(instance: ESObject, identifier: number) { + this.logWarningIfFinalizationListenerHasStopped(); + this.addInstance(instance, identifier); + } +} + +interface FinalizationListener { + onFinalize: (identifier: number) => void; +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannel.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannel.ets new file mode 100644 index 0000000000000000000000000000000000000000..3915aa8627cdadc8967a0a648b98632de4a9c222 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannel.ets @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { JavaScriptChannelFlutterApiImpl } from "./JavaScriptChannelFlutterApiImpl" + +export class JavaScriptChannel { + private javaScriptChannelName: string; + + private flutterApi: JavaScriptChannelFlutterApiImpl; + + constructor( + flutterApi: JavaScriptChannelFlutterApiImpl, + channelName: string, + ) { + this.flutterApi = flutterApi; + this.javaScriptChannelName = channelName; + } + + public postMessage(message: string) { + this.flutterApi.postMessage( + this, message, + { + reply: () => { + } + } + ) + } + + getJavaScriptChannelName(): string { + return this.javaScriptChannelName; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..94cf1124c15fe7c1ef01ff11ce3f619f08cabc94 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelFlutterApiImpl.ets @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import {InstanceManager} from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import {Reply, JavaScriptChannelFlutterApi} from "./GeneratedOhosWebView" +import { JavaScriptChannel } from './JavaScriptChannel'; + +export class JavaScriptChannelFlutterApiImpl extends JavaScriptChannelFlutterApi { + private instanceManager : InstanceManager; + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + } + + + postMessage( + javaScriptChannel:JavaScriptChannel, + messageArg:string, + callback:Reply) { + super.postMessageT(this.getIdentifierForJavaScriptChannel(javaScriptChannel), messageArg, callback); + } + + private getIdentifierForJavaScriptChannel( javaScriptChannel:JavaScriptChannel) :number{ + const identifier:number = this.instanceManager.getIdentifier(javaScriptChannel); + if (identifier == null) { + throw new Error("Could not find identifier for JavaScriptChannel."); + } + return identifier; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..6e24d134fef6bb5c9970556685bf686d6632b87d --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/JavaScriptChannelHostApiImpl.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { JavaScriptChannelHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { JavaScriptChannel } from './JavaScriptChannel'; +import { JavaScriptChannelFlutterApiImpl } from './JavaScriptChannelFlutterApiImpl'; + +export class JavaScriptChannelHostApiImpl extends JavaScriptChannelHostApi { + private instanceManager: InstanceManager; + + private javaScriptChannelCreator: JavaScriptChannelCreator; + + private flutterApi: JavaScriptChannelFlutterApiImpl; + + /** Handles creating {@link JavaScriptChannel}s for a {@link JavaScriptChannelHostApiImpl}. */ + + /** + * Creates a host API that handles creating {@link JavaScriptChannel}s. + * + * @param instanceManager maintains instances stored to communicate with Dart objects + * @param javaScriptChannelCreator handles creating {@link JavaScriptChannel}s + * @param flutterApi handles sending messages to Dart + * @param platformThreadHandler handles making callbacks on the desired thread + */ + constructor( + instanceManager: InstanceManager, javaScriptChannelCreator: JavaScriptChannelCreator, + flutterApi: JavaScriptChannelFlutterApiImpl + ) { + super() + this.instanceManager = instanceManager; + this.javaScriptChannelCreator = javaScriptChannelCreator; + this.flutterApi = flutterApi; + } + + create(instanceId: number, channelName: string) { + const javaScriptChannel: JavaScriptChannel = + this.javaScriptChannelCreator.createJavaScriptChannel( + this.flutterApi, channelName + ) + this.instanceManager.addDartCreatedInstance(javaScriptChannel, instanceId); + } +} + +export class JavaScriptChannelCreator { + createJavaScriptChannel( + flutterApi: JavaScriptChannelFlutterApiImpl, channelName: string + ): JavaScriptChannel { + return new JavaScriptChannel(flutterApi, channelName); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosObjectHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosObjectHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c1b68e4e81fbb964003c4ea56a2d4f184947186 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosObjectHostApiImpl.ets @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { OhosObjectHostApi as OhosObjectHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; + +export class OhosObjectHostApiImpl extends OhosObjectHostApi { + private instanceManager: InstanceManager; + + /** + * Constructs a {@link OhosObjectHostApiImpl}. + * + * @param instanceManager maintains instances stored to communicate with Dart objects + */ + constructor(instanceManager: InstanceManager) { + super() + this.instanceManager = instanceManager; + } + + dispose(identifier: number) { + this.instanceManager.remove(identifier); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosWebView.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosWebView.ets new file mode 100644 index 0000000000000000000000000000000000000000..3f6f322119b069de27e196c549e0b2e45a8c4829 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/OhosWebView.ets @@ -0,0 +1,129 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import web_webview from '@ohos.web.webview' +import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; +import { Any } from '@ohos/flutter_ohos'; + +@Component +export struct OhosWebView { + @Prop params: Params; + webView: WebViewPlatformView = this.params.platformView as WebViewPlatformView; + controller: web_webview.WebviewController = this.webView.getController(); + + @State textZoomRatio: number = this.webView.getWebSettings().getTextZoom(); + @State disposed: boolean = false; + + aboutToAppear() { + this.webView.getWebSettings().onTextZoomChanged((ratio: number) => { + this.textZoomRatio = ratio; + }); + this.webView.setOnDisposeCallback(() => { + this.disposed = true; + }); + } + + build() { + Column() { + if (!this.disposed) { + Web( + { + src: this.webView.getUrl(), + controller: this.controller, + renderMode: RenderMode.SYNC_RENDER + }) + .keyboardAvoidMode(WebKeyboardAvoidMode.RESIZE_VISUAL) + .backgroundColor(this.webView.getWebSettings().getBackgroundColor()) + .onDownloadStart(this.webView.onDownloadStart) + .onPageBegin(this.webView.onPageBegin) + .onPageEnd(this.webView.onPageEnd) + .onErrorReceive(this.webView.onErrorReceive) + .onRefreshAccessedHistory(this.webView.onRefreshAccessedHistory) + .onProgressChange(this.webView.onProgressChange) + .onGeolocationShow(this.webView.onGeolocationShow) + .onGeolocationHide(this.webView.onGeolocationHide) + .onShowFileSelector(this.webView.onShowFileSelector) + .onPermissionRequest(this.webView.onPermissionRequest) + .onConsole(this.webView.onConsoleMessage) + .onWindowExit(this.webView.onWindowExit) + .domStorageAccess(this.webView.getWebSettings().getDomStorageEnabled()) + .allowWindowOpenMethod(this.webView.getWebSettings().getJavaScriptCanOpenWindowsAutomatically()) + .multiWindowAccess(false) + .javaScriptAccess(this.webView.getWebSettings().getJavaScriptEnabled()) + .mediaPlayGestureAccess(this.webView.getWebSettings().getMediaPlaybackRequiresUserGesture()) + .zoomAccess(this.webView.getWebSettings().getSupportZoom()) + .overviewModeAccess(this.webView.getWebSettings().getLoadWithOverviewMode()) + .wideViewModeAccess(this.webView.getWebSettings().getUseWideViewPort()) + .fileAccess(this.webView.getWebSettings().getAllowFileAccess()) + .textZoomRatio(this.textZoomRatio) + .onScroll(this.webView.onScroll) + .onControllerAttached(this.webView.onControllerAttached) + .onWindowNew((event: Any) => { + let newWebViewController: web_webview.WebviewController = new web_webview.WebviewController(); + let dialogController: CustomDialogController = new CustomDialogController({ + builder: NewWebView({ webViewController: newWebViewController }) + }) + dialogController.open(); + event.handler.setWebController(newWebViewController); + }) + .onSslErrorEventReceive((event) => { + event.handler.handleConfirm(); + }) + .onAlert(this.webView.onJsAlert) + .onConfirm(this.webView.onJsConfirm) + .onPrompt(this.webView.onJsPrompt) + .mixedMode(MixedMode.All) + .onOverrideUrlLoading(this.webView.onOverrideUrlLoading) + .gesture( + PinchGesture({ fingers: 2 }) + .onActionUpdate((event: GestureEvent) => { + if (event && this.webView.getWebSettings().getSupportZoom()) { + this.controller.zoom(event.scale); + } + }) + ) + } + } + } +} + +@Builder +export function WebBuilder(params: Params) { + OhosWebView({ + params: params, + webView: params.platformView as WebViewPlatformView, + controller: (params.platformView as WebViewPlatformView).getController() + }) +} + +@CustomDialog +struct NewWebView { + controller?: CustomDialogController + webViewController: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Web({ src: "", controller: this.webViewController }) + .javaScriptAccess(true) + .multiWindowAccess(false) + .onWindowExit( + () => { + if (this.controller) { + this.controller.close(); + } + } + ) + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..36dbcafbf8aef27683e6d6baaa157affbb90dae0 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestFlutterApiImpl.ets @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import {InstanceManager} from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import {PermissionRequestFlutterApi,Reply} from "./GeneratedOhosWebView" +export class PermissionRequestFlutterApiImpl { + private binaryMessenger:BinaryMessenger ; + private instanceManager:InstanceManager; + private api:PermissionRequestFlutterApi; + + + constructor(binaryMessenger:BinaryMessenger, instanceManager:InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new PermissionRequestFlutterApi(binaryMessenger); + } + + create(instance:PermissionRequest,resources:string[],callback:Reply):void { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), resources, callback); + } + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..8706e75fe9da8e21d03370c9b2825423dc7de055 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/PermissionRequestHostApiImpl.ets @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import {InstanceManager} from './InstanceManager' +import {BinaryMessenger} from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import {PermissionRequestHostApi} from "./GeneratedOhosWebView" +export class PermissionRequestHostApiImpl extends PermissionRequestHostApi { + + private binaryMessenger:BinaryMessenger ; + + private instanceManager:InstanceManager; + + constructor(binaryMessenger:BinaryMessenger, instanceManager:InstanceManager) { + super() + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + grant(instanceId:number,resources:string[]):void{ + this.getPermissionRequestInstance(instanceId).grant(resources); + } + + deny(instanceId:number):void{ + this.getPermissionRequestInstance(instanceId).deny(); + } + + private getPermissionRequestInstance(identifier:number):PermissionRequest{ + return this.instanceManager.getInstance(identifier); + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/ViewFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/ViewFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..e6ef91a0c48c1f0f0df36703a71bc2f89a3bcc78 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/ViewFlutterApiImpl.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { ViewFlutterApi, Reply } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager' + +/** + * Flutter API implementation for `View`. + * + *

This class may handle adding native instances that are attached to a Dart instance or passing + * arguments of callbacks methods to a Dart instance. + */ +export class ViewFlutterApiImpl { + // To ease adding additional methods, this value is added prematurely. + binaryMessenger: BinaryMessenger; + + instanceManager: InstanceManager; + api: ViewFlutterApi; + + /** + * Constructs a {@link ViewFlutterApiImpl}. + * + * @param binaryMessenger used to communicate with Dart over asynchronous messages + * @param instanceManager maintains instances stored to communicate with attached Dart objects + */ + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new ViewFlutterApi(binaryMessenger); + } + + /** + * Stores the `View` instance and notifies Dart to create and store a new `View` instance that is + * attached to this one. If `instance` has already been added, this method does nothing. + */ + create(instance: ESObject, callback: Reply) { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), callback); + } + } + + /** + * Sets the Flutter API used to send messages to Dart. + * + *

This is only visible for testing. + */ + setApi(api: ViewFlutterApi) { + this.api = api; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..081b561db69b44c1fcfb0246be4390443d5b3fb3 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientFlutterApiImpl.ets @@ -0,0 +1,218 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { CustomViewCallbackFlutterApiImpl } from './CustomViewCallbackFlutterApiImpl'; +import { DVModel } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView'; +import { FileChooserParamsFlutterApiImpl } from './FileChooserParamsFlutterApiImpl'; +import GeneratedOhosWebView, { + ConsoleMessageLevel, + ConsoleMessage as FlutterConsoleMessage, + CustomViewCallback, + Reply, + WebChromeClientFlutterApi +} from './GeneratedOhosWebView'; +import { GeolocationPermissionsCallbackFlutterApiImpl } from './GeolocationPermissionsCallbackFlutterApiImpl'; +import { InstanceManager } from './InstanceManager'; +import { PermissionRequestFlutterApiImpl } from './PermissionRequestFlutterApiImpl'; +import { ViewFlutterApiImpl } from './ViewFlutterApiImpl'; +import { WebChromeClient } from './WebChromeClientHostApiImpl'; +import { WebViewFlutterApiImpl } from './WebViewFlutterApiImpl'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; + +const TAG: string = "WebChromeClientFlutterApiImpl"; + +export class WebChromeClientFlutterApiImpl extends WebChromeClientFlutterApi { + private instanceManager: InstanceManager; + private webViewFlutterApi: WebViewFlutterApiImpl; + private emptyReply: Reply = { + reply: (reply) => { + } + } + + toConsoleMessageLevel(level: MessageLevel): ConsoleMessageLevel { + switch (level) { + case MessageLevel.Info: + return ConsoleMessageLevel.TIP; + case MessageLevel.Log: + return ConsoleMessageLevel.LOG; + case MessageLevel.Warn: + return ConsoleMessageLevel.WARNING; + case MessageLevel.Error: + return ConsoleMessageLevel.ERROR; + case MessageLevel.Debug: + return ConsoleMessageLevel.DEBUG; + default: + return ConsoleMessageLevel.UNKNOWN; + } + } + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + this.webViewFlutterApi = new WebViewFlutterApiImpl(binaryMessenger, instanceManager); + } + + onProgressChangedImpl( + webChromeClient: WebChromeClient, + webView: WebViewPlatformView, + progress: number, + callback: Reply + ): void { + this.webViewFlutterApi.create(webView, this.emptyReply); + + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + this.onProgressChanged(this.getIdentifierForClient(webChromeClient), webViewIdentifier, progress, callback); + } + + onShowFileChooserImpl( + webChromeClient: WebChromeClient, + webView: WebViewPlatformView, + fileChooserParams: FileSelectorParam, + callback: Reply> + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + + new FileChooserParamsFlutterApiImpl( + this.binaryMessenger, + this.instanceManager + ).create( + fileChooserParams, + this.emptyReply + ); + + this.onShowFileChooser( + this.instanceManager.getIdentifier(webChromeClient), + this.instanceManager.getIdentifier(webView), + this.instanceManager.getIdentifier(fileChooserParams), + callback + ) + } + + onGeolocationPermissionsShowPromptImpl( + webChromeClient: WebChromeClient, + origin: string, + callback: JsGeolocation, + replyCallback: Reply + ) { + new GeolocationPermissionsCallbackFlutterApiImpl(this.binaryMessenger, this.instanceManager) + .create(callback, this.emptyReply); + this.onGeolocationPermissionsShowPrompt( + this.instanceManager.getIdentifier(webChromeClient), + this.instanceManager.getIdentifier(callback), + origin, + replyCallback + ) + } + + onGeolocationPermissionsHidePromptImpl( + instance: WebChromeClient, callback: Reply + ) { + this.onGeolocationPermissionsHidePrompt( + this.instanceManager.getIdentifier(instance), + callback + ); + } + + onPermissionRequestImpl( + instance: WebChromeClient, + request: PermissionRequest, + callback: Reply + ) { + new PermissionRequestFlutterApiImpl(this.binaryMessenger, this.instanceManager) + .create(request, request.getAccessibleResource(), this.emptyReply); + + this.onPermissionRequest( + this.instanceManager.getIdentifier(instance), + this.instanceManager.getIdentifier(request), + callback + ); + } + + onShowCustomViewImpl( + instance: WebChromeClient, + view: DVModel, + customViewCallback: CustomViewCallback, + callback: Reply + ) { + new ViewFlutterApiImpl(this.binaryMessenger, this.instanceManager).create(view, this.emptyReply); + new CustomViewCallbackFlutterApiImpl(this.binaryMessenger, this.instanceManager) + .create(customViewCallback, this.emptyReply); + + this.onShowCustomView( + this.instanceManager.getIdentifier(instance), + this.instanceManager.getIdentifier(view), + this.instanceManager.getIdentifier(customViewCallback), + callback + ); + } + + onHideCustomViewImpl(instance: WebChromeClient, callback: Reply) { + this.onHideCustomView( + this.instanceManager.getIdentifier(instance), + callback + ); + } + + onConsoleMessageImpl( + instance: WebChromeClient, + message: ConsoleMessage, + callback: Reply + ) { + this.onConsoleMessage( + this.instanceManager.getIdentifier(instance), + FlutterConsoleMessage.Builder() + .setLineNumber(message.getLineNumber()) + .setMessage(message.getMessage()) + .setLevel(this.toConsoleMessageLevel(message.getMessageLevel())) + .setSourceId(message.getSourceId()) + .build(), + callback + ); + } + + onJsAlertImpl( + instance: WebChromeClient, + url: string, + message: string, + callback: Reply) { + this.onJsAlert(this.getIdentifierForClient(instance), url, message, callback); + } + + onJsConfirmImpl( + instance: WebChromeClient, + url: string, + message: string, + callback: Reply) { + this.onJsConfirm(this.getIdentifierForClient(instance), url, message, callback); + } + + onJsPromptImpl( + instance: WebChromeClient, + url: string, + message: string, + defaultValue: string, + callback: Reply) { + this.onJsPrompt(this.getIdentifierForClient(instance), url, message, defaultValue, callback); + } + + getIdentifierForClient(webChromeClient: WebChromeClient): number { + const identifier: number = this.instanceManager.getIdentifier(webChromeClient); + if (identifier == null) { + throw new Error("Could not find identifier for WebChromeClient."); + } + return identifier; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f046c912c45304c81f4ba62a5df5b8b38180aff --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebChromeClientHostApiImpl.ets @@ -0,0 +1,307 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import { Reply, WebChromeClientHostApi, CustomViewCallback, HttpAuthHandler } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { OhosWebView } from './OhosWebView'; +import { WebChromeClientFlutterApiImpl } from './WebChromeClientFlutterApiImpl'; +import { WebViewPlatformView } from './WebViewHostApiImpl' +import { WebViewClient } from './WebViewClientHostApiImpl'; +import { BuilderParams, DVModelParameters, DVModel } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView' +import web_webview from '@ohos.web.webview' + +const TAG: string = "WebChromeClientHostApiImpl"; + +export interface WebChromeClient { + onProgressChanged(view: WebViewPlatformView, progress: number): void; + + onGeolocationPermissionsShowPrompt(origin: string, callback: JsGeolocation): void; + + onGeolocationPermissionsHidePrompt(): void; + + onShowFileChooser( + webView: WebViewPlatformView, filePathCallback: FileSelectorResult, fileChooserParams: FileSelectorParam + ): boolean; + + onPermissionRequest(request: PermissionRequest): void; + + onConsoleMessage(message: ConsoleMessage): void; + + onCreateWindow(webView: WebViewPlatformView, isDialog: boolean, isUserGesture: boolean, handler: ControllerHandler): void; + + onJsAlert(webView: WebViewPlatformView, url: string, message: string, result: JsResult): boolean; + + onJsConfirm(webView: WebViewPlatformView, url: string, message: string, result: JsResult): boolean; + + onJsPrompt(webView: WebViewPlatformView, url: string, message: string, defaultValue: string, result: JsResult): boolean; +} + +export class WebChromeClientHostApiImpl extends WebChromeClientHostApi { + private instanceManager: InstanceManager; + + private webChromeClientCreator: WebChromeClientCreator; + + private flutterApi: WebChromeClientFlutterApiImpl; + + constructor( + instanceManager: InstanceManager, + webChromeClientCreator: WebChromeClientCreator, + flutterApi: WebChromeClientFlutterApiImpl + ) { + super(); + this.instanceManager = instanceManager; + this.webChromeClientCreator = webChromeClientCreator; + this.flutterApi = flutterApi; + } + + create(instanceId: number) { + const webChromeClient: WebChromeClient = this.webChromeClientCreator.createWebChromeClient(this.flutterApi); + this.instanceManager.addDartCreatedInstance(webChromeClient, instanceId); + } + + setSynchronousReturnValueForOnShowFileChooser(instanceId: number, value: boolean) { + const webChromeClient: WebChromeClientImpl = this.instanceManager.getInstance(instanceId); + webChromeClient.setReturnValueForOnShowFileChooser(value); + } + + setSynchronousReturnValueForOnConsoleMessage(instanceId: number, value: boolean) { + const webChromeClient: WebChromeClientImpl = this.instanceManager.getInstance(instanceId); + webChromeClient.setReturnValueForOnConsoleMessage(value); + } + + setSynchronousReturnValueForOnJsAlert(instanceId: number, value: boolean) { + const webChromeClient: WebChromeClientImpl = this.instanceManager.getInstance(instanceId); + webChromeClient.setReturnValueForOnJsAlert(value); + } + + setSynchronousReturnValueForOnJsConfirm(instanceId: number, value: boolean) { + const webChromeClient: WebChromeClientImpl = this.instanceManager.getInstance(instanceId); + webChromeClient.setReturnValueForOnJsConfirm(value); + } + + setSynchronousReturnValueForOnJsPrompt(instanceId: number, value: boolean) { + const webChromeClient: WebChromeClientImpl = this.instanceManager.getInstance(instanceId); + webChromeClient.setReturnValueForOnJsPrompt(value); + } +} + +export class WebChromeClientCreator { + createWebChromeClient(flutterApi: WebChromeClientFlutterApiImpl): WebChromeClientImpl { + return new WebChromeClientImpl(flutterApi); + } +} + + +@CustomDialog +struct NewWebView { + controller?: CustomDialogController + webViewController: web_webview.WebviewController = new web_webview.WebviewController(); + + build() { + Web({ src: "", controller: this.webViewController }) + .javaScriptAccess(true) + .multiWindowAccess(false) + .onWindowExit( + () => { + if (this.controller) { + this.controller.close(); + } + } + ) + } +} + +class WebChromeClientImpl implements WebChromeClient { + private flutterApi: WebChromeClientFlutterApiImpl; + private returnValueForOnShowFileChooser: boolean = false; + private returnValueForOnConsoleMessage: boolean = false; + + private returnValueForOnJsAlert : boolean = false; + private returnValueForOnJsConfirm : boolean = false; + private returnValueForOnJsPrompt : boolean = false; + + constructor(flutterApi: WebChromeClientFlutterApiImpl) { + this.flutterApi = flutterApi; + } + + private emptyReply: Reply = { + reply: (reply) => { + } + } + + onCreateWindow(webView: WebViewPlatformView, isDialog: boolean, isUserGesture: boolean, handler: ControllerHandler) { + if (webView.getDialogController() != null) { + webView.getDialogController()?.close(); + } + let newWebViewController: web_webview.WebviewController = new web_webview.WebviewController(); + let dialogController: CustomDialogController = new CustomDialogController({ + builder: NewWebView({ webViewController: newWebViewController }) + }) + dialogController.open(); + handler.setWebController(newWebViewController); + } + + onProgressChanged(view: WebViewPlatformView, progress: number) { + this.flutterApi.onProgressChangedImpl( + this, view, progress, this.emptyReply + ) + } + + onShowCustomView(view: DVModel, callback: CustomViewCallback) { + this.flutterApi.onShowCustomViewImpl(this, view, callback, this.emptyReply); + } + + onHideCustomView() { + this.flutterApi.onHideCustomViewImpl(this, this.emptyReply); + } + + onGeolocationPermissionsShowPrompt(origin: string, callback: JsGeolocation) { + this.flutterApi.onGeolocationPermissionsShowPromptImpl(this, origin, callback, this.emptyReply); + } + + onGeolocationPermissionsHidePrompt() { + this.flutterApi.onGeolocationPermissionsHidePromptImpl(this, this.emptyReply); + } + + onShowFileChooser( + webView: WebViewPlatformView, filePathCallback: FileSelectorResult, fileChooserParams: FileSelectorParam + ) { + let currentReturnValueForOnShowFileChooser: boolean = this.returnValueForOnShowFileChooser; + this.flutterApi.onShowFileChooserImpl( + this, webView, fileChooserParams, { + reply: (reply: Array | null) => { + if (currentReturnValueForOnShowFileChooser && reply) { + filePathCallback.handleFileList(reply); + } + } + } + ); + return currentReturnValueForOnShowFileChooser; + } + + onPermissionRequest(request: PermissionRequest) { + this.flutterApi.onPermissionRequestImpl(this, request, this.emptyReply); + } + + onConsoleMessage(consoleMessage: ConsoleMessage): boolean { + this.flutterApi.onConsoleMessageImpl(this, consoleMessage, this.emptyReply); + return this.returnValueForOnConsoleMessage; + } + + setReturnValueForOnShowFileChooser(value: boolean) { + this.returnValueForOnShowFileChooser = value; + } + + setReturnValueForOnConsoleMessage(value: boolean) { + this.returnValueForOnConsoleMessage = value; + } + + setReturnValueForOnJsAlert(value: boolean) { + this.returnValueForOnJsAlert = value; + } + + setReturnValueForOnJsConfirm(value: boolean) { + this.returnValueForOnJsConfirm = value; + } + + setReturnValueForOnJsPrompt(value: boolean) { + this.returnValueForOnJsPrompt = value; + } + + onJsAlert(webView: WebViewPlatformView, url: string, message: string, result: JsResult) { + if (this.returnValueForOnJsAlert) { + this.flutterApi.onJsAlertImpl(this, url, message, { + reply: () => { + result.handleConfirm(); + } + }); + return true; + } else { + return false; + } + } + + onJsConfirm(webView: WebViewPlatformView, url: string, message: string, result: JsResult) { + if (this.returnValueForOnJsConfirm) { + this.flutterApi.onJsConfirmImpl(this, url, message, { + reply: (data: boolean | null) => { + if (data) { + result.handleConfirm(); + } else { + result.handleCancel(); + } + } + }) + return true; + } else { + return false; + } + } + + onJsPrompt(webView: WebViewPlatformView, url: string, message: string, defaultValue: string, result: JsResult) { + if (this.returnValueForOnJsPrompt) { + this.flutterApi.onJsPromptImpl(this, url, message, defaultValue, { + reply: (data: string | null) => { + if (data != null) { + result.handlePromptConfirm(data); + } else { + result.handleCancel(); + } + } + }) + return true; + } else { + return false; + } + } +} + +class newWindowWebViewClient implements WebViewClient { + onPageStarted(view: WebViewPlatformView, url: string) { + Log.i(TAG, "onPageStarted"); + } + + onPageFinished(view: WebViewPlatformView, url: string) { + Log.i(TAG, "onPageFinished"); + } + + onReceivedHttpError(view: WebViewPlatformView, request: WebResourceRequest, response: WebResourceResponse): void { + Log.i(TAG, "onReceivedHttpError"); + } + + onReceivedError(view: WebViewPlatformView, request: WebResourceRequest, error: WebResourceError) { + Log.i(TAG, "onReceivedError"); + } + + doUpdateVisitedHistory(view: WebViewPlatformView, url: string, isReload: boolean) { + Log.i(TAG, "doUpdateVisitedHistory"); + } + + shouldOverrideUrlLoading(view: WebViewPlatformView, request: WebResourceRequest): boolean { + view.getController().loadUrl(request.getRequestUrl()); + return true; + } + + onReceivedHttpAuthRequest( + view: WebViewPlatformView, + handler: HttpAuthHandler, + host: string, + realm: string + ): void { + // todo + Log.i(TAG, "onReceivedHttpAuthRequest"); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebSettingsHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebSettingsHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..cc6f5912e1cfc79912eeea789c78e39ee2820d35 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebSettingsHostApiImpl.ets @@ -0,0 +1,173 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { WebSettingsHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; + +export interface WebSettings { + setDomStorageEnabled(flag: boolean): void; + + getDomStorageEnabled(): boolean; + + setJavaScriptCanOpenWindowsAutomatically(flag: boolean): void; + + getJavaScriptCanOpenWindowsAutomatically(): boolean; + + setSupportMultipleWindows(support: boolean): void; + + getSupportMultipleWindows(): boolean; + + setBackgroundColor(color: number): void; + + getBackgroundColor(): string; + + setJavaScriptEnabled(flag: boolean): void; + + getJavaScriptEnabled(): boolean; + + setUserAgentString(userAgentString: string): void; + + setMediaPlaybackRequiresUserGesture(require: boolean): void; + + getMediaPlaybackRequiresUserGesture(): boolean; + + setSupportZoom(support: boolean): void; + + getSupportZoom(): boolean; + + setLoadWithOverviewMode(overview: boolean): void; + + getLoadWithOverviewMode(): boolean; + + setUseWideViewPort(use: boolean): void; + + getUseWideViewPort(): boolean; + + setDisplayZoomControls(enabled: boolean): void; + + setBuiltInZoomControls(enabled: boolean): void; + + setAllowFileAccess(enabled: boolean): void; + + getAllowFileAccess(): boolean; + + setTextZoom(textZoom: number): void; + + getTextZoom(): number; + + + getUserAgentString(): Promise; + + onTextZoomChanged(callback: (ratio: number) => void): void; +} + +export class WebSettingsCreator { + createWebSettings(webView: WebViewPlatformView): WebSettings { + return webView.getWebSettings(); + } +} + +export class WebSettingsHostApiImpl extends WebSettingsHostApi { + private instanceManager: InstanceManager; + + private webSettingsCreator: WebSettingsCreator; + + constructor(instanceManager: InstanceManager, webSettingsCreator: WebSettingsCreator) { + super(); + this.instanceManager = instanceManager; + this.webSettingsCreator = webSettingsCreator; + } + + create(instanceId: number, webViewInstanceId: number) { + const webView: WebViewPlatformView = this.instanceManager.getInstance(webViewInstanceId); + this.instanceManager.addDartCreatedInstance(this.webSettingsCreator.createWebSettings(webView), instanceId); + } + + setDomStorageEnabled(instanceId: number, flag: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setDomStorageEnabled(flag); + } + + setJavaScriptCanOpenWindowsAutomatically(instanceId: number, flag: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setJavaScriptCanOpenWindowsAutomatically(flag); + } + + setSupportMultipleWindows(instanceId: number, support: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setSupportMultipleWindows(support); + } + + setBackgroundColor(instanceId: number, color: number) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setBackgroundColor(color); + } + + setJavaScriptEnabled(instanceId: number, flag: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setJavaScriptEnabled(flag); + } + + setUserAgentString(instanceId: number, userAgentString: string) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setUserAgentString(userAgentString); + } + + setMediaPlaybackRequiresUserGesture(instanceId: number, require: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setMediaPlaybackRequiresUserGesture(require); + } + + setSupportZoom(instanceId: number, support: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setSupportZoom(support); + } + + setLoadWithOverviewMode(instanceId: number, overview: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setLoadWithOverviewMode(overview); + } + + setUseWideViewPort(instanceId: number, use: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setUseWideViewPort(use); + } + + setDisplayZoomControls(instanceId: number, enabled: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setDisplayZoomControls(enabled); + } + + setBuiltInZoomControls(instanceId: number, enabled: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setBuiltInZoomControls(enabled); + } + + setAllowFileAccess(instanceId: number, enabled: boolean) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setAllowFileAccess(enabled); + } + + setTextZoom(instanceId: number, textZoom: number) { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + webSettings.setTextZoom(textZoom); + } + + getUserAgentString(instanceId: number): Promise { + const webSettings:WebSettings = this.instanceManager.getInstance(instanceId); + return webSettings.getUserAgentString(); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebStorageHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebStorageHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..8cc0fb8fa612a06ba209075821c01a7a1622b7ff --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebStorageHostApiImpl.ets @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { WebStorageHostApi } from './GeneratedOhosWebView'; +import web_webview from '@ohos.web.webview' +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; + +const TAG:string = "WebStorageHostApiImpl"; +export class WebStorageHostApiImpl extends WebStorageHostApi { + create(instanceId: number) { + Log.i(TAG, "WebStorage no need to create"); + } + + deleteAllData(instanceId: number) { + web_webview.WebStorage.deleteAllData(); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..23ce2809c637e137fac7bc9cb3a3bf1e66f393b8 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientFlutterApiImpl.ets @@ -0,0 +1,204 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { + Reply, + WebResourceErrorData, + WebResourceRequestData, + WebResourceResponseData, + WebViewClientFlutterApi, + WebViewFlutterApi, + HttpAuthHandler, +} from './GeneratedOhosWebView'; +import { HttpAuthHandlerFlutterApiImpl } from './HttpAuthHandlerFlutterApiImpl'; +import { InstanceManager } from './InstanceManager'; +import { WebViewClient } from './WebViewClientHostApiImpl'; +import { WebViewFlutterApiImpl } from './WebViewFlutterApiImpl'; +import { WebViewHostApiImpl, WebViewPlatformView } from './WebViewHostApiImpl'; + +export class WebViewClientFlutterApiImpl extends WebViewClientFlutterApi { + private instanceManager: InstanceManager; + private webViewFlutterApi: WebViewFlutterApiImpl; + private emptyReply: Reply = { + reply: (reply) => { + } + } + + static createWebResourceErrorData(error: WebResourceError): WebResourceErrorData { + return WebResourceErrorData.Builder() + .setErrorCode(error.getErrorCode()) + .setDescription(error.getErrorInfo()) + .build(); + } + + static toWebHeadersMap(headers: Array

) { + let headersMap: Map = new Map(); + if (headers == null || headers.length == 0) { + return headersMap; + } + for (let header of headers) { + headersMap.set(header.headerKey, header.headerValue); + } + return headersMap; + } + + static createWebResourceRequestData(request: WebResourceRequest): WebResourceRequestData { + return WebResourceRequestData.Builder() + .setUrl(request.getRequestUrl()) + .setIsForMainFrame(request.isMainFrame()) + .setIsRedirect(request.isRedirect()) + .setHasGesture(request.isRequestGesture()) + .setMethod(request.getRequestMethod()) + .setRequestHeaders(WebViewClientFlutterApiImpl.toWebHeadersMap(request.getRequestHeader())) + .build(); + } + + static createWebResourceResponseData(response: WebResourceResponse): WebResourceResponseData { + return WebResourceResponseData.Builder() + .setStatusCode(response.getResponseCode()) //setStatusCode(response.getStatusCode()) + .build(); + } + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + this.webViewFlutterApi = new WebViewFlutterApiImpl(binaryMessenger, instanceManager); + } + + onPageStartedImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + urlArg: string, + callback: Reply + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + this.onPageStarted(this.getIdentifierForClient(webViewClient), webViewIdentifier, urlArg, callback); + } + + onPageFinishedImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + urlArg: string, + callback: Reply + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + this.onPageFinished(this.getIdentifierForClient(webViewClient), webViewIdentifier, urlArg, callback); + } + + /** Passes arguments from {@link WebViewClient#onReceivedHttpError} to Dart. */ + onReceivedHttpErrorImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + request: WebResourceRequest, + response: WebResourceResponse, + callback: Reply + ){ + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + this.onReceivedHttpError( + this.getIdentifierForClient(webViewClient), + webViewIdentifier, + WebViewClientFlutterApiImpl.createWebResourceRequestData(request), + WebViewClientFlutterApiImpl.createWebResourceResponseData(response), + callback + ) + } + + onReceivedRequestErrorImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + request: WebResourceRequest, + error: WebResourceError, + callback: Reply + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + + this.onReceivedRequestError( + this.getIdentifierForClient(webViewClient), + webViewIdentifier, + WebViewClientFlutterApiImpl.createWebResourceRequestData(request), + WebViewClientFlutterApiImpl.createWebResourceErrorData(error), + callback + ) + } + + requestLoadingImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + request: WebResourceRequest, + callback: Reply + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + + this.requestLoading( + this.getIdentifierForClient(webViewClient), + webViewIdentifier, + WebViewClientFlutterApiImpl.createWebResourceRequestData(request), + callback + ) + } + + doUpdateVisitedHistoryImpl( + webViewClient: WebViewClient, + webView: WebViewPlatformView, + url: string, + isReload: boolean, + callback: Reply + ) { + this.webViewFlutterApi.create(webView, this.emptyReply); + const webViewIdentifier: number = this.instanceManager.getIdentifier(webView); + + this.doUpdateVisitedHistory( + this.getIdentifierForClient(webViewClient), + webViewIdentifier, + url, + isReload, + callback + ) + } + + onReceivedHttpAuthRequestImpl( + webViewClient: WebViewClient, + webview: WebViewPlatformView, + httpAuthHandler: HttpAuthHandler, + host: string, + realm: string, + callback: Reply + ) { + new HttpAuthHandlerFlutterApiImpl(this.binaryMessenger, this.instanceManager) + .create(httpAuthHandler, this.emptyReply); + + this.onReceivedHttpAuthRequest( + this.instanceManager.getIdentifier(webViewClient), + this.instanceManager.getIdentifier(webview), + this.instanceManager.getIdentifier(httpAuthHandler), + host, + realm, + callback); + } + + getIdentifierForClient(webViewClient: WebViewClient): number { + let identifier: number = this.instanceManager.getIdentifier(webViewClient); + if (identifier == null) { + throw new Error("Could not find identifier for WebViewClient."); + } + return identifier; + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c7efe8ccf2436cb639e4d09b0fe89636faf3731 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewClientHostApiImpl.ets @@ -0,0 +1,127 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { Reply, WebViewClientHostApi, HttpAuthHandler } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { WebViewClientFlutterApiImpl } from './WebViewClientFlutterApiImpl'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; + +export interface WebViewClient { + onPageStarted(view: WebViewPlatformView, url: string): void; + + onPageFinished(view: WebViewPlatformView, url: string): void; + + onReceivedHttpError(view: WebViewPlatformView, request: WebResourceRequest, response: WebResourceResponse): void; + + onReceivedError(view: WebViewPlatformView, request: WebResourceRequest, error: WebResourceError): void; + + shouldOverrideUrlLoading(view: WebViewPlatformView, request: WebResourceRequest): boolean; + + doUpdateVisitedHistory(view: WebViewPlatformView, url: string, isReload: boolean): void; + + onReceivedHttpAuthRequest( + view: WebViewPlatformView, + handler: HttpAuthHandler, + host: string, + realm: string + ): void; +} + +export class WebViewClientImpl implements WebViewClient { + private flutterApi: WebViewClientFlutterApiImpl; + private returnValueForShouldOverrideUrlLoading: boolean = false; + private emptyReply: Reply = { + reply: (reply) => { + } + } + + constructor(flutterApi: WebViewClientFlutterApiImpl) { + this.flutterApi = flutterApi; + } + + onPageStarted(view: WebViewPlatformView, url: string) { + this.flutterApi.onPageStartedImpl(this, view, url, this.emptyReply); + } + + onPageFinished(view: WebViewPlatformView, url: string) { + this.flutterApi.onPageFinishedImpl(this, view, url, this.emptyReply); + } + + onReceivedHttpError(view: WebViewPlatformView, request: WebResourceRequest, response:WebResourceResponse) { + this.flutterApi.onReceivedHttpErrorImpl(this, view, request, response, this.emptyReply); +} + + onReceivedError(view: WebViewPlatformView, request: WebResourceRequest, error: WebResourceError) { + this.flutterApi.onReceivedRequestErrorImpl(this, view, request, error, this.emptyReply); + } + + shouldOverrideUrlLoading(view: WebViewPlatformView, request: WebResourceRequest): boolean { + this.flutterApi.requestLoadingImpl(this, view, request, this.emptyReply); + return request.isMainFrame() && this.returnValueForShouldOverrideUrlLoading; + } + + doUpdateVisitedHistory(view: WebViewPlatformView, url: string, isReload: boolean) { + this.flutterApi.doUpdateVisitedHistoryImpl(this, view, url, isReload, this.emptyReply); + } + + onReceivedHttpAuthRequest( + view: WebViewPlatformView, + handler: HttpAuthHandler, + host: string, + realm: string) { + this.flutterApi.onReceivedHttpAuthRequestImpl(this, view, handler, host, realm, this.emptyReply); +} + + setReturnValueForShouldOverrideUrlLoading(value: boolean) { + this.returnValueForShouldOverrideUrlLoading = value; + } +} + +export class WebViewClientCreator { + createWebViewClient(flutterApi: WebViewClientFlutterApiImpl): WebViewClient { + return new WebViewClientImpl(flutterApi); + } +} + +export class WebViewClientHostApiImpl extends WebViewClientHostApi { + private instanceManager: InstanceManager; + private webViewClientCreator: WebViewClientCreator; + private flutterApi: WebViewClientFlutterApiImpl; + + constructor( + instanceManager: InstanceManager, + webViewClientCreator: WebViewClientCreator, + flutterApi: WebViewClientFlutterApiImpl + ) { + super(); + this.instanceManager = instanceManager; + this.webViewClientCreator = webViewClientCreator; + this.flutterApi = flutterApi; + } + + create(instanceId: number) { + const webViewClient: WebViewClient = this.webViewClientCreator.createWebViewClient(this.flutterApi); + this.instanceManager.addDartCreatedInstance(webViewClient, instanceId); + } + + setSynchronousReturnValueForShouldOverrideUrlLoading(instanceId: number, value: boolean) { + const webViewClient: WebViewClient = this.instanceManager.getInstance(instanceId); + if (webViewClient instanceof WebViewClientImpl) { + webViewClient.setReturnValueForShouldOverrideUrlLoading(value); + } else { + throw new Error("This WebViewClient doesn't support setting the returnValueForShouldOverrideUrlLoading."); + } + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..a6de573c03facf8c0667efe4b64dfbc9140bad57 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterApiImpl.ets @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { Reply, WebViewFlutterApi, WebViewHostApi } from './GeneratedOhosWebView'; +import { InstanceManager } from './InstanceManager'; +import { WebViewPlatformView } from './WebViewHostApiImpl'; + +export class WebViewFlutterApiImpl { + private binaryMessenger: BinaryMessenger; + private instanceManager: InstanceManager; + private api: WebViewFlutterApi; + + constructor(binaryMessenger: BinaryMessenger, instanceManager: InstanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + this.api = new WebViewFlutterApi(binaryMessenger); + } + + create(instance: WebViewPlatformView, callback: Reply): void { + if (!this.instanceManager.containsInstance(instance)) { + this.api.create(this.instanceManager.addHostCreatedInstance(instance), callback); + } + } + + setApi(api: WebViewFlutterApi): void { + this.api = api; + } + + onScrollChanged( + instance: WebViewHostApi, + left: number, + top: number, + oldLeft: number, + oldTop: number, + callback: Reply): void { + this.api.onScrollChanged( + this.instanceManager.getIdentifier(instance), + left, + top, + oldLeft, + oldTop, + callback); + } +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterPlugin.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterPlugin.ets new file mode 100644 index 0000000000000000000000000000000000000000..c6af1abce4fc42cf1ecb907fb39d793ebdf1fcfd --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewFlutterPlugin.ets @@ -0,0 +1,188 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterPluginBinding, FlutterPlugin } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import PluginRegistry from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/PluginRegistry'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import PlatformViewRegistry from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewRegistry'; +import { OhosObjectHostApiImpl } from './OhosObjectHostApiImpl'; +import { CookieManagerHostApiImpl } from './CookieManagerHostApiImpl'; +import { CustomViewCallbackHostApiImpl } from './CustomViewCallbackHostApiImpl'; +import { DownloadListenerFlutterApiImpl } from './DownloadListenerFlutterApiImpl'; +import { DownloadListenerCreator, DownloadListenerHostApiImpl } from './DownloadListenerHostApiImpl'; +import { FlutterAssetManager, PluginBindingFlutterAssetManager } from './FlutterAssetManager'; +import { FlutterAssetManagerHostApiImpl } from './FlutterAssetManagerHostApiImpl'; +import GeneratedOhosWebView, { + CookieManagerHostApi, + CustomViewCallbackHostApi, + DownloadListenerHostApi, + FlutterAssetManagerHostApi, + GeolocationPermissionsCallbackHostApi, + HttpAuthHandlerHostApi, + InstanceManagerHostApi, + JavaScriptChannelHostApi, + PermissionRequestHostApi, + OhosObjectFlutterApi, + OhosObjectHostApi, + WebViewHostApi, + InstanceManagerApi, + WebViewClientHostApi, + WebChromeClientHostApi, + WebSettingsHostApi, + WebStorageHostApi +} from './GeneratedOhosWebView'; +import { GeolocationPermissionsCallbackHostApiImpl } from './GeolocationPermissionsCallbackHostApiImpl'; +import { HttpAuthHandlerHostApiImpl } from './HttpAuthHandlerHostApiImpl'; +import { InstanceManager } from './InstanceManager'; +import { JavaScriptChannelCreator, JavaScriptChannelHostApiImpl } from './JavaScriptChannelHostApiImpl'; +import { PermissionRequestHostApiImpl } from './PermissionRequestHostApiImpl'; +import { WebViewHostApiImpl, WebViewProxy } from './WebViewHostApiImpl'; +import { FlutterViewFactory } from './FlutterViewFactory'; +import { JavaScriptChannelFlutterApiImpl } from './JavaScriptChannelFlutterApiImpl'; +import { WebViewClientCreator, WebViewClientHostApiImpl } from './WebViewClientHostApiImpl'; +import { WebViewClientFlutterApiImpl } from './WebViewClientFlutterApiImpl'; +import { WebChromeClientCreator, WebChromeClientHostApiImpl } from './WebChromeClientHostApiImpl'; +import { WebChromeClientFlutterApiImpl } from './WebChromeClientFlutterApiImpl'; +import { WebSettingsCreator, WebSettingsHostApiImpl } from './WebSettingsHostApiImpl'; +import { WebStorageHostApiImpl } from './WebStorageHostApiImpl'; + +const TAG:string = "WebViewFlutterPlugin"; +export class WebViewFlutterPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return TAG; + } + + private instanceManager: InstanceManager|null = null; + + setUp( + binaryMessenger: BinaryMessenger, viewRegistry: PlatformViewRegistry, context: Context, + flutterAssetManager: FlutterAssetManager + ) { + this.instanceManager = new InstanceManager({ + onFinalize: (identifier: number) => { + new OhosObjectFlutterApi(binaryMessenger).dispose( + identifier, { reply: () => { + } } + ) + } + }) + + InstanceManagerHostApi.setup( + binaryMessenger, + { + clear: () => { + if(this.instanceManager) + this.instanceManager.clear(); + } + } + ); + viewRegistry.registerViewFactory( + "plugins.flutter.io/webview", new FlutterViewFactory(this.instanceManager) + ); + + let webViewHostApi: WebViewHostApi = + new WebViewHostApiImpl( + this.instanceManager, new WebViewProxy(), binaryMessenger, context); + let javaScriptChannelHostApi: JavaScriptChannelHostApi = + new JavaScriptChannelHostApiImpl( + this.instanceManager, + new JavaScriptChannelCreator(), + new JavaScriptChannelFlutterApiImpl(binaryMessenger, this.instanceManager), + ); + + OhosObjectHostApi.setup(binaryMessenger, new OhosObjectHostApiImpl(this.instanceManager)); + + WebViewHostApi.setup(binaryMessenger, webViewHostApi); + + JavaScriptChannelHostApi.setup(binaryMessenger, javaScriptChannelHostApi); + + WebViewClientHostApi.setup( + binaryMessenger, + new WebViewClientHostApiImpl( + this.instanceManager, + new WebViewClientCreator(), + new WebViewClientFlutterApiImpl(binaryMessenger, this.instanceManager)) + ); + + WebChromeClientHostApi.setup( + binaryMessenger, + new WebChromeClientHostApiImpl( + this.instanceManager, + new WebChromeClientCreator(), + new WebChromeClientFlutterApiImpl(binaryMessenger, this.instanceManager)) + ); + + DownloadListenerHostApi.setup( + binaryMessenger, + new DownloadListenerHostApiImpl( + this.instanceManager, + new DownloadListenerCreator(), + new DownloadListenerFlutterApiImpl(binaryMessenger, this.instanceManager)) + ); + + WebSettingsHostApi.setup( + binaryMessenger, + new WebSettingsHostApiImpl( + this.instanceManager, new WebSettingsCreator()) + ); + + FlutterAssetManagerHostApi.setup( + binaryMessenger, new FlutterAssetManagerHostApiImpl(flutterAssetManager) + ); + + CookieManagerHostApi.setup( + binaryMessenger, new CookieManagerHostApiImpl(binaryMessenger, this.instanceManager) + ); + + WebStorageHostApi.setup( + binaryMessenger, + new WebStorageHostApiImpl() + ); + + PermissionRequestHostApi.setup( + binaryMessenger, new PermissionRequestHostApiImpl(binaryMessenger, this.instanceManager) + ); + + GeolocationPermissionsCallbackHostApi.setup( + binaryMessenger, + new GeolocationPermissionsCallbackHostApiImpl(binaryMessenger, this.instanceManager) + ); + CustomViewCallbackHostApi.setup( + binaryMessenger, new CustomViewCallbackHostApiImpl(binaryMessenger, this.instanceManager)); + HttpAuthHandlerHostApi.setup( + binaryMessenger, new HttpAuthHandlerHostApiImpl(binaryMessenger, this.instanceManager)); + } + + onAttachedToEngine(binding: FlutterPluginBinding) { + this.setUp( + binding.getBinaryMessenger(), + binding.getPlatformViewRegistry(), + binding.getApplicationContext(), + new PluginBindingFlutterAssetManager( + binding.getApplicationContext().resourceManager, binding.getFlutterAssets()) + ); + } + + onDetachedFromEngine(binding: FlutterPluginBinding) { + if (this.instanceManager != null) { + this.instanceManager.stopFinalizationListener(); + this.instanceManager = null; + } + } + + getInstanceManager() { + return this.instanceManager; + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewHostApiImpl.ets b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewHostApiImpl.ets new file mode 100644 index 0000000000000000000000000000000000000000..63147881d1bcda30ba950e6e1f86a6cdf2172a9f --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/ets/io.flutter.plugins/webview_flutter/WebViewHostApiImpl.ets @@ -0,0 +1,674 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView' +import { DVModel, DVModelParameters } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView' +import { Result, WebViewHostApi, WebViewPoint } from './GeneratedOhosWebView' +import web_webview from '@ohos.web.webview' +import { WebBuilder, OhosWebView } from './OhosWebView' +import { createDVModelFromJson } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson' +import { DVModelJson } from "./DynamicUtils" +import { InstanceManager } from './InstanceManager' +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import common from '@ohos.app.ability.common' +import { WebChromeClient } from './WebChromeClientHostApiImpl' +import { WebViewClient } from './WebViewClientHostApiImpl' +import { WebSettings } from './WebSettingsHostApiImpl' +import { DynamicUtils } from "./DynamicUtils" +import { DownloadListener } from './DownloadListenerFlutterApiImpl' +import { DisplayListenerProxy } from './DisplayListenerProxy' +import { JavaScriptChannel } from './JavaScriptChannel' +import Log from '@ohos/flutter_ohos/src/main/ets/util/Log'; +import { WebViewFlutterApiImpl } from './WebViewFlutterApiImpl.ets' + +const TAG: string = "WebViewHostApiImpl"; + +export class WebViewHostApiImpl extends WebViewHostApi { + private instanceManager: InstanceManager; + + private webViewProxy: WebViewProxy; + + private binaryMessenger: BinaryMessenger; + + private context: common.Context; + private api?: WebViewFlutterApiImpl; + + constructor( + instanceManager: InstanceManager, + webViewProxy: WebViewProxy, + binaryMessenger: BinaryMessenger, + context: common.Context + ) { + super(); + this.instanceManager = instanceManager; + this.webViewProxy = webViewProxy; + this.binaryMessenger = binaryMessenger; + this.context = context; + } + + setContext(context: common.Context): void { + this.context = context; + } + + create(instanceId: number): void { + let displayProxy: DisplayListenerProxy = new DisplayListenerProxy(); + displayProxy.onPreWebViewInitialization(); + const webView: WebViewPlatformView = this.webViewProxy.createWebView(); + displayProxy.onPostWebViewInitialization(); + this.instanceManager.addDartCreatedInstance(webView, instanceId); + } + + loadData(instanceId: number, data: string, mimeType: string, encoding: string): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().loadData(data, mimeType, encoding, " ", " "); + } + + async loadDataWithBaseUrl( + instanceId: number, baseUrl: string, data: string, mimeType: string, encoding: string, historyUrl: string + ): Promise { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + await webView.waitControllerAttached(); + try { + // 当baseUrl为空时,其值默认为resource://rawfile/。这样设置是为了解决标签锚点无效问题。 + webView.getController().loadData(data, mimeType, encoding, baseUrl == null || baseUrl.trim().length === 0 ? "resource://rawfile/" : baseUrl , historyUrl == null ? " " : historyUrl); + } catch (err) { + Log.e(TAG, "loadDataWithBaseUrl err = " + err); + } + } + + async loadUrl(instanceId: number, url: string, headers: Map): Promise { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + await webView.waitControllerAttached(); + try { + if (url.startsWith("resources/rawfile/")) { + webView.getController().loadUrl($rawfile(url.replace("resources/rawfile/","")), this.toWebHeaders(headers)); + }else { + webView.getController().loadUrl(url, this.toWebHeaders(headers)); + } + webView.setUrl(webView.getController().getUrl()); + } catch (err) { + Log.e(TAG, "loadUrl err = " + err); + } + } + + toWebHeaders(headers: Map): Array { + let result: Array = new Array; + if (headers == null || headers.size == 0) { + return result; + } + for (let arr of headers) { + let key = arr[0]; + let value = arr[1]; + let header: web_webview.WebHeader = { headerKey: key, headerValue: value }; + result.push(header); + } + return result; + } + + async postUrl(instanceId: number, url: string, data: Uint8Array): Promise { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + await webView.waitControllerAttached(); + try { + webView.getController().postUrl(url,data.buffer); + } catch (err) { + Log.e(TAG, "postUrl err = " + err); + } + } + + getUrl(instanceId: number): string { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getController().getUrl(); + } + + canGoBack(instanceId: number): boolean { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getController().accessBackward(); + } + + canGoForward(instanceId: number): boolean { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getController().accessForward(); + } + + goBack(instanceId: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().backward(); + } + + goForward(instanceId: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().forward(); + } + + reload(instanceId: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().refresh(); + } + + clearCache(instanceId: number, includeDiskFiles: boolean): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().removeCache(includeDiskFiles); + } + + evaluateJavascript(instanceId: number, javascriptString: string, result: Result): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().runJavaScript(javascriptString) + .then( + scriptResult => { + result.success(scriptResult); + } + ) + .catch( + (error: ESObject) => { + result.error(error); + } + ) + } + + getTitle(instanceId: number): string { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getController().getTitle(); + } + + scrollTo(instanceId: number, x: number, y: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().scrollTo(x, y); + } + + scrollBy(instanceId: number, x: number, y: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.getController().scrollBy(x, y); + } + + getScrollX(instanceId: number): number { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getScrollX(); + } + + getScrollY(instanceId: number): number { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return webView.getScrollY() + } + + getScrollPosition(instanceId: number): WebViewPoint { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + return WebViewPoint.Builder() + .setX(webView.getScrollY()) + .setY(webView.getScrollY()) + .build(); + } + + setWebContentsDebuggingEnabled(enabled: boolean): void { + this.webViewProxy.setWebContentsDebuggingEnabled(enabled); + } + + setWebViewClient(instanceId: number, webViewClientInstanceId: number) { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.setWebViewClient(this.instanceManager.getInstance(webViewClientInstanceId)); + } + + async addJavaScriptChannel(instanceId: number, javaScriptChannelInstanceId: number): Promise { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + const javaScriptChannel: JavaScriptChannel = this.instanceManager.getInstance(javaScriptChannelInstanceId); + await webView.waitControllerAttached(); + try { + webView.getController().registerJavaScriptProxy( + { + postMessage: (message: string) => { + javaScriptChannel.postMessage(message) + }, + }, + javaScriptChannel.getJavaScriptChannelName(), + ["postMessage"] + ) + webView.getController().refresh() + } catch (err) { + Log.e(TAG, "addJavaScriptChannel err = " + err); + } + } + + removeJavaScriptChannel(instanceId: number, javaScriptChannelInstanceId: number): void { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + const javaScriptChannel: JavaScriptChannel = this.instanceManager.getInstance(javaScriptChannelInstanceId); + webView.getController().deleteJavaScriptRegister(javaScriptChannel.getJavaScriptChannelName()); + } + + setDownloadListener(instanceId: number, listenerInstanceId: number) { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.setDownloadListener(this.instanceManager.getInstance(listenerInstanceId)); + } + + setWebChromeClient(instanceId: number, clientInstanceId: number) { + const webView: WebViewPlatformView = this.instanceManager.getInstance(instanceId); + webView.setWebChromeClient(this.instanceManager.getInstance(clientInstanceId)); + } + + getInstanceManager(): InstanceManager { + return this.instanceManager; + } + + + onScrollChangedImpl(left: number, top: number, oldLeft: number, oldTop: number) { + this.onScrollChangedImpl(left, top, oldLeft, oldTop); + this.api?.onScrollChanged( + this, left, top, oldLeft, oldTop, {reply: () => {} }); + } + + setApi(api: WebViewFlutterApiImpl) { + this.api = api; + } +} + +export class WebViewPlatformView extends PlatformView { + + private WebCookieManager: web_webview.WebCookieManager = new web_webview.WebCookieManager(); + + private controller: web_webview.WebviewController = new web_webview.WebviewController(); + + private tempUrl: string = ""; + + private downloadListener: DownloadListener = {} as ESObject; + + private webChromeClient: WebChromeClient | null = null; + + private webViewClint: WebViewClient | null = null; + + private webSettings: WebSettings | null = null; + + private dialogController: CustomDialogController | null = null; + + private scrollX: number = 0; + + private scrollY: number = 0; + + private returnValueForShouldOverrideUrlLoading: boolean = false; + + private controllerAttached: boolean = false; + + private onDisposeCallback?: () => void; + + onDownloadStart = (event: ESObject) => { + if (this.downloadListener && this.downloadListener.onDownloadStart) { + this.downloadListener.onDownloadStart( + event.url, + event.userAgent, + event.contentDisposition, + event.mimetype, + event.contentLength + ) + } + } + + onPageBegin = (event: ESObject) => { + if (this.webViewClint) { + this.webViewClint.onPageStarted(this, event.url); + } + } + + onPageEnd = (event: ESObject) => { + if (this.webViewClint) { + this.webViewClint.onPageFinished(this, event.url); + } + } + + onErrorReceive = (event: ESObject) => { + if (this.webViewClint) { + this.webViewClint.onReceivedError(this, event.request, event.error); + } + } + + onOverrideUrlLoading = (request: WebResourceRequest) => { + Log.i(TAG, "onOverrideUrlLoading request = " + JSON.stringify(request)) + if(request.getRequestUrl() == 'loaded:///'){ + return true; + } + if (this.webViewClint) { + return this.webViewClint.shouldOverrideUrlLoading(this, request); + } + return false; + } + + onRefreshAccessedHistory = (event: ESObject) => { + if (this.webViewClint) { + this.webViewClint.doUpdateVisitedHistory(this, event.url, event.isRefreshed); + } + } + + onProgressChange = (event: ESObject) => { + if (this.webChromeClient) { + this.webChromeClient.onProgressChanged(this, event.newProgress) + } + } + + onGeolocationShow = (event: ESObject) => { + if (this.webChromeClient) { + this.webChromeClient.onGeolocationPermissionsShowPrompt(event.origin, event.geolocation) + } + } + + onGeolocationHide = () => { + if (this.webChromeClient) { + this.webChromeClient.onGeolocationPermissionsHidePrompt(); + } + } + + onShowFileSelector = (event: ESObject) => { + if (this.webChromeClient) { + return this.webChromeClient.onShowFileChooser(this, event.result, event.fileSelector) + } + return false; + } + + onPermissionRequest = (event: ESObject) => { + if (this.webChromeClient) { + this.webChromeClient.onPermissionRequest(event.request); + } + } + + onConsoleMessage = (event: ESObject) => { + let message:ConsoleMessage = event.message; + if (message.getMessageLevel() == MessageLevel.Error || message.getMessageLevel() == MessageLevel.Warn) { + if (this.webChromeClient) { + this.webChromeClient.onConsoleMessage(event.message); + } + } else { + Log.d(TAG, "logLevel: " + message.getMessageLevel() + " "+ message.getMessage()); + } + return true; + } + + onWindowNew = (event: ESObject) => { + if (this.webChromeClient) { + this.webChromeClient.onCreateWindow(this, event.isAlert, event.isUserTrigger, event.handler) + } + } + + onWindowExit = () => { + if (this.dialogController) { + this.dialogController.close(); + } + } + + onScroll = (event: ESObject) => { + this.scrollX = event.xOffset; + this.scrollY = event.yOffset; + } + + onControllerAttached = () => { + Log.d(TAG, "onControllerAttached"); + this.controllerAttached = true + } + + setOnDisposeCallback(callback: () => void) { + this.onDisposeCallback = callback; + } + + onJsAlert = (event: ESObject): boolean => { + if (this.webChromeClient && event) { + return this.webChromeClient.onJsAlert(this, event.url, event.message, event.result); + } + return true; + } + + onJsConfirm = (event: ESObject): boolean => { + if (this.webChromeClient && event) { + return this.webChromeClient.onJsConfirm(this, event.url, event.message, event.result); + } + return true; + } + + onJsPrompt = (event: ESObject): boolean => { + if (this.webChromeClient && event) { + return this.webChromeClient.onJsPrompt(this, event.url, event.message, event.value, event.result); + } + return true; + } + + getType(): string { + return 'web'; + } + + getView(): WrappedBuilder<[Params]> { + return new WrappedBuilder(WebBuilder); + } + + dispose(): void { + this.controller.stopAllMedia(); + this.onDisposeCallback && this.onDisposeCallback(); + } + + getController(): web_webview.WebviewController { + return this.controller; + } + + setUrl(url: string): void { + this.tempUrl = url; + } + + getUrl(): string { + return this.tempUrl; + } + + getWebCookieManager(): web_webview.WebCookieManager { + return this.WebCookieManager + } + + setDownloadListener(listener: DownloadListener) { + this.downloadListener = listener; + } + + setWebViewClient(webViewClient: WebViewClient) { + this.webViewClint = webViewClient; + } + + setWebChromeClient(webChromeClient: WebChromeClient) { + this.webChromeClient = webChromeClient; + } + + setDialogController(dialogController: CustomDialogController) { + this.dialogController = dialogController; + } + + getDialogController(): CustomDialogController | null { + return this.dialogController; + } + + getWebSettings(): WebSettings { + if (this.webSettings == null) { + this.webSettings = new WebSettingsImpl(this); + } + return this.webSettings!; + } + + getScrollX(): number { + return this.scrollX; + } + + getScrollY(): number { + return this.scrollY; + } + + setReturnValueForShouldOverrideUrlLoading(value: boolean) { + this.returnValueForShouldOverrideUrlLoading = value; + } + + async waitControllerAttached() { + if (!this.controllerAttached) { + await this.checkControllerAttached() + } + } + + checkControllerAttached(): Promise { + return new Promise((resolve, reject) => { + try { + let intervalId = setInterval(() => { + if (this.controllerAttached) { + clearInterval(intervalId) + resolve() + } + }, 20) + } catch (err) { + reject() + } + }) + } + +} + +export class WebViewProxy { + createWebView(): WebViewPlatformView { + return new WebViewPlatformView(); + } + + setWebContentsDebuggingEnabled(enabled: boolean): void { + web_webview.WebviewController.setWebDebuggingAccess(enabled); + } +} + +class WebSettingsImpl implements WebSettings { + private webView: WebViewPlatformView; + params: DVModelParameters = new DVModelParameters; + domStorageAccess: boolean = false; + allowWindowOpenMethod : boolean = false; + multiWindowAccess : boolean = false; + backgroundColor : string = ""; + javaScriptAccess : boolean = false; + mediaPlayGestureAccess : boolean = false; + zoomAccess : boolean = true; + overviewModeAccess : boolean = false; + wideViewModeAccess: boolean = false; + fileAccess : boolean = true; + textZoomRatio : number = 0; + textZoomRatioCallback?: (ratio: number) => void; + + constructor(webView: WebViewPlatformView) { + this.webView = webView; + //this.params = webView.getView().params; + } + + setDomStorageEnabled(flag: boolean) { + this.domStorageAccess = flag; + } + + getDomStorageEnabled() : boolean{ + return this.domStorageAccess; + } + + setJavaScriptCanOpenWindowsAutomatically(flag: boolean) { + this.allowWindowOpenMethod = flag; + } + + getJavaScriptCanOpenWindowsAutomatically() : boolean{ + return this.allowWindowOpenMethod; + } + + setSupportMultipleWindows(support: boolean) { + this.multiWindowAccess = support; + } + + getSupportMultipleWindows() : boolean{ + return this.multiWindowAccess; + } + + setBackgroundColor(color: number) { + // number 无法实现透明度,所以转成 string + let colorStr = `#${color.toString(16).padStart(8, '0')}`; + this.backgroundColor = colorStr; + } + + getBackgroundColor() : string{ + return this.backgroundColor; + } + + setJavaScriptEnabled(flag: boolean) { + this.javaScriptAccess = flag; + } + + getJavaScriptEnabled() : boolean { + return this.javaScriptAccess; + } + + async setUserAgentString(userAgentString: string) { + await this.webView.waitControllerAttached(); + this.webView.getController().setCustomUserAgent(userAgentString); + } + + setMediaPlaybackRequiresUserGesture(require: boolean) { + this.mediaPlayGestureAccess = require; + } + + getMediaPlaybackRequiresUserGesture() : boolean{ + return this.mediaPlayGestureAccess; + } + + setSupportZoom(support: boolean) { + this.zoomAccess = support; + } + + getSupportZoom() : boolean{ + return this.zoomAccess; + } + + setLoadWithOverviewMode(overview: boolean) { + this.overviewModeAccess = overview; + } + + getLoadWithOverviewMode() : boolean { + return this.overviewModeAccess; + } + + setUseWideViewPort(use: boolean) { + this.wideViewModeAccess = use; + } + + getUseWideViewPort() : boolean { + return this.wideViewModeAccess; + } + + setDisplayZoomControls(enabled: boolean) { + //TODO:确认是否支持 + } + + setBuiltInZoomControls(enabled: boolean) { + //TODO:确认是否支持 + } + + setAllowFileAccess(enabled: boolean) { + this.fileAccess = enabled; + } + + getAllowFileAccess() : boolean { + return this.fileAccess; + } + + setTextZoom(textZoom: number) { + this.textZoomRatio = textZoom; + this.textZoomRatioCallback && this.textZoomRatioCallback(textZoom); + } + + async getUserAgentString(): Promise { + await this.webView.waitControllerAttached(); + return this.webView.getController().getCustomUserAgent(); + } + + getTextZoom() : number{ + return this.textZoomRatio; + } + + onTextZoomChanged(callback: (ratio: number) => void): void { + this.textZoomRatioCallback = callback; + } + +} \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/module.json5 b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a4200765f600db4a4e9a5c89730140afd33f9ba3 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/ohos/src/main/module.json5 @@ -0,0 +1,24 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "webview_flutter_ohos", + "type": "har", + "deviceTypes": [ + "default" + ] + } +} diff --git a/packages/webview_flutter/webview_flutter_ohos/pubspec.yaml b/packages/webview_flutter/webview_flutter_ohos/pubspec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a8a8ff35b7ac7db19111fcc05ecb2af936ccb92c --- /dev/null +++ b/packages/webview_flutter/webview_flutter_ohos/pubspec.yaml @@ -0,0 +1,45 @@ +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: webview_flutter_ohos +description: A Flutter plugin that provides a WebView widget on Ohos. +repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 +version: 3.16.2 + +environment: + sdk: ^3.2.0 + flutter: ">=3.16.0" + +flutter: + plugin: + implements: webview_flutter + platforms: + ohos: + package: io.flutter.plugins.webviewflutter + pluginClass: WebViewFlutterPlugin + dartPluginClass: OhosWebViewPlatform + +dependencies: + flutter: + sdk: flutter + webview_flutter_platform_interface: + git: + url: https://gitee.com/openharmony-sig/flutter_packages.git + path: packages/webview_flutter/webview_flutter_platform_interface + +dev_dependencies: + build_runner: ^2.1.4 + flutter_test: + sdk: flutter + pigeon: ^11.0.0 \ No newline at end of file