diff --git a/example/integration_test/chrome_safari_browser/open_and_close.dart b/example/integration_test/chrome_safari_browser/open_and_close.dart index b29f5aca..0d93396f 100644 --- a/example/integration_test/chrome_safari_browser/open_and_close.dart +++ b/example/integration_test/chrome_safari_browser/open_and_close.dart @@ -40,7 +40,7 @@ void openAndClose() { activityButton: ActivityButton( templateImage: UIImage(systemName: "sun.max"), extensionIdentifier: - "com.pichillilorenzo.flutter-inappwebview-example1.test"))); + "com.pichillilorenzo.flutter-inappwebview-ios-example.test"))); await chromeSafariBrowser.opened.future; expect(chromeSafariBrowser.isOpened(), true); expect(() async { diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index b34f61c2..652b1176 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -356,7 +356,7 @@ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/OrderedSet/OrderedSet.framework", "${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework", - "${BUILT_PRODUCTS_DIR}/flutter_inappwebview/flutter_inappwebview.framework", + "${BUILT_PRODUCTS_DIR}/flutter_inappwebview_ios/flutter_inappwebview_ios.framework", "${BUILT_PRODUCTS_DIR}/integration_test/integration_test.framework", "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework", @@ -365,7 +365,7 @@ outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OrderedSet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/integration_test.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework", @@ -460,7 +460,7 @@ MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example1.test"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-ios-example.test"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -497,7 +497,7 @@ ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example1.test"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-ios-example.test"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; @@ -646,7 +646,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example1"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-ios-example"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -681,7 +681,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-example1"; + PRODUCT_BUNDLE_IDENTIFIER = "com.pichillilorenzo.flutter-inappwebview-ios-example"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/flutter_inappwebview_android/lib/src/inappwebview_platform.dart b/flutter_inappwebview_android/lib/src/inappwebview_platform.dart index cf497e38..5d3a9b07 100644 --- a/flutter_inappwebview_android/lib/src/inappwebview_platform.dart +++ b/flutter_inappwebview_android/lib/src/inappwebview_platform.dart @@ -1,4 +1,3 @@ -import 'package:flutter_inappwebview_android/src/print_job/main.dart'; import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; import 'chrome_safari_browser/chrome_safari_browser.dart'; @@ -7,6 +6,7 @@ import 'http_auth_credentials_database.dart'; import 'find_interaction/main.dart'; import 'in_app_browser/in_app_browser.dart'; import 'in_app_webview/main.dart'; +import 'print_job/main.dart'; import 'pull_to_refresh/main.dart'; import 'web_message/main.dart'; import 'web_storage/main.dart'; @@ -17,9 +17,9 @@ import 'tracing_controller.dart'; import 'webview_asset_loader.dart'; import 'webview_feature.dart' as wv; -/// Implementation of [WebViewPlatform] using the WebKit API. +/// Implementation of [InAppWebViewPlatform] using the WebKit API. class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { - /// Registers this class as the default instance of [WebViewPlatform]. + /// Registers this class as the default instance of [InAppWebViewPlatform]. static void registerWith() { InAppWebViewPlatform.instance = AndroidInAppWebViewPlatform(); } @@ -28,6 +28,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [CookieManager] in `flutter_inappwebview` instead. + @override AndroidCookieManager createPlatformCookieManager( PlatformCookieManagerCreationParams params, ) { @@ -38,6 +39,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InAppWebViewController] in `flutter_inappwebview` instead. + @override AndroidInAppWebViewController createPlatformInAppWebViewController( PlatformInAppWebViewControllerCreationParams params, ) { @@ -48,6 +50,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InAppWebViewController] in `flutter_inappwebview` instead. + @override AndroidInAppWebViewController createPlatformInAppWebViewControllerStatic() { return AndroidInAppWebViewController.static(); } @@ -56,6 +59,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InAppWebView] in `flutter_inappwebview` instead. + @override AndroidInAppWebViewWidget createPlatformInAppWebViewWidget( PlatformInAppWebViewWidgetCreationParams params, ) { @@ -66,6 +70,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [FindInteractionController] in `flutter_inappwebview` instead. + @override AndroidFindInteractionController createPlatformFindInteractionController( PlatformFindInteractionControllerCreationParams params, ) { @@ -76,6 +81,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [PrintJobController] in `flutter_inappwebview` instead. + @override AndroidPrintJobController createPlatformPrintJobController( PlatformPrintJobControllerCreationParams params, ) { @@ -86,6 +92,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [PullToRefreshController] in `flutter_inappwebview` instead. + @override AndroidPullToRefreshController createPlatformPullToRefreshController( PlatformPullToRefreshControllerCreationParams params, ) { @@ -96,6 +103,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebMessageChannel] in `flutter_inappwebview` instead. + @override AndroidWebMessageChannel createPlatformWebMessageChannel( PlatformWebMessageChannelCreationParams params, ) { @@ -106,6 +114,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebMessageChannel] in `flutter_inappwebview` instead. + @override AndroidWebMessageChannel createPlatformWebMessageChannelStatic() { return AndroidWebMessageChannel.static(); } @@ -114,6 +123,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebMessageListener] in `flutter_inappwebview` instead. + @override AndroidWebMessageListener createPlatformWebMessageListener( PlatformWebMessageListenerCreationParams params, ) { @@ -124,6 +134,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [JavaScriptReplyProxy] in `flutter_inappwebview` instead. + @override AndroidJavaScriptReplyProxy createPlatformJavaScriptReplyProxy( PlatformJavaScriptReplyProxyCreationParams params, ) { @@ -134,6 +145,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebMessagePort] in `flutter_inappwebview` instead. + @override AndroidWebMessagePort createPlatformWebMessagePort( PlatformWebMessagePortCreationParams params, ) { @@ -144,6 +156,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [AndroidWebStorage] in `flutter_inappwebview` instead. + @override AndroidWebStorage createPlatformWebStorage( PlatformWebStorageCreationParams params, ) { @@ -154,6 +167,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [AndroidLocalStorage] in `flutter_inappwebview` instead. + @override AndroidLocalStorage createPlatformLocalStorage( PlatformLocalStorageCreationParams params, ) { @@ -164,6 +178,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [PlatformSessionStorage] in `flutter_inappwebview` instead. + @override AndroidSessionStorage createPlatformSessionStorage( PlatformSessionStorageCreationParams params, ) { @@ -174,6 +189,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [HeadlessInAppWebView] in `flutter_inappwebview` instead. + @override AndroidHeadlessInAppWebView createPlatformHeadlessInAppWebView( PlatformHeadlessInAppWebViewCreationParams params, ) { @@ -184,6 +200,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [HttpAuthCredentialDatabase] in `flutter_inappwebview` instead. + @override AndroidHttpAuthCredentialDatabase createPlatformHttpAuthCredentialDatabase( PlatformHttpAuthCredentialDatabaseCreationParams params, ) { @@ -194,6 +211,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InAppBrowser] in `flutter_inappwebview` instead. + @override AndroidInAppBrowser createPlatformInAppBrowser( PlatformInAppBrowserCreationParams params, ) { @@ -204,6 +222,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InAppBrowser] in `flutter_inappwebview` instead. + @override AndroidInAppBrowser createPlatformInAppBrowserStatic() { return AndroidInAppBrowser.static(); } @@ -212,6 +231,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ProcessGlobalConfig] in `flutter_inappwebview` instead. + @override AndroidProcessGlobalConfig createPlatformProcessGlobalConfig( PlatformProcessGlobalConfigCreationParams params, ) { @@ -222,6 +242,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ProxyController] in `flutter_inappwebview` instead. + @override AndroidProxyController createPlatformProxyController( PlatformProxyControllerCreationParams params, ) { @@ -232,6 +253,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ServiceWorkerController] in `flutter_inappwebview` instead. + @override AndroidServiceWorkerController createPlatformServiceWorkerController( PlatformServiceWorkerControllerCreationParams params, ) { @@ -242,6 +264,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ServiceWorkerController] in `flutter_inappwebview` instead. + @override AndroidServiceWorkerController createPlatformServiceWorkerControllerStatic() { return AndroidServiceWorkerController.static(); } @@ -250,6 +273,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [TracingController] in `flutter_inappwebview` instead. + @override AndroidTracingController createPlatformTracingController( PlatformTracingControllerCreationParams params, ) { @@ -260,6 +284,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [AssetsPathHandler] in `flutter_inappwebview` instead. + @override AndroidAssetsPathHandler createPlatformAssetsPathHandler( PlatformAssetsPathHandlerCreationParams params, ) { @@ -270,6 +295,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ResourcesPathHandler] in `flutter_inappwebview` instead. + @override AndroidResourcesPathHandler createPlatformResourcesPathHandler( PlatformResourcesPathHandlerCreationParams params, ) { @@ -280,6 +306,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [InternalStoragePathHandler] in `flutter_inappwebview` instead. + @override AndroidInternalStoragePathHandler createPlatformInternalStoragePathHandler( PlatformInternalStoragePathHandlerCreationParams params, ) { @@ -290,6 +317,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebViewFeature] in `flutter_inappwebview` instead. + @override wv.AndroidWebViewFeature createPlatformWebViewFeature( PlatformWebViewFeatureCreationParams params, ) { @@ -300,6 +328,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebViewFeature] in `flutter_inappwebview` instead. + @override wv.AndroidWebViewFeature createPlatformWebViewFeatureStatic() { return wv.AndroidWebViewFeature.static(); } @@ -308,6 +337,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ChromeSafariBrowser] in `flutter_inappwebview` instead. + @override AndroidChromeSafariBrowser createPlatformChromeSafariBrowser( PlatformChromeSafariBrowserCreationParams params, ) { @@ -318,6 +348,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [ChromeSafariBrowser] in `flutter_inappwebview` instead. + @override AndroidChromeSafariBrowser createPlatformChromeSafariBrowserStatic() { return AndroidChromeSafariBrowser.static(); } @@ -326,6 +357,7 @@ class AndroidInAppWebViewPlatform extends InAppWebViewPlatform { /// /// This function should only be called by the app-facing package. /// Look at using [WebStorageManager] in `flutter_inappwebview` instead. + @override AndroidWebStorageManager createPlatformWebStorageManager( PlatformWebStorageManagerCreationParams params) { return AndroidWebStorageManager(params); diff --git a/flutter_inappwebview_ios/.gitignore b/flutter_inappwebview_ios/.gitignore new file mode 100644 index 00000000..96486fd9 --- /dev/null +++ b/flutter_inappwebview_ios/.gitignore @@ -0,0 +1,30 @@ +# 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 +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/flutter_inappwebview_ios/.metadata b/flutter_inappwebview_ios/.metadata new file mode 100644 index 00000000..1d00c64b --- /dev/null +++ b/flutter_inappwebview_ios/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e" + channel: "stable" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + - platform: ios + create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter_inappwebview_ios/CHANGELOG.md b/flutter_inappwebview_ios/CHANGELOG.md new file mode 100644 index 00000000..41cc7d81 --- /dev/null +++ b/flutter_inappwebview_ios/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/flutter_inappwebview_ios/LICENSE b/flutter_inappwebview_ios/LICENSE new file mode 100644 index 00000000..ba75c69f --- /dev/null +++ b/flutter_inappwebview_ios/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/flutter_inappwebview_ios/README.md b/flutter_inappwebview_ios/README.md new file mode 100644 index 00000000..18e5ad26 --- /dev/null +++ b/flutter_inappwebview_ios/README.md @@ -0,0 +1,15 @@ +# flutter_inappwebview_ios + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/developing-packages/), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/flutter_inappwebview_ios/analysis_options.yaml b/flutter_inappwebview_ios/analysis_options.yaml new file mode 100644 index 00000000..c98f8e5d --- /dev/null +++ b/flutter_inappwebview_ios/analysis_options.yaml @@ -0,0 +1,13 @@ +include: package:flutter_lints/flutter.yaml + +linter: + rules: + constant_identifier_names: ignore + deprecated_member_use_from_same_package: ignore + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options +analyzer: + errors: + deprecated_member_use: ignore + deprecated_member_use_from_same_package: ignore diff --git a/flutter_inappwebview_ios/example/.gitignore b/flutter_inappwebview_ios/example/.gitignore new file mode 100644 index 00000000..24476c5d --- /dev/null +++ b/flutter_inappwebview_ios/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/flutter_inappwebview_ios/example/README.md b/flutter_inappwebview_ios/example/README.md new file mode 100644 index 00000000..972be4ed --- /dev/null +++ b/flutter_inappwebview_ios/example/README.md @@ -0,0 +1,16 @@ +# flutter_inappwebview_ios_example + +Demonstrates how to use the flutter_inappwebview_ios plugin. + +## 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/flutter_inappwebview_ios/example/analysis_options.yaml b/flutter_inappwebview_ios/example/analysis_options.yaml new file mode 100644 index 00000000..0d290213 --- /dev/null +++ b/flutter_inappwebview_ios/example/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/ios/Assets/.gitkeep b/flutter_inappwebview_ios/example/integration_test/plugin_integration_test.dart old mode 100755 new mode 100644 similarity index 100% rename from ios/Assets/.gitkeep rename to flutter_inappwebview_ios/example/integration_test/plugin_integration_test.dart diff --git a/flutter_inappwebview_ios/example/ios/.gitignore b/flutter_inappwebview_ios/example/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/flutter_inappwebview_ios/example/ios/Flutter/AppFrameworkInfo.plist b/flutter_inappwebview_ios/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..9625e105 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/flutter_inappwebview_ios/example/ios/Flutter/Debug.xcconfig b/flutter_inappwebview_ios/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..ec97fc6f --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_inappwebview_ios/example/ios/Flutter/Release.xcconfig b/flutter_inappwebview_ios/example/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..c4855bfe --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/flutter_inappwebview_ios/example/ios/Podfile b/flutter_inappwebview_ios/example/ios/Podfile new file mode 100644 index 00000000..fdcc671e --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.pbxproj b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..123bf9e5 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,614 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.pichillilorenzo.flutterInappwebviewIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..87131a09 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner/AppDelegate.swift b/flutter_inappwebview_ios/example/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..70693e4a --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d36b1fab --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..dc9ada47 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..7353c41e Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..797d452e Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..6ed2d933 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..4cd7b009 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..fe730945 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..321773cd Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..797d452e Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..502f463a Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..0ec30343 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..0ec30343 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..e9f5fea2 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..84ac32ae Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..8953cba0 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..0467bf12 Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 00000000..9da19eac Binary files /dev/null and b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/Main.storyboard b/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner/Info.plist b/flutter_inappwebview_ios/example/ios/Runner/Info.plist new file mode 100644 index 00000000..5aceee7b --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Flutter Inappwebview Ios + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutter_inappwebview_ios_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/flutter_inappwebview_ios/example/ios/Runner/Runner-Bridging-Header.h b/flutter_inappwebview_ios/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/flutter_inappwebview_ios/example/ios/RunnerTests/RunnerTests.swift b/flutter_inappwebview_ios/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..3fff3af3 --- /dev/null +++ b/flutter_inappwebview_ios/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,26 @@ +import Flutter +import UIKit +import XCTest + +@testable import flutter_inappwebview_ios + +// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. +// +// See https://developer.apple.com/documentation/xctest for more information about using XCTest. + +class RunnerTests: XCTestCase { + + func testGetPlatformVersion() { + let plugin = FlutterInappwebviewIosPlugin() + + let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) + + let resultExpectation = expectation(description: "result block must be called.") + plugin.handle(call) { result in + XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) + resultExpectation.fulfill() + } + waitForExpectations(timeout: 1) + } + +} diff --git a/flutter_inappwebview_ios/example/lib/main.dart b/flutter_inappwebview_ios/example/lib/main.dart new file mode 100644 index 00000000..e69de29b diff --git a/flutter_inappwebview_ios/example/pubspec.lock b/flutter_inappwebview_ios/example/pubspec.lock new file mode 100644 index 00000000..caa8a08a --- /dev/null +++ b/flutter_inappwebview_ios/example/pubspec.lock @@ -0,0 +1,282 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_inappwebview_internal_annotations: + dependency: transitive + description: + name: flutter_inappwebview_internal_annotations + sha256: "5f80fd30e208ddded7dbbcd0d569e7995f9f63d45ea3f548d8dd4c0b473fb4c8" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_inappwebview_ios: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "0.0.1" + flutter_inappwebview_platform_interface: + dependency: transitive + description: + path: "../../flutter_inappwebview_platform_interface" + relative: true + source: path + version: "0.0.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + url: "https://pub.dev" + source: hosted + version: "2.1.7" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + url: "https://pub.dev" + source: hosted + version: "11.7.1" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + url: "https://pub.dev" + source: hosted + version: "3.0.2" +sdks: + dart: ">=3.1.4 <4.0.0" + flutter: ">=3.0.0" diff --git a/flutter_inappwebview_ios/example/pubspec.yaml b/flutter_inappwebview_ios/example/pubspec.yaml new file mode 100644 index 00000000..3eef0f0a --- /dev/null +++ b/flutter_inappwebview_ios/example/pubspec.yaml @@ -0,0 +1,85 @@ +name: flutter_inappwebview_ios_example +description: Demonstrates how to use the flutter_inappwebview_ios plugin. +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: '>=3.1.4 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + flutter_inappwebview_ios: + # When depending on this package from a real application you should use: + # flutter_inappwebview_ios: ^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: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/flutter_inappwebview_ios/example/test/widget_test.dart b/flutter_inappwebview_ios/example/test/widget_test.dart new file mode 100644 index 00000000..e69de29b diff --git a/ios/.gitignore b/flutter_inappwebview_ios/ios/.gitignore similarity index 100% rename from ios/.gitignore rename to flutter_inappwebview_ios/ios/.gitignore diff --git a/flutter_inappwebview_ios/ios/Assets/.gitkeep b/flutter_inappwebview_ios/ios/Assets/.gitkeep new file mode 100755 index 00000000..e69de29b diff --git a/ios/Classes/CredentialDatabase.swift b/flutter_inappwebview_ios/ios/Classes/CredentialDatabase.swift similarity index 100% rename from ios/Classes/CredentialDatabase.swift rename to flutter_inappwebview_ios/ios/Classes/CredentialDatabase.swift diff --git a/ios/Classes/FindInteraction/FindInteractionChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionChannelDelegate.swift similarity index 100% rename from ios/Classes/FindInteraction/FindInteractionChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionChannelDelegate.swift diff --git a/ios/Classes/FindInteraction/FindInteractionController.swift b/flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionController.swift similarity index 100% rename from ios/Classes/FindInteraction/FindInteractionController.swift rename to flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionController.swift diff --git a/ios/Classes/FindInteraction/FindInteractionSettings.swift b/flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionSettings.swift similarity index 100% rename from ios/Classes/FindInteraction/FindInteractionSettings.swift rename to flutter_inappwebview_ios/ios/Classes/FindInteraction/FindInteractionSettings.swift diff --git a/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift b/flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift similarity index 100% rename from ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift rename to flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebView.swift diff --git a/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebViewManager.swift b/flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebViewManager.swift similarity index 100% rename from ios/Classes/HeadlessInAppWebView/HeadlessInAppWebViewManager.swift rename to flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessInAppWebViewManager.swift diff --git a/ios/Classes/HeadlessInAppWebView/HeadlessWebViewChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessWebViewChannelDelegate.swift similarity index 100% rename from ios/Classes/HeadlessInAppWebView/HeadlessWebViewChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/HeadlessInAppWebView/HeadlessWebViewChannelDelegate.swift diff --git a/ios/Classes/ISettings.swift b/flutter_inappwebview_ios/ios/Classes/ISettings.swift similarity index 100% rename from ios/Classes/ISettings.swift rename to flutter_inappwebview_ios/ios/Classes/ISettings.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserChannelDelegate.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserChannelDelegate.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserDelegate.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserDelegate.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserManager.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserManager.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserManager.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserManager.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserNavigationController.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserNavigationController.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserNavigationController.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserNavigationController.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserSettings.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserSettings.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserSettings.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserSettings.swift diff --git a/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift b/flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift similarity index 100% rename from ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift rename to flutter_inappwebview_ios/ios/Classes/InAppBrowser/InAppBrowserWebViewController.swift diff --git a/ios/Classes/InAppWebView/ContextMenuSettings.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/ContextMenuSettings.swift similarity index 100% rename from ios/Classes/InAppWebView/ContextMenuSettings.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/ContextMenuSettings.swift diff --git a/ios/Classes/InAppWebView/CustomSchemeHandler.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/CustomSchemeHandler.swift similarity index 100% rename from ios/Classes/InAppWebView/CustomSchemeHandler.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/CustomSchemeHandler.swift diff --git a/ios/Classes/InAppWebView/FlutterWebViewController.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/FlutterWebViewController.swift similarity index 100% rename from ios/Classes/InAppWebView/FlutterWebViewController.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/FlutterWebViewController.swift diff --git a/ios/Classes/InAppWebView/FlutterWebViewFactory.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/FlutterWebViewFactory.swift similarity index 100% rename from ios/Classes/InAppWebView/FlutterWebViewFactory.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/FlutterWebViewFactory.swift diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift similarity index 100% rename from ios/Classes/InAppWebView/InAppWebView.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift diff --git a/ios/Classes/InAppWebView/InAppWebViewManager.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewManager.swift similarity index 100% rename from ios/Classes/InAppWebView/InAppWebViewManager.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewManager.swift diff --git a/ios/Classes/InAppWebView/InAppWebViewSettings.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift similarity index 100% rename from ios/Classes/InAppWebView/InAppWebViewSettings.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebViewSettings.swift diff --git a/ios/Classes/InAppWebView/WebMessage/WebMessageChannel.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageChannel.swift similarity index 100% rename from ios/Classes/InAppWebView/WebMessage/WebMessageChannel.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageChannel.swift diff --git a/ios/Classes/InAppWebView/WebMessage/WebMessageChannelChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageChannelChannelDelegate.swift similarity index 100% rename from ios/Classes/InAppWebView/WebMessage/WebMessageChannelChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageChannelChannelDelegate.swift diff --git a/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift similarity index 100% rename from ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageListener.swift diff --git a/ios/Classes/InAppWebView/WebMessage/WebMessageListenerChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageListenerChannelDelegate.swift similarity index 100% rename from ios/Classes/InAppWebView/WebMessage/WebMessageListenerChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebMessage/WebMessageListenerChannelDelegate.swift diff --git a/ios/Classes/InAppWebView/WebViewChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift similarity index 100% rename from ios/Classes/InAppWebView/WebViewChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift diff --git a/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift similarity index 100% rename from ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift rename to flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift diff --git a/ios/Classes/InAppWebViewFlutterPlugin.h b/flutter_inappwebview_ios/ios/Classes/InAppWebViewFlutterPlugin.h similarity index 100% rename from ios/Classes/InAppWebViewFlutterPlugin.h rename to flutter_inappwebview_ios/ios/Classes/InAppWebViewFlutterPlugin.h diff --git a/ios/Classes/InAppWebViewFlutterPlugin.m b/flutter_inappwebview_ios/ios/Classes/InAppWebViewFlutterPlugin.m similarity index 86% rename from ios/Classes/InAppWebViewFlutterPlugin.m rename to flutter_inappwebview_ios/ios/Classes/InAppWebViewFlutterPlugin.m index c16dedb4..adcf1123 100755 --- a/ios/Classes/InAppWebViewFlutterPlugin.m +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebViewFlutterPlugin.m @@ -16,13 +16,13 @@ */ #import "InAppWebViewFlutterPlugin.h" -#if __has_include() -#import +#if __has_include() +#import #else // Support project import fallback if the generated compatibility header // is not copied when this plugin is created as a library. // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 -#import "flutter_inappwebview-Swift.h" +#import "flutter_inappwebview_ios-Swift.h" #endif @implementation InAppWebViewFlutterPlugin : NSObject diff --git a/ios/Classes/LeakAvoider.swift b/flutter_inappwebview_ios/ios/Classes/LeakAvoider.swift similarity index 100% rename from ios/Classes/LeakAvoider.swift rename to flutter_inappwebview_ios/ios/Classes/LeakAvoider.swift diff --git a/ios/Classes/MyCookieManager.swift b/flutter_inappwebview_ios/ios/Classes/MyCookieManager.swift similarity index 100% rename from ios/Classes/MyCookieManager.swift rename to flutter_inappwebview_ios/ios/Classes/MyCookieManager.swift diff --git a/ios/Classes/MyWebStorageManager.swift b/flutter_inappwebview_ios/ios/Classes/MyWebStorageManager.swift similarity index 100% rename from ios/Classes/MyWebStorageManager.swift rename to flutter_inappwebview_ios/ios/Classes/MyWebStorageManager.swift diff --git a/ios/Classes/PlatformUtil.swift b/flutter_inappwebview_ios/ios/Classes/PlatformUtil.swift similarity index 100% rename from ios/Classes/PlatformUtil.swift rename to flutter_inappwebview_ios/ios/Classes/PlatformUtil.swift diff --git a/ios/Classes/PluginScriptsJS/CallAsyncJavaScriptBelowIOS14WrapperJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/CallAsyncJavaScriptBelowIOS14WrapperJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/CallAsyncJavaScriptBelowIOS14WrapperJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/CallAsyncJavaScriptBelowIOS14WrapperJS.swift diff --git a/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/ConsoleLogJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/ConsoleLogJS.swift diff --git a/ios/Classes/PluginScriptsJS/EnableViewportScaleJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/EnableViewportScaleJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/EnableViewportScaleJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/EnableViewportScaleJS.swift diff --git a/ios/Classes/PluginScriptsJS/FindElementsAtPointJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/FindElementsAtPointJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/FindElementsAtPointJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/FindElementsAtPointJS.swift diff --git a/ios/Classes/PluginScriptsJS/FindTextHighlightJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/FindTextHighlightJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/FindTextHighlightJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/FindTextHighlightJS.swift diff --git a/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptAjaxRequestJS.swift diff --git a/ios/Classes/PluginScriptsJS/InterceptFetchRequestJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptFetchRequestJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/InterceptFetchRequestJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/InterceptFetchRequestJS.swift diff --git a/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift diff --git a/ios/Classes/PluginScriptsJS/LastTouchedAnchorOrImageJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/LastTouchedAnchorOrImageJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/LastTouchedAnchorOrImageJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/LastTouchedAnchorOrImageJS.swift diff --git a/ios/Classes/PluginScriptsJS/OnLoadResourceJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnLoadResourceJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/OnLoadResourceJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnLoadResourceJS.swift diff --git a/ios/Classes/PluginScriptsJS/OnWindowBlurEventJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnWindowBlurEventJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/OnWindowBlurEventJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnWindowBlurEventJS.swift diff --git a/ios/Classes/PluginScriptsJS/OnWindowFocusEventJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnWindowFocusEventJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/OnWindowFocusEventJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OnWindowFocusEventJS.swift diff --git a/ios/Classes/PluginScriptsJS/OriginalViewPortMetaTagContentJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OriginalViewPortMetaTagContentJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/OriginalViewPortMetaTagContentJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/OriginalViewPortMetaTagContentJS.swift diff --git a/ios/Classes/PluginScriptsJS/PluginScriptsUtil.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PluginScriptsUtil.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/PluginScriptsUtil.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PluginScriptsUtil.swift diff --git a/ios/Classes/PluginScriptsJS/PrintJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PrintJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/PrintJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PrintJS.swift diff --git a/ios/Classes/PluginScriptsJS/PromisePolyfillJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PromisePolyfillJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/PromisePolyfillJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/PromisePolyfillJS.swift diff --git a/ios/Classes/PluginScriptsJS/SupportZoomJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/SupportZoomJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/SupportZoomJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/SupportZoomJS.swift diff --git a/ios/Classes/PluginScriptsJS/WebMessageChannelJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WebMessageChannelJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/WebMessageChannelJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WebMessageChannelJS.swift diff --git a/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift diff --git a/ios/Classes/PluginScriptsJS/WindowIdJS.swift b/flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WindowIdJS.swift similarity index 100% rename from ios/Classes/PluginScriptsJS/WindowIdJS.swift rename to flutter_inappwebview_ios/ios/Classes/PluginScriptsJS/WindowIdJS.swift diff --git a/ios/Classes/PrintJob/CustomUIPrintPageRenderer.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/CustomUIPrintPageRenderer.swift similarity index 100% rename from ios/Classes/PrintJob/CustomUIPrintPageRenderer.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/CustomUIPrintPageRenderer.swift diff --git a/ios/Classes/PrintJob/PrintAttributes.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintAttributes.swift similarity index 100% rename from ios/Classes/PrintJob/PrintAttributes.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintAttributes.swift diff --git a/ios/Classes/PrintJob/PrintJobChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobChannelDelegate.swift similarity index 100% rename from ios/Classes/PrintJob/PrintJobChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobChannelDelegate.swift diff --git a/ios/Classes/PrintJob/PrintJobController.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobController.swift similarity index 100% rename from ios/Classes/PrintJob/PrintJobController.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobController.swift diff --git a/ios/Classes/PrintJob/PrintJobInfo.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobInfo.swift similarity index 100% rename from ios/Classes/PrintJob/PrintJobInfo.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobInfo.swift diff --git a/ios/Classes/PrintJob/PrintJobManager.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobManager.swift similarity index 100% rename from ios/Classes/PrintJob/PrintJobManager.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobManager.swift diff --git a/ios/Classes/PrintJob/PrintJobSettings.swift b/flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobSettings.swift similarity index 100% rename from ios/Classes/PrintJob/PrintJobSettings.swift rename to flutter_inappwebview_ios/ios/Classes/PrintJob/PrintJobSettings.swift diff --git a/ios/Classes/PullToRefresh/PullToRefreshChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshChannelDelegate.swift similarity index 100% rename from ios/Classes/PullToRefresh/PullToRefreshChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshChannelDelegate.swift diff --git a/ios/Classes/PullToRefresh/PullToRefreshControl.swift b/flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshControl.swift similarity index 100% rename from ios/Classes/PullToRefresh/PullToRefreshControl.swift rename to flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshControl.swift diff --git a/ios/Classes/PullToRefresh/PullToRefreshDelegate.swift b/flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshDelegate.swift similarity index 100% rename from ios/Classes/PullToRefresh/PullToRefreshDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshDelegate.swift diff --git a/ios/Classes/PullToRefresh/PullToRefreshSettings.swift b/flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshSettings.swift similarity index 100% rename from ios/Classes/PullToRefresh/PullToRefreshSettings.swift rename to flutter_inappwebview_ios/ios/Classes/PullToRefresh/PullToRefreshSettings.swift diff --git a/ios/Classes/SafariViewController/ChromeSafariBrowserManager.swift b/flutter_inappwebview_ios/ios/Classes/SafariViewController/ChromeSafariBrowserManager.swift similarity index 100% rename from ios/Classes/SafariViewController/ChromeSafariBrowserManager.swift rename to flutter_inappwebview_ios/ios/Classes/SafariViewController/ChromeSafariBrowserManager.swift diff --git a/ios/Classes/SafariViewController/CustomUIActivity.swift b/flutter_inappwebview_ios/ios/Classes/SafariViewController/CustomUIActivity.swift similarity index 100% rename from ios/Classes/SafariViewController/CustomUIActivity.swift rename to flutter_inappwebview_ios/ios/Classes/SafariViewController/CustomUIActivity.swift diff --git a/ios/Classes/SafariViewController/SafariBrowserSettings.swift b/flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariBrowserSettings.swift similarity index 100% rename from ios/Classes/SafariViewController/SafariBrowserSettings.swift rename to flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariBrowserSettings.swift diff --git a/ios/Classes/SafariViewController/SafariViewController.swift b/flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariViewController.swift similarity index 100% rename from ios/Classes/SafariViewController/SafariViewController.swift rename to flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariViewController.swift diff --git a/ios/Classes/SafariViewController/SafariViewControllerChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariViewControllerChannelDelegate.swift similarity index 100% rename from ios/Classes/SafariViewController/SafariViewControllerChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/SafariViewController/SafariViewControllerChannelDelegate.swift diff --git a/ios/Classes/SwiftFlutterPlugin.swift b/flutter_inappwebview_ios/ios/Classes/SwiftFlutterPlugin.swift similarity index 100% rename from ios/Classes/SwiftFlutterPlugin.swift rename to flutter_inappwebview_ios/ios/Classes/SwiftFlutterPlugin.swift diff --git a/ios/Classes/Types/ActivityButton.swift b/flutter_inappwebview_ios/ios/Classes/Types/ActivityButton.swift similarity index 100% rename from ios/Classes/Types/ActivityButton.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ActivityButton.swift diff --git a/ios/Classes/Types/BaseCallbackResult.swift b/flutter_inappwebview_ios/ios/Classes/Types/BaseCallbackResult.swift similarity index 100% rename from ios/Classes/Types/BaseCallbackResult.swift rename to flutter_inappwebview_ios/ios/Classes/Types/BaseCallbackResult.swift diff --git a/ios/Classes/Types/CGRect.swift b/flutter_inappwebview_ios/ios/Classes/Types/CGRect.swift similarity index 100% rename from ios/Classes/Types/CGRect.swift rename to flutter_inappwebview_ios/ios/Classes/Types/CGRect.swift diff --git a/ios/Classes/Types/CGSize.swift b/flutter_inappwebview_ios/ios/Classes/Types/CGSize.swift similarity index 100% rename from ios/Classes/Types/CGSize.swift rename to flutter_inappwebview_ios/ios/Classes/Types/CGSize.swift diff --git a/ios/Classes/Types/CallbackResult.swift b/flutter_inappwebview_ios/ios/Classes/Types/CallbackResult.swift similarity index 100% rename from ios/Classes/Types/CallbackResult.swift rename to flutter_inappwebview_ios/ios/Classes/Types/CallbackResult.swift diff --git a/ios/Classes/Types/ChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/Types/ChannelDelegate.swift similarity index 100% rename from ios/Classes/Types/ChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ChannelDelegate.swift diff --git a/ios/Classes/Types/ClientCertChallenge.swift b/flutter_inappwebview_ios/ios/Classes/Types/ClientCertChallenge.swift similarity index 100% rename from ios/Classes/Types/ClientCertChallenge.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ClientCertChallenge.swift diff --git a/ios/Classes/Types/ClientCertResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/ClientCertResponse.swift similarity index 100% rename from ios/Classes/Types/ClientCertResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ClientCertResponse.swift diff --git a/ios/Classes/Types/CreateWindowAction.swift b/flutter_inappwebview_ios/ios/Classes/Types/CreateWindowAction.swift similarity index 100% rename from ios/Classes/Types/CreateWindowAction.swift rename to flutter_inappwebview_ios/ios/Classes/Types/CreateWindowAction.swift diff --git a/ios/Classes/Types/CustomSchemeResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/CustomSchemeResponse.swift similarity index 100% rename from ios/Classes/Types/CustomSchemeResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/CustomSchemeResponse.swift diff --git a/ios/Classes/Types/Disposable.swift b/flutter_inappwebview_ios/ios/Classes/Types/Disposable.swift similarity index 100% rename from ios/Classes/Types/Disposable.swift rename to flutter_inappwebview_ios/ios/Classes/Types/Disposable.swift diff --git a/ios/Classes/Types/DownloadStartRequest.swift b/flutter_inappwebview_ios/ios/Classes/Types/DownloadStartRequest.swift similarity index 100% rename from ios/Classes/Types/DownloadStartRequest.swift rename to flutter_inappwebview_ios/ios/Classes/Types/DownloadStartRequest.swift diff --git a/ios/Classes/Types/FlutterMethodCallDelegate.swift b/flutter_inappwebview_ios/ios/Classes/Types/FlutterMethodCallDelegate.swift similarity index 100% rename from ios/Classes/Types/FlutterMethodCallDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/Types/FlutterMethodCallDelegate.swift diff --git a/ios/Classes/Types/FlutterMethodChannel.swift b/flutter_inappwebview_ios/ios/Classes/Types/FlutterMethodChannel.swift similarity index 100% rename from ios/Classes/Types/FlutterMethodChannel.swift rename to flutter_inappwebview_ios/ios/Classes/Types/FlutterMethodChannel.swift diff --git a/ios/Classes/Types/HitTestResult.swift b/flutter_inappwebview_ios/ios/Classes/Types/HitTestResult.swift similarity index 100% rename from ios/Classes/Types/HitTestResult.swift rename to flutter_inappwebview_ios/ios/Classes/Types/HitTestResult.swift diff --git a/ios/Classes/Types/HttpAuthResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/HttpAuthResponse.swift similarity index 100% rename from ios/Classes/Types/HttpAuthResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/HttpAuthResponse.swift diff --git a/ios/Classes/Types/HttpAuthenticationChallenge.swift b/flutter_inappwebview_ios/ios/Classes/Types/HttpAuthenticationChallenge.swift similarity index 100% rename from ios/Classes/Types/HttpAuthenticationChallenge.swift rename to flutter_inappwebview_ios/ios/Classes/Types/HttpAuthenticationChallenge.swift diff --git a/ios/Classes/Types/InAppBrowserMenuItem.swift b/flutter_inappwebview_ios/ios/Classes/Types/InAppBrowserMenuItem.swift similarity index 100% rename from ios/Classes/Types/InAppBrowserMenuItem.swift rename to flutter_inappwebview_ios/ios/Classes/Types/InAppBrowserMenuItem.swift diff --git a/ios/Classes/Types/JsAlertResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/JsAlertResponse.swift similarity index 100% rename from ios/Classes/Types/JsAlertResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/JsAlertResponse.swift diff --git a/ios/Classes/Types/JsConfirmResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/JsConfirmResponse.swift similarity index 100% rename from ios/Classes/Types/JsConfirmResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/JsConfirmResponse.swift diff --git a/ios/Classes/Types/JsPromptResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/JsPromptResponse.swift similarity index 100% rename from ios/Classes/Types/JsPromptResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/JsPromptResponse.swift diff --git a/ios/Classes/Types/MethodChannelResult.swift b/flutter_inappwebview_ios/ios/Classes/Types/MethodChannelResult.swift similarity index 100% rename from ios/Classes/Types/MethodChannelResult.swift rename to flutter_inappwebview_ios/ios/Classes/Types/MethodChannelResult.swift diff --git a/ios/Classes/Types/NSAttributedString.swift b/flutter_inappwebview_ios/ios/Classes/Types/NSAttributedString.swift similarity index 100% rename from ios/Classes/Types/NSAttributedString.swift rename to flutter_inappwebview_ios/ios/Classes/Types/NSAttributedString.swift diff --git a/ios/Classes/Types/PermissionRequest.swift b/flutter_inappwebview_ios/ios/Classes/Types/PermissionRequest.swift similarity index 100% rename from ios/Classes/Types/PermissionRequest.swift rename to flutter_inappwebview_ios/ios/Classes/Types/PermissionRequest.swift diff --git a/ios/Classes/Types/PermissionResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/PermissionResponse.swift similarity index 100% rename from ios/Classes/Types/PermissionResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/PermissionResponse.swift diff --git a/ios/Classes/Types/PluginScript.swift b/flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift similarity index 100% rename from ios/Classes/Types/PluginScript.swift rename to flutter_inappwebview_ios/ios/Classes/Types/PluginScript.swift diff --git a/ios/Classes/Types/SecCertificate.swift b/flutter_inappwebview_ios/ios/Classes/Types/SecCertificate.swift similarity index 100% rename from ios/Classes/Types/SecCertificate.swift rename to flutter_inappwebview_ios/ios/Classes/Types/SecCertificate.swift diff --git a/ios/Classes/Types/ServerTrustAuthResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/ServerTrustAuthResponse.swift similarity index 100% rename from ios/Classes/Types/ServerTrustAuthResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ServerTrustAuthResponse.swift diff --git a/ios/Classes/Types/ServerTrustChallenge.swift b/flutter_inappwebview_ios/ios/Classes/Types/ServerTrustChallenge.swift similarity index 100% rename from ios/Classes/Types/ServerTrustChallenge.swift rename to flutter_inappwebview_ios/ios/Classes/Types/ServerTrustChallenge.swift diff --git a/ios/Classes/Types/Size2D.swift b/flutter_inappwebview_ios/ios/Classes/Types/Size2D.swift similarity index 100% rename from ios/Classes/Types/Size2D.swift rename to flutter_inappwebview_ios/ios/Classes/Types/Size2D.swift diff --git a/ios/Classes/Types/SslCertificate.swift b/flutter_inappwebview_ios/ios/Classes/Types/SslCertificate.swift similarity index 100% rename from ios/Classes/Types/SslCertificate.swift rename to flutter_inappwebview_ios/ios/Classes/Types/SslCertificate.swift diff --git a/ios/Classes/Types/SslError.swift b/flutter_inappwebview_ios/ios/Classes/Types/SslError.swift similarity index 100% rename from ios/Classes/Types/SslError.swift rename to flutter_inappwebview_ios/ios/Classes/Types/SslError.swift diff --git a/ios/Classes/Types/StringOrInt.swift b/flutter_inappwebview_ios/ios/Classes/Types/StringOrInt.swift similarity index 100% rename from ios/Classes/Types/StringOrInt.swift rename to flutter_inappwebview_ios/ios/Classes/Types/StringOrInt.swift diff --git a/ios/Classes/Types/UIColor.swift b/flutter_inappwebview_ios/ios/Classes/Types/UIColor.swift similarity index 100% rename from ios/Classes/Types/UIColor.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UIColor.swift diff --git a/ios/Classes/Types/UIEdgeInsets.swift b/flutter_inappwebview_ios/ios/Classes/Types/UIEdgeInsets.swift similarity index 100% rename from ios/Classes/Types/UIEdgeInsets.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UIEdgeInsets.swift diff --git a/ios/Classes/Types/UIEventAttribution.swift b/flutter_inappwebview_ios/ios/Classes/Types/UIEventAttribution.swift similarity index 100% rename from ios/Classes/Types/UIEventAttribution.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UIEventAttribution.swift diff --git a/ios/Classes/Types/UIFindSession.swift b/flutter_inappwebview_ios/ios/Classes/Types/UIFindSession.swift similarity index 100% rename from ios/Classes/Types/UIFindSession.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UIFindSession.swift diff --git a/ios/Classes/Types/UIImage.swift b/flutter_inappwebview_ios/ios/Classes/Types/UIImage.swift similarity index 100% rename from ios/Classes/Types/UIImage.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UIImage.swift diff --git a/ios/Classes/Types/URLAuthenticationChallenge.swift b/flutter_inappwebview_ios/ios/Classes/Types/URLAuthenticationChallenge.swift similarity index 100% rename from ios/Classes/Types/URLAuthenticationChallenge.swift rename to flutter_inappwebview_ios/ios/Classes/Types/URLAuthenticationChallenge.swift diff --git a/ios/Classes/Types/URLCredential.swift b/flutter_inappwebview_ios/ios/Classes/Types/URLCredential.swift similarity index 100% rename from ios/Classes/Types/URLCredential.swift rename to flutter_inappwebview_ios/ios/Classes/Types/URLCredential.swift diff --git a/ios/Classes/Types/URLProtectionSpace.swift b/flutter_inappwebview_ios/ios/Classes/Types/URLProtectionSpace.swift similarity index 100% rename from ios/Classes/Types/URLProtectionSpace.swift rename to flutter_inappwebview_ios/ios/Classes/Types/URLProtectionSpace.swift diff --git a/ios/Classes/Types/URLRequest.swift b/flutter_inappwebview_ios/ios/Classes/Types/URLRequest.swift similarity index 100% rename from ios/Classes/Types/URLRequest.swift rename to flutter_inappwebview_ios/ios/Classes/Types/URLRequest.swift diff --git a/ios/Classes/Types/URLResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/URLResponse.swift similarity index 100% rename from ios/Classes/Types/URLResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/URLResponse.swift diff --git a/ios/Classes/Types/UserScript.swift b/flutter_inappwebview_ios/ios/Classes/Types/UserScript.swift similarity index 100% rename from ios/Classes/Types/UserScript.swift rename to flutter_inappwebview_ios/ios/Classes/Types/UserScript.swift diff --git a/ios/Classes/Types/WKContentWorld.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKContentWorld.swift similarity index 100% rename from ios/Classes/Types/WKContentWorld.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKContentWorld.swift diff --git a/ios/Classes/Types/WKFrameInfo.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKFrameInfo.swift similarity index 100% rename from ios/Classes/Types/WKFrameInfo.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKFrameInfo.swift diff --git a/ios/Classes/Types/WKNavigationAction.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKNavigationAction.swift similarity index 100% rename from ios/Classes/Types/WKNavigationAction.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKNavigationAction.swift diff --git a/ios/Classes/Types/WKNavigationResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKNavigationResponse.swift similarity index 100% rename from ios/Classes/Types/WKNavigationResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKNavigationResponse.swift diff --git a/ios/Classes/Types/WKSecurityOrigin.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKSecurityOrigin.swift similarity index 100% rename from ios/Classes/Types/WKSecurityOrigin.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKSecurityOrigin.swift diff --git a/ios/Classes/Types/WKUserContentController.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift similarity index 100% rename from ios/Classes/Types/WKUserContentController.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKUserContentController.swift diff --git a/ios/Classes/Types/WKWindowFeatures.swift b/flutter_inappwebview_ios/ios/Classes/Types/WKWindowFeatures.swift similarity index 100% rename from ios/Classes/Types/WKWindowFeatures.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WKWindowFeatures.swift diff --git a/ios/Classes/Types/WebMessage.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebMessage.swift similarity index 100% rename from ios/Classes/Types/WebMessage.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebMessage.swift diff --git a/ios/Classes/Types/WebMessagePort.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebMessagePort.swift similarity index 100% rename from ios/Classes/Types/WebMessagePort.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebMessagePort.swift diff --git a/ios/Classes/Types/WebResourceError.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebResourceError.swift similarity index 100% rename from ios/Classes/Types/WebResourceError.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebResourceError.swift diff --git a/ios/Classes/Types/WebResourceRequest.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebResourceRequest.swift similarity index 100% rename from ios/Classes/Types/WebResourceRequest.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebResourceRequest.swift diff --git a/ios/Classes/Types/WebResourceResponse.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebResourceResponse.swift similarity index 100% rename from ios/Classes/Types/WebResourceResponse.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebResourceResponse.swift diff --git a/ios/Classes/Types/WebViewTransport.swift b/flutter_inappwebview_ios/ios/Classes/Types/WebViewTransport.swift similarity index 100% rename from ios/Classes/Types/WebViewTransport.swift rename to flutter_inappwebview_ios/ios/Classes/Types/WebViewTransport.swift diff --git a/ios/Classes/UIApplication/VisibleViewController.swift b/flutter_inappwebview_ios/ios/Classes/UIApplication/VisibleViewController.swift similarity index 100% rename from ios/Classes/UIApplication/VisibleViewController.swift rename to flutter_inappwebview_ios/ios/Classes/UIApplication/VisibleViewController.swift diff --git a/ios/Classes/Util.swift b/flutter_inappwebview_ios/ios/Classes/Util.swift similarity index 100% rename from ios/Classes/Util.swift rename to flutter_inappwebview_ios/ios/Classes/Util.swift diff --git a/ios/Classes/WKProcessPoolManager.swift b/flutter_inappwebview_ios/ios/Classes/WKProcessPoolManager.swift similarity index 100% rename from ios/Classes/WKProcessPoolManager.swift rename to flutter_inappwebview_ios/ios/Classes/WKProcessPoolManager.swift diff --git a/ios/Classes/WebAuthenticationSession/WebAuthenticationSession.swift b/flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSession.swift similarity index 100% rename from ios/Classes/WebAuthenticationSession/WebAuthenticationSession.swift rename to flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSession.swift diff --git a/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionChannelDelegate.swift similarity index 100% rename from ios/Classes/WebAuthenticationSession/WebAuthenticationSessionChannelDelegate.swift rename to flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionChannelDelegate.swift diff --git a/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionManager.swift b/flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionManager.swift similarity index 100% rename from ios/Classes/WebAuthenticationSession/WebAuthenticationSessionManager.swift rename to flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionManager.swift diff --git a/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionSettings.swift b/flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionSettings.swift similarity index 100% rename from ios/Classes/WebAuthenticationSession/WebAuthenticationSessionSettings.swift rename to flutter_inappwebview_ios/ios/Classes/WebAuthenticationSession/WebAuthenticationSessionSettings.swift diff --git a/ios/Storyboards/WebView.storyboard b/flutter_inappwebview_ios/ios/Storyboards/WebView.storyboard similarity index 95% rename from ios/Storyboards/WebView.storyboard rename to flutter_inappwebview_ios/ios/Storyboards/WebView.storyboard index 9c71b050..51a8d4f4 100755 --- a/ios/Storyboards/WebView.storyboard +++ b/flutter_inappwebview_ios/ios/Storyboards/WebView.storyboard @@ -11,7 +11,7 @@ - + @@ -24,7 +24,7 @@ - + diff --git a/ios/flutter_inappwebview.podspec b/flutter_inappwebview_ios/ios/flutter_inappwebview_ios.podspec similarity index 96% rename from ios/flutter_inappwebview.podspec rename to flutter_inappwebview_ios/ios/flutter_inappwebview_ios.podspec index 03e2e86c..a08fa7fb 100755 --- a/ios/flutter_inappwebview.podspec +++ b/flutter_inappwebview_ios/ios/flutter_inappwebview_ios.podspec @@ -3,7 +3,7 @@ # Run `pod lib lint flutterplugintest.podspec' to validate before publishing. # Pod::Spec.new do |s| - s.name = 'flutter_inappwebview' + s.name = 'flutter_inappwebview_ios' s.version = '0.0.1' s.summary = 'A new Flutter plugin.' s.description = <<-DESC diff --git a/flutter_inappwebview_ios/lib/flutter_inappwebview_ios.dart b/flutter_inappwebview_ios/lib/flutter_inappwebview_ios.dart new file mode 100644 index 00000000..9390a49d --- /dev/null +++ b/flutter_inappwebview_ios/lib/flutter_inappwebview_ios.dart @@ -0,0 +1,3 @@ +library flutter_inappwebview_ios; + +export 'src/main.dart'; diff --git a/flutter_inappwebview_ios/lib/src/chrome_safari_browser/chrome_safari_browser.dart b/flutter_inappwebview_ios/lib/src/chrome_safari_browser/chrome_safari_browser.dart new file mode 100755 index 00000000..931e1b8e --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/chrome_safari_browser/chrome_safari_browser.dart @@ -0,0 +1,408 @@ +import 'dart:async'; +import 'dart:collection'; +import 'dart:typed_data'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSChromeSafariBrowser]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformChromeSafariBrowserCreationParams] for +/// more information. +@immutable +class IOSChromeSafariBrowserCreationParams + extends PlatformChromeSafariBrowserCreationParams { + /// Creates a new [IOSChromeSafariBrowserCreationParams] instance. + const IOSChromeSafariBrowserCreationParams(); + + /// Creates a [IOSChromeSafariBrowserCreationParams] instance based on [PlatformChromeSafariBrowserCreationParams]. + factory IOSChromeSafariBrowserCreationParams.fromPlatformChromeSafariBrowserCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformChromeSafariBrowserCreationParams params) { + return IOSChromeSafariBrowserCreationParams(); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformChromeSafariBrowser} +class IOSChromeSafariBrowser extends PlatformChromeSafariBrowser + with ChannelController { + @override + final String id = IdGenerator.generate(); + + /// Constructs a [IOSChromeSafariBrowser]. + IOSChromeSafariBrowser(PlatformChromeSafariBrowserCreationParams params) + : super.implementation( + params is IOSChromeSafariBrowserCreationParams + ? params + : IOSChromeSafariBrowserCreationParams + .fromPlatformChromeSafariBrowserCreationParams(params), + ); + + static final IOSChromeSafariBrowser _staticValue = + IOSChromeSafariBrowser(IOSChromeSafariBrowserCreationParams()); + + /// Provide static access. + factory IOSChromeSafariBrowser.static() { + return _staticValue; + } + + ChromeSafariBrowserActionButton? _actionButton; + Map _menuItems = new HashMap(); + ChromeSafariBrowserSecondaryToolbar? _secondaryToolbar; + bool _isOpened = false; + static const MethodChannel _staticChannel = + const MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser'); + + _init() { + channel = + MethodChannel('com.pichillilorenzo/flutter_chromesafaribrowser_$id'); + handler = _handleMethod; + initMethodCallHandler(); + } + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + id: id, + debugLoggingSettings: PlatformChromeSafariBrowser.debugLoggingSettings, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + _debugLog(call.method, call.arguments); + + switch (call.method) { + case "onServiceConnected": + eventHandler?.onServiceConnected(); + break; + case "onOpened": + eventHandler?.onOpened(); + break; + case "onCompletedInitialLoad": + final bool? didLoadSuccessfully = call.arguments["didLoadSuccessfully"]; + eventHandler?.onCompletedInitialLoad(didLoadSuccessfully); + break; + case "onInitialLoadDidRedirect": + final String? url = call.arguments["url"]; + final WebUri? uri = url != null ? WebUri(url) : null; + eventHandler?.onInitialLoadDidRedirect(uri); + break; + case "onNavigationEvent": + final navigationEvent = CustomTabsNavigationEventType.fromNativeValue( + call.arguments["navigationEvent"]); + eventHandler?.onNavigationEvent(navigationEvent); + break; + case "onRelationshipValidationResult": + final relation = + CustomTabsRelationType.fromNativeValue(call.arguments["relation"]); + final requestedOrigin = call.arguments["requestedOrigin"] != null + ? WebUri(call.arguments["requestedOrigin"]) + : null; + final bool result = call.arguments["result"]; + eventHandler?.onRelationshipValidationResult( + relation, requestedOrigin, result); + break; + case "onWillOpenInBrowser": + eventHandler?.onWillOpenInBrowser(); + break; + case "onClosed": + _isOpened = false; + final onClosed = eventHandler?.onClosed; + dispose(); + onClosed?.call(); + break; + case "onItemActionPerform": + String url = call.arguments["url"]; + String title = call.arguments["title"]; + int id = call.arguments["id"].toInt(); + if (this._actionButton?.id == id) { + if (this._actionButton?.action != null) { + this._actionButton?.action!(url, title); + } + if (this._actionButton?.onClick != null) { + this._actionButton?.onClick!(WebUri(url), title); + } + } else if (this._menuItems[id] != null) { + if (this._menuItems[id]?.action != null) { + this._menuItems[id]?.action!(url, title); + } + if (this._menuItems[id]?.onClick != null) { + this._menuItems[id]?.onClick!(WebUri(url), title); + } + } + break; + case "onSecondaryItemActionPerform": + final clickableIDs = this._secondaryToolbar?.clickableIDs; + if (clickableIDs != null) { + WebUri? url = call.arguments["url"] != null + ? WebUri(call.arguments["url"]) + : null; + String name = call.arguments["name"]; + for (final clickable in clickableIDs) { + var clickableFullname = clickable.id.name; + if (clickable.id.defType != null && + !clickableFullname.contains("/")) { + clickableFullname = "${clickable.id.defType}/$clickableFullname"; + } + if (clickable.id.defPackage != null && + !clickableFullname.contains(":")) { + clickableFullname = + "${clickable.id.defPackage}:$clickableFullname"; + } + if (clickableFullname == name) { + if (clickable.onClick != null) { + clickable.onClick!(url); + } + break; + } + } + } + break; + case "onMessageChannelReady": + eventHandler?.onMessageChannelReady(); + break; + case "onPostMessage": + final String message = call.arguments["message"]; + eventHandler?.onPostMessage(message); + break; + case "onVerticalScrollEvent": + final bool isDirectionUp = call.arguments["isDirectionUp"]; + eventHandler?.onVerticalScrollEvent(isDirectionUp); + break; + case "onGreatestScrollPercentageIncreased": + final int scrollPercentage = call.arguments["scrollPercentage"]; + eventHandler?.onGreatestScrollPercentageIncreased(scrollPercentage); + break; + case "onSessionEnded": + final bool didUserInteract = call.arguments["didUserInteract"]; + eventHandler?.onSessionEnded(didUserInteract); + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + } + + @override + Future open( + {WebUri? url, + Map? headers, + List? otherLikelyURLs, + WebUri? referrer, + @Deprecated('Use settings instead') + // ignore: deprecated_member_use_from_same_package + ChromeSafariBrowserClassOptions? options, + ChromeSafariBrowserSettings? settings}) async { + assert(!_isOpened, 'The browser is already opened.'); + _isOpened = true; + + if (Util.isIOS) { + assert(url != null, 'The specified URL must not be null on iOS.'); + assert(['http', 'https'].contains(url!.scheme), + 'The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported on iOS.'); + } + if (url != null) { + assert(url.toString().isNotEmpty, 'The specified URL must not be empty.'); + } + + _init(); + + List> menuItemList = []; + _menuItems.forEach((key, value) { + menuItemList.add(value.toMap()); + }); + + var initialSettings = settings?.toMap() ?? + options?.toMap() ?? + ChromeSafariBrowserSettings().toMap(); + + Map args = {}; + args.putIfAbsent('id', () => id); + args.putIfAbsent('url', () => url?.toString()); + args.putIfAbsent('headers', () => headers); + args.putIfAbsent('otherLikelyURLs', + () => otherLikelyURLs?.map((e) => e.toString()).toList()); + args.putIfAbsent('referrer', () => referrer?.toString()); + args.putIfAbsent('settings', () => initialSettings); + args.putIfAbsent('actionButton', () => _actionButton?.toMap()); + args.putIfAbsent('secondaryToolbar', () => _secondaryToolbar?.toMap()); + args.putIfAbsent('menuItemList', () => menuItemList); + await _staticChannel.invokeMethod('open', args); + } + + @override + Future launchUrl({ + required WebUri url, + Map? headers, + List? otherLikelyURLs, + WebUri? referrer, + }) async { + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + args.putIfAbsent('headers', () => headers); + args.putIfAbsent('otherLikelyURLs', + () => otherLikelyURLs?.map((e) => e.toString()).toList()); + args.putIfAbsent('referrer', () => referrer?.toString()); + await channel?.invokeMethod("launchUrl", args); + } + + @override + Future mayLaunchUrl( + {WebUri? url, List? otherLikelyURLs}) async { + Map args = {}; + args.putIfAbsent('url', () => url?.toString()); + args.putIfAbsent('otherLikelyURLs', + () => otherLikelyURLs?.map((e) => e.toString()).toList()); + return await channel?.invokeMethod("mayLaunchUrl", args) ?? false; + } + + @override + Future validateRelationship( + {required CustomTabsRelationType relation, + required WebUri origin}) async { + Map args = {}; + args.putIfAbsent('relation', () => relation.toNativeValue()); + args.putIfAbsent('origin', () => origin.toString()); + return await channel?.invokeMethod("validateRelationship", args) ?? + false; + } + + @override + Future close() async { + Map args = {}; + await channel?.invokeMethod("close", args); + } + + @override + void setActionButton(ChromeSafariBrowserActionButton actionButton) { + this._actionButton = actionButton; + } + + @override + Future updateActionButton( + {required Uint8List icon, required String description}) async { + Map args = {}; + args.putIfAbsent('icon', () => icon); + args.putIfAbsent('description', () => description); + await channel?.invokeMethod("updateActionButton", args); + _actionButton?.icon = icon; + _actionButton?.description = description; + } + + @override + void setSecondaryToolbar( + ChromeSafariBrowserSecondaryToolbar secondaryToolbar) { + this._secondaryToolbar = secondaryToolbar; + } + + @override + Future updateSecondaryToolbar( + ChromeSafariBrowserSecondaryToolbar secondaryToolbar) async { + Map args = {}; + args.putIfAbsent('secondaryToolbar', () => secondaryToolbar.toMap()); + await channel?.invokeMethod("updateSecondaryToolbar", args); + this._secondaryToolbar = secondaryToolbar; + } + + @override + void addMenuItem(ChromeSafariBrowserMenuItem menuItem) { + this._menuItems[menuItem.id] = menuItem; + } + + @override + void addMenuItems(List menuItems) { + menuItems.forEach((menuItem) { + this._menuItems[menuItem.id] = menuItem; + }); + } + + @override + Future requestPostMessageChannel( + {required WebUri sourceOrigin, WebUri? targetOrigin}) async { + Map args = {}; + args.putIfAbsent("sourceOrigin", () => sourceOrigin.toString()); + args.putIfAbsent("targetOrigin", () => targetOrigin.toString()); + return await channel?.invokeMethod( + "requestPostMessageChannel", args) ?? + false; + } + + @override + Future postMessage(String message) async { + Map args = {}; + args.putIfAbsent("message", () => message); + return CustomTabsPostMessageResultType.fromNativeValue( + await channel?.invokeMethod("postMessage", args)) ?? + CustomTabsPostMessageResultType.FAILURE_MESSAGING_ERROR; + } + + @override + Future isEngagementSignalsApiAvailable() async { + Map args = {}; + return await channel?.invokeMethod( + "isEngagementSignalsApiAvailable", args) ?? + false; + } + + @override + Future isAvailable() async { + Map args = {}; + return await _staticChannel.invokeMethod("isAvailable", args) ?? + false; + } + + @override + Future getMaxToolbarItems() async { + Map args = {}; + return await _staticChannel.invokeMethod("getMaxToolbarItems", args) ?? + 0; + } + + @override + Future getPackageName( + {List? packages, bool ignoreDefault = false}) async { + Map args = {}; + args.putIfAbsent("packages", () => packages); + args.putIfAbsent("ignoreDefault", () => ignoreDefault); + return await _staticChannel.invokeMethod("getPackageName", args); + } + + @override + Future clearWebsiteData() async { + Map args = {}; + await _staticChannel.invokeMethod("clearWebsiteData", args); + } + + @override + Future prewarmConnections(List URLs) async { + Map args = {}; + args.putIfAbsent('URLs', () => URLs.map((e) => e.toString()).toList()); + Map? result = + (await _staticChannel.invokeMethod("prewarmConnections", args)) + ?.cast(); + return PrewarmingToken.fromMap(result); + } + + @override + Future invalidatePrewarmingToken( + PrewarmingToken prewarmingToken) async { + Map args = {}; + args.putIfAbsent('prewarmingToken', () => prewarmingToken.toMap()); + await _staticChannel.invokeMethod("invalidatePrewarmingToken", args); + } + + @override + bool isOpened() { + return _isOpened; + } + + @override + @mustCallSuper + void dispose() { + disposeChannel(); + eventHandler = null; + } +} diff --git a/flutter_inappwebview_ios/lib/src/chrome_safari_browser/main.dart b/flutter_inappwebview_ios/lib/src/chrome_safari_browser/main.dart new file mode 100644 index 00000000..9a6238b7 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/chrome_safari_browser/main.dart @@ -0,0 +1 @@ +export 'chrome_safari_browser.dart'; diff --git a/flutter_inappwebview_ios/lib/src/cookie_manager.dart b/flutter_inappwebview_ios/lib/src/cookie_manager.dart new file mode 100755 index 00000000..26ecef34 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/cookie_manager.dart @@ -0,0 +1,442 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import 'in_app_webview/headless_in_app_webview.dart'; +import 'platform_util.dart'; + +/// Object specifying creation parameters for creating a [IOSCookieManager]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformCookieManagerCreationParams] for +/// more information. +@immutable +class IOSCookieManagerCreationParams + extends PlatformCookieManagerCreationParams { + /// Creates a new [IOSCookieManagerCreationParams] instance. + const IOSCookieManagerCreationParams( + // This parameter prevents breaking changes later. + // ignore: avoid_unused_constructor_parameters + PlatformCookieManagerCreationParams params, + ) : super(); + + /// Creates a [IOSCookieManagerCreationParams] instance based on [PlatformCookieManagerCreationParams]. + factory IOSCookieManagerCreationParams.fromPlatformCookieManagerCreationParams( + PlatformCookieManagerCreationParams params) { + return IOSCookieManagerCreationParams(params); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformCookieManager} +class IOSCookieManager extends PlatformCookieManager + with ChannelController { + /// Creates a new [IOSCookieManager]. + IOSCookieManager(PlatformCookieManagerCreationParams params) + : super.implementation( + params is IOSCookieManagerCreationParams + ? params + : IOSCookieManagerCreationParams + .fromPlatformCookieManagerCreationParams(params), + ) { + channel = const MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_cookiemanager'); + handler = handleMethod; + initMethodCallHandler(); + } + + static IOSCookieManager? _instance; + + ///Gets the [IOSCookieManager] shared instance. + static IOSCookieManager instance() { + return (_instance != null) ? _instance! : _init(); + } + + static IOSCookieManager _init() { + _instance = IOSCookieManager(IOSCookieManagerCreationParams( + const PlatformCookieManagerCreationParams())); + return _instance!; + } + + Future _handleMethod(MethodCall call) async {} + + @override + Future setCookie( + {required WebUri url, + required String name, + required String value, + String path = "/", + String? domain, + int? expiresDate, + int? maxAge, + bool? isSecure, + bool? isHttpOnly, + HTTPCookieSameSitePolicy? sameSite, + @Deprecated("Use webViewController instead") + PlatformInAppWebViewController? iosBelow11WebViewController, + PlatformInAppWebViewController? webViewController}) async { + webViewController = webViewController ?? iosBelow11WebViewController; + + assert(url.toString().isNotEmpty); + assert(name.isNotEmpty); + assert(value.isNotEmpty); + assert(path.isNotEmpty); + + if (await _shouldUseJavascript()) { + await _setCookieWithJavaScript( + url: url, + name: name, + value: value, + domain: domain, + path: path, + expiresDate: expiresDate, + maxAge: maxAge, + isSecure: isSecure, + sameSite: sameSite, + webViewController: webViewController); + return true; + } + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + args.putIfAbsent('name', () => name); + args.putIfAbsent('value', () => value); + args.putIfAbsent('domain', () => domain); + args.putIfAbsent('path', () => path); + args.putIfAbsent('expiresDate', () => expiresDate?.toString()); + args.putIfAbsent('maxAge', () => maxAge); + args.putIfAbsent('isSecure', () => isSecure); + args.putIfAbsent('isHttpOnly', () => isHttpOnly); + args.putIfAbsent('sameSite', () => sameSite?.toNativeValue()); + + return await channel?.invokeMethod('setCookie', args) ?? false; + } + + Future _setCookieWithJavaScript( + {required WebUri url, + required String name, + required String value, + String path = "/", + String? domain, + int? expiresDate, + int? maxAge, + bool? isSecure, + HTTPCookieSameSitePolicy? sameSite, + PlatformInAppWebViewController? webViewController}) async { + var cookieValue = name + "=" + value + "; Path=" + path; + + if (domain != null) cookieValue += "; Domain=" + domain; + + if (expiresDate != null) + cookieValue += "; Expires=" + await _getCookieExpirationDate(expiresDate); + + if (maxAge != null) cookieValue += "; Max-Age=" + maxAge.toString(); + + if (isSecure != null && isSecure) cookieValue += "; Secure"; + + if (sameSite != null) + cookieValue += "; SameSite=" + sameSite.toNativeValue(); + + cookieValue += ";"; + + if (webViewController != null) { + final javaScriptEnabled = + (await webViewController.getSettings())?.javaScriptEnabled ?? false; + if (javaScriptEnabled) { + await webViewController.evaluateJavascript( + source: 'document.cookie="$cookieValue"'); + return; + } + } + + final setCookieCompleter = Completer(); + final headlessWebView = + IOSHeadlessInAppWebView(IOSHeadlessInAppWebViewCreationParams( + initialUrlRequest: URLRequest(url: url), + onLoadStop: (controller, url) async { + await controller.evaluateJavascript( + source: 'document.cookie="$cookieValue"'); + setCookieCompleter.complete(); + })); + await headlessWebView.run(); + await setCookieCompleter.future; + await headlessWebView.dispose(); + } + + @override + Future> getCookies( + {required WebUri url, + @Deprecated("Use webViewController instead") + PlatformInAppWebViewController? iosBelow11WebViewController, + PlatformInAppWebViewController? webViewController}) async { + assert(url.toString().isNotEmpty); + + webViewController = webViewController ?? iosBelow11WebViewController; + + if (await _shouldUseJavascript()) { + return await _getCookiesWithJavaScript( + url: url, webViewController: webViewController); + } + + List cookies = []; + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + List cookieListMap = + await channel?.invokeMethod('getCookies', args) ?? []; + cookieListMap = cookieListMap.cast>(); + + cookieListMap.forEach((cookieMap) { + cookies.add(Cookie( + name: cookieMap["name"], + value: cookieMap["value"], + expiresDate: cookieMap["expiresDate"], + isSessionOnly: cookieMap["isSessionOnly"], + domain: cookieMap["domain"], + sameSite: + HTTPCookieSameSitePolicy.fromNativeValue(cookieMap["sameSite"]), + isSecure: cookieMap["isSecure"], + isHttpOnly: cookieMap["isHttpOnly"], + path: cookieMap["path"])); + }); + return cookies; + } + + Future> _getCookiesWithJavaScript( + {required WebUri url, + PlatformInAppWebViewController? webViewController}) async { + assert(url.toString().isNotEmpty); + + List cookies = []; + + if (webViewController != null) { + final javaScriptEnabled = + (await webViewController.getSettings())?.javaScriptEnabled ?? false; + if (javaScriptEnabled) { + List documentCookies = (await webViewController + .evaluateJavascript(source: 'document.cookie') as String) + .split(';') + .map((documentCookie) => documentCookie.trim()) + .toList(); + documentCookies.forEach((documentCookie) { + List cookie = documentCookie.split('='); + if (cookie.length > 1) { + cookies.add(Cookie( + name: cookie[0], + value: cookie[1], + )); + } + }); + return cookies; + } + } + + final pageLoaded = Completer(); + final headlessWebView = + IOSHeadlessInAppWebView(IOSHeadlessInAppWebViewCreationParams( + initialUrlRequest: URLRequest(url: url), + onLoadStop: (controller, url) async { + pageLoaded.complete(); + }, + )); + await headlessWebView.run(); + await pageLoaded.future; + + List documentCookies = (await headlessWebView.webViewController! + .evaluateJavascript(source: 'document.cookie') as String) + .split(';') + .map((documentCookie) => documentCookie.trim()) + .toList(); + documentCookies.forEach((documentCookie) { + List cookie = documentCookie.split('='); + if (cookie.length > 1) { + cookies.add(Cookie( + name: cookie[0], + value: cookie[1], + )); + } + }); + await headlessWebView.dispose(); + return cookies; + } + + @override + Future getCookie( + {required WebUri url, + required String name, + @Deprecated("Use webViewController instead") + PlatformInAppWebViewController? iosBelow11WebViewController, + PlatformInAppWebViewController? webViewController}) async { + assert(url.toString().isNotEmpty); + assert(name.isNotEmpty); + + webViewController = webViewController ?? iosBelow11WebViewController; + + if (await _shouldUseJavascript()) { + List cookies = await _getCookiesWithJavaScript( + url: url, webViewController: webViewController); + return cookies + .cast() + .firstWhere((cookie) => cookie!.name == name, orElse: () => null); + } + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + List cookies = + await channel?.invokeMethod('getCookies', args) ?? []; + cookies = cookies.cast>(); + for (var i = 0; i < cookies.length; i++) { + cookies[i] = cookies[i].cast(); + if (cookies[i]["name"] == name) + return Cookie( + name: cookies[i]["name"], + value: cookies[i]["value"], + expiresDate: cookies[i]["expiresDate"], + isSessionOnly: cookies[i]["isSessionOnly"], + domain: cookies[i]["domain"], + sameSite: HTTPCookieSameSitePolicy.fromNativeValue( + cookies[i]["sameSite"]), + isSecure: cookies[i]["isSecure"], + isHttpOnly: cookies[i]["isHttpOnly"], + path: cookies[i]["path"]); + } + return null; + } + + @override + Future deleteCookie( + {required WebUri url, + required String name, + String path = "/", + String? domain, + @Deprecated("Use webViewController instead") + PlatformInAppWebViewController? iosBelow11WebViewController, + PlatformInAppWebViewController? webViewController}) async { + assert(url.toString().isNotEmpty); + assert(name.isNotEmpty); + + webViewController = webViewController ?? iosBelow11WebViewController; + + if (await _shouldUseJavascript()) { + await _setCookieWithJavaScript( + url: url, + name: name, + value: "", + path: path, + domain: domain, + maxAge: -1, + webViewController: webViewController); + return; + } + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + args.putIfAbsent('name', () => name); + args.putIfAbsent('domain', () => domain); + args.putIfAbsent('path', () => path); + await channel?.invokeMethod('deleteCookie', args); + } + + @override + Future deleteCookies( + {required WebUri url, + String path = "/", + String? domain, + @Deprecated("Use webViewController instead") + PlatformInAppWebViewController? iosBelow11WebViewController, + PlatformInAppWebViewController? webViewController}) async { + assert(url.toString().isNotEmpty); + + webViewController = webViewController ?? iosBelow11WebViewController; + + if (await _shouldUseJavascript()) { + List cookies = await _getCookiesWithJavaScript( + url: url, webViewController: webViewController); + for (var i = 0; i < cookies.length; i++) { + await _setCookieWithJavaScript( + url: url, + name: cookies[i].name, + value: "", + path: path, + domain: domain, + maxAge: -1, + webViewController: webViewController); + } + return; + } + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + args.putIfAbsent('domain', () => domain); + args.putIfAbsent('path', () => path); + await channel?.invokeMethod('deleteCookies', args); + } + + @override + Future deleteAllCookies() async { + Map args = {}; + await channel?.invokeMethod('deleteAllCookies', args); + } + + @override + Future> getAllCookies() async { + List cookies = []; + + Map args = {}; + List cookieListMap = + await channel?.invokeMethod('getAllCookies', args) ?? []; + cookieListMap = cookieListMap.cast>(); + + cookieListMap.forEach((cookieMap) { + cookies.add(Cookie( + name: cookieMap["name"], + value: cookieMap["value"], + expiresDate: cookieMap["expiresDate"], + isSessionOnly: cookieMap["isSessionOnly"], + domain: cookieMap["domain"], + sameSite: + HTTPCookieSameSitePolicy.fromNativeValue(cookieMap["sameSite"]), + isSecure: cookieMap["isSecure"], + isHttpOnly: cookieMap["isHttpOnly"], + path: cookieMap["path"])); + }); + return cookies; + } + + Future _getCookieExpirationDate(int expiresDate) async { + var platformUtil = PlatformUtil.instance(); + var dateTime = DateTime.fromMillisecondsSinceEpoch(expiresDate).toUtc(); + return !kIsWeb + ? await platformUtil.formatDate( + date: dateTime, + format: 'EEE, dd MMM yyyy hh:mm:ss z', + locale: 'en_US', + timezone: 'GMT') + : await platformUtil.getWebCookieExpirationDate(date: dateTime); + } + + Future _shouldUseJavascript() async { + if (Util.isWeb) { + return true; + } + if (Util.isIOS || Util.isMacOS) { + final platformUtil = PlatformUtil.instance(); + final systemVersion = await platformUtil.getSystemVersion(); + return Util.isIOS + ? systemVersion.compareTo("11") == -1 + : systemVersion.compareTo("10.13") == -1; + } + return false; + } + + @override + void dispose() { + // empty + } +} + +extension InternalCookieManager on IOSCookieManager { + get handleMethod => _handleMethod; +} diff --git a/flutter_inappwebview_ios/lib/src/find_interaction/find_interaction_controller.dart b/flutter_inappwebview_ios/lib/src/find_interaction/find_interaction_controller.dart new file mode 100644 index 00000000..83ea52b5 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/find_interaction/find_interaction_controller.dart @@ -0,0 +1,149 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSFindInteractionController]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformFindInteractionControllerCreationParams] for +/// more information. +@immutable +class IOSFindInteractionControllerCreationParams + extends PlatformFindInteractionControllerCreationParams { + /// Creates a new [IOSFindInteractionControllerCreationParams] instance. + const IOSFindInteractionControllerCreationParams( + {super.onFindResultReceived}); + + /// Creates a [IOSFindInteractionControllerCreationParams] instance based on [PlatformFindInteractionControllerCreationParams]. + factory IOSFindInteractionControllerCreationParams.fromPlatformFindInteractionControllerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformFindInteractionControllerCreationParams params) { + return IOSFindInteractionControllerCreationParams( + onFindResultReceived: params.onFindResultReceived); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController} +class IOSFindInteractionController extends PlatformFindInteractionController + with ChannelController { + /// Constructs a [IOSFindInteractionController]. + IOSFindInteractionController( + PlatformFindInteractionControllerCreationParams params) + : super.implementation( + params is IOSFindInteractionControllerCreationParams + ? params + : IOSFindInteractionControllerCreationParams + .fromPlatformFindInteractionControllerCreationParams(params), + ); + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + debugLoggingSettings: + PlatformFindInteractionController.debugLoggingSettings, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + _debugLog(call.method, call.arguments); + + switch (call.method) { + case "onFindResultReceived": + if (onFindResultReceived != null) { + int activeMatchOrdinal = call.arguments["activeMatchOrdinal"]; + int numberOfMatches = call.arguments["numberOfMatches"]; + bool isDoneCounting = call.arguments["isDoneCounting"]; + onFindResultReceived!( + this, activeMatchOrdinal, numberOfMatches, isDoneCounting); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.findAll} + Future findAll({String? find}) async { + Map args = {}; + args.putIfAbsent('find', () => find); + await channel?.invokeMethod('findAll', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.findNext} + Future findNext({bool forward = true}) async { + Map args = {}; + args.putIfAbsent('forward', () => forward); + await channel?.invokeMethod('findNext', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.clearMatches} + Future clearMatches() async { + Map args = {}; + await channel?.invokeMethod('clearMatches', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.setSearchText} + Future setSearchText(String? searchText) async { + Map args = {}; + args.putIfAbsent('searchText', () => searchText); + await channel?.invokeMethod('setSearchText', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.getSearchText} + Future getSearchText() async { + Map args = {}; + return await channel?.invokeMethod('getSearchText', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.isFindNavigatorVisible} + Future isFindNavigatorVisible() async { + Map args = {}; + return await channel?.invokeMethod('isFindNavigatorVisible', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.updateResultCount} + Future updateResultCount() async { + Map args = {}; + await channel?.invokeMethod('updateResultCount', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.presentFindNavigator} + Future presentFindNavigator() async { + Map args = {}; + await channel?.invokeMethod('presentFindNavigator', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.dismissFindNavigator} + Future dismissFindNavigator() async { + Map args = {}; + await channel?.invokeMethod('dismissFindNavigator', args); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.getActiveFindSession} + Future getActiveFindSession() async { + Map args = {}; + Map? result = + (await channel?.invokeMethod('getActiveFindSession', args)) + ?.cast(); + return FindSession.fromMap(result); + } + + ///{@macro flutter_inappwebview_platform_interface.PlatformFindInteractionController.dispose} + @override + void dispose({bool isKeepAlive = false}) { + disposeChannel(removeMethodCallHandler: !isKeepAlive); + } +} + +extension InternalFindInteractionController + on IOSFindInteractionController { + void init(dynamic id) { + channel = MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_find_interaction_$id'); + handler = _handleMethod; + initMethodCallHandler(); + } +} diff --git a/flutter_inappwebview_ios/lib/src/find_interaction/main.dart b/flutter_inappwebview_ios/lib/src/find_interaction/main.dart new file mode 100644 index 00000000..a7adaacf --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/find_interaction/main.dart @@ -0,0 +1,2 @@ +export 'find_interaction_controller.dart' + hide InternalFindInteractionController; diff --git a/flutter_inappwebview_ios/lib/src/http_auth_credentials_database.dart b/flutter_inappwebview_ios/lib/src/http_auth_credentials_database.dart new file mode 100755 index 00000000..4de0fb6c --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/http_auth_credentials_database.dart @@ -0,0 +1,155 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSHttpAuthCredentialDatabase]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformHttpAuthCredentialDatabaseCreationParams] for +/// more information. +@immutable +class IOSHttpAuthCredentialDatabaseCreationParams + extends PlatformHttpAuthCredentialDatabaseCreationParams { + /// Creates a new [IOSHttpAuthCredentialDatabaseCreationParams] instance. + const IOSHttpAuthCredentialDatabaseCreationParams( + // This parameter prevents breaking changes later. + // ignore: avoid_unused_constructor_parameters + PlatformHttpAuthCredentialDatabaseCreationParams params, + ) : super(); + + /// Creates a [IOSHttpAuthCredentialDatabaseCreationParams] instance based on [PlatformHttpAuthCredentialDatabaseCreationParams]. + factory IOSHttpAuthCredentialDatabaseCreationParams.fromPlatformHttpAuthCredentialDatabaseCreationParams( + PlatformHttpAuthCredentialDatabaseCreationParams params) { + return IOSHttpAuthCredentialDatabaseCreationParams(params); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformHttpAuthCredentialDatabase} +class IOSHttpAuthCredentialDatabase + extends PlatformHttpAuthCredentialDatabase with ChannelController { + /// Creates a new [IOSHttpAuthCredentialDatabase]. + IOSHttpAuthCredentialDatabase( + PlatformHttpAuthCredentialDatabaseCreationParams params) + : super.implementation( + params is IOSHttpAuthCredentialDatabaseCreationParams + ? params + : IOSHttpAuthCredentialDatabaseCreationParams + .fromPlatformHttpAuthCredentialDatabaseCreationParams(params), + ) { + channel = const MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_credential_database'); + handler = handleMethod; + initMethodCallHandler(); + } + + static IOSHttpAuthCredentialDatabase? _instance; + + ///Gets the database shared instance. + static IOSHttpAuthCredentialDatabase instance() { + return (_instance != null) ? _instance! : _init(); + } + + static IOSHttpAuthCredentialDatabase _init() { + _instance = IOSHttpAuthCredentialDatabase( + IOSHttpAuthCredentialDatabaseCreationParams( + const PlatformHttpAuthCredentialDatabaseCreationParams())); + return _instance!; + } + + Future _handleMethod(MethodCall call) async {} + + @override + Future> + getAllAuthCredentials() async { + Map args = {}; + List allCredentials = + await channel?.invokeMethod('getAllAuthCredentials', args) ?? []; + + List result = []; + + for (Map map in allCredentials) { + var element = URLProtectionSpaceHttpAuthCredentials.fromMap( + map.cast()); + if (element != null) { + result.add(element); + } + } + return result; + } + + @override + Future> getHttpAuthCredentials( + {required URLProtectionSpace protectionSpace}) async { + Map args = {}; + args.putIfAbsent("host", () => protectionSpace.host); + args.putIfAbsent("protocol", () => protectionSpace.protocol); + args.putIfAbsent("realm", () => protectionSpace.realm); + args.putIfAbsent("port", () => protectionSpace.port); + List credentialList = + await channel?.invokeMethod('getHttpAuthCredentials', args) ?? []; + List credentials = []; + for (Map map in credentialList) { + var credential = URLCredential.fromMap(map.cast()); + if (credential != null) { + credentials.add(credential); + } + } + return credentials; + } + + @override + Future setHttpAuthCredential( + {required URLProtectionSpace protectionSpace, + required URLCredential credential}) async { + Map args = {}; + args.putIfAbsent("host", () => protectionSpace.host); + args.putIfAbsent("protocol", () => protectionSpace.protocol); + args.putIfAbsent("realm", () => protectionSpace.realm); + args.putIfAbsent("port", () => protectionSpace.port); + args.putIfAbsent("username", () => credential.username); + args.putIfAbsent("password", () => credential.password); + await channel?.invokeMethod('setHttpAuthCredential', args); + } + + @override + Future removeHttpAuthCredential( + {required URLProtectionSpace protectionSpace, + required URLCredential credential}) async { + Map args = {}; + args.putIfAbsent("host", () => protectionSpace.host); + args.putIfAbsent("protocol", () => protectionSpace.protocol); + args.putIfAbsent("realm", () => protectionSpace.realm); + args.putIfAbsent("port", () => protectionSpace.port); + args.putIfAbsent("username", () => credential.username); + args.putIfAbsent("password", () => credential.password); + await channel?.invokeMethod('removeHttpAuthCredential', args); + } + + @override + Future removeHttpAuthCredentials( + {required URLProtectionSpace protectionSpace}) async { + Map args = {}; + args.putIfAbsent("host", () => protectionSpace.host); + args.putIfAbsent("protocol", () => protectionSpace.protocol); + args.putIfAbsent("realm", () => protectionSpace.realm); + args.putIfAbsent("port", () => protectionSpace.port); + await channel?.invokeMethod('removeHttpAuthCredentials', args); + } + + @override + Future clearAllAuthCredentials() async { + Map args = {}; + await channel?.invokeMethod('clearAllAuthCredentials', args); + } + + @override + void dispose() { + // empty + } +} + +extension InternalHttpAuthCredentialDatabase + on IOSHttpAuthCredentialDatabase { + get handleMethod => _handleMethod; +} diff --git a/flutter_inappwebview_ios/lib/src/in_app_browser/in_app_browser.dart b/flutter_inappwebview_ios/lib/src/in_app_browser/in_app_browser.dart new file mode 100755 index 00000000..fd4a6adf --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_browser/in_app_browser.dart @@ -0,0 +1,375 @@ +import 'dart:async'; +import 'dart:collection'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import '../find_interaction/find_interaction_controller.dart'; +import '../in_app_webview/in_app_webview_controller.dart'; +import '../pull_to_refresh/pull_to_refresh_controller.dart'; + +/// Object specifying creation parameters for creating a [IOSInAppBrowser]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformInAppBrowserCreationParams] for +/// more information. +class IOSInAppBrowserCreationParams + extends PlatformInAppBrowserCreationParams { + /// Creates a new [IOSInAppBrowserCreationParams] instance. + IOSInAppBrowserCreationParams( + {super.contextMenu, + this.pullToRefreshController, + this.findInteractionController, + super.initialUserScripts, + super.windowId}); + + /// Creates a [IOSInAppBrowserCreationParams] instance based on [PlatformInAppBrowserCreationParams]. + factory IOSInAppBrowserCreationParams.fromPlatformInAppBrowserCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformInAppBrowserCreationParams params) { + return IOSInAppBrowserCreationParams( + contextMenu: params.contextMenu, + pullToRefreshController: + params.pullToRefreshController as IOSPullToRefreshController?, + findInteractionController: params.findInteractionController + as IOSFindInteractionController?, + initialUserScripts: params.initialUserScripts, + windowId: params.windowId); + } + + @override + final IOSFindInteractionController? findInteractionController; + + @override + final IOSPullToRefreshController? pullToRefreshController; +} + +///{@macro flutter_inappwebview_platform_interface.PlatformInAppBrowser} +class IOSInAppBrowser extends PlatformInAppBrowser with ChannelController { + @override + final String id = IdGenerator.generate(); + + /// Constructs a [IOSInAppBrowser]. + IOSInAppBrowser(PlatformInAppBrowserCreationParams params) + : super.implementation( + params is IOSInAppBrowserCreationParams + ? params + : IOSInAppBrowserCreationParams + .fromPlatformInAppBrowserCreationParams(params), + ) { + _contextMenu = params.contextMenu; + } + + static final IOSInAppBrowser _staticValue = + IOSInAppBrowser(IOSInAppBrowserCreationParams()); + + /// Provide static access. + factory IOSInAppBrowser.static() { + return _staticValue; + } + + IOSInAppBrowserCreationParams get _iosParams => + params as IOSInAppBrowserCreationParams; + + static const MethodChannel _staticChannel = + const MethodChannel('com.pichillilorenzo/flutter_inappbrowser'); + + ContextMenu? _contextMenu; + + @override + ContextMenu? get contextMenu => _contextMenu; + + Map _menuItems = HashMap(); + bool _isOpened = false; + IOSInAppWebViewController? _webViewController; + + @override + IOSInAppWebViewController? get webViewController { + return _isOpened ? _webViewController : null; + } + + _init() { + channel = MethodChannel('com.pichillilorenzo/flutter_inappbrowser_$id'); + handler = _handleMethod; + initMethodCallHandler(); + + _webViewController = IOSInAppWebViewController.fromInAppBrowser( + IOSInAppWebViewControllerCreationParams(id: id), + channel!, + this, + this.initialUserScripts); + _iosParams.pullToRefreshController?.init(id); + _iosParams.findInteractionController?.init(id); + } + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + id: id, + debugLoggingSettings: PlatformInAppBrowser.debugLoggingSettings, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onBrowserCreated": + _debugLog(call.method, call.arguments); + eventHandler?.onBrowserCreated(); + break; + case "onMenuItemClicked": + _debugLog(call.method, call.arguments); + int id = call.arguments["id"].toInt(); + if (this._menuItems[id] != null) { + if (this._menuItems[id]?.onClick != null) { + this._menuItems[id]?.onClick!(); + } + } + break; + case "onExit": + _debugLog(call.method, call.arguments); + _isOpened = false; + final onExit = eventHandler?.onExit; + dispose(); + onExit?.call(); + break; + default: + return _webViewController?.handleMethod(call); + } + } + + Map _prepareOpenRequest( + {@Deprecated('Use settings instead') InAppBrowserClassOptions? options, + InAppBrowserClassSettings? settings}) { + assert(!_isOpened, 'The browser is already opened.'); + _isOpened = true; + _init(); + + var initialSettings = settings?.toMap() ?? + options?.toMap() ?? + InAppBrowserClassSettings().toMap(); + + Map pullToRefreshSettings = + pullToRefreshController?.settings.toMap() ?? + pullToRefreshController?.options.toMap() ?? + PullToRefreshSettings(enabled: false).toMap(); + + List> menuItemList = []; + _menuItems.forEach((key, value) { + menuItemList.add(value.toMap()); + }); + + Map args = {}; + args.putIfAbsent('id', () => id); + args.putIfAbsent('settings', () => initialSettings); + args.putIfAbsent('contextMenu', () => contextMenu?.toMap() ?? {}); + args.putIfAbsent('windowId', () => windowId); + args.putIfAbsent('initialUserScripts', + () => initialUserScripts?.map((e) => e.toMap()).toList() ?? []); + args.putIfAbsent('pullToRefreshSettings', () => pullToRefreshSettings); + args.putIfAbsent('menuItems', () => menuItemList); + return args; + } + + @override + Future openUrlRequest( + {required URLRequest urlRequest, + // ignore: deprecated_member_use_from_same_package + @Deprecated('Use settings instead') InAppBrowserClassOptions? options, + InAppBrowserClassSettings? settings}) async { + assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty); + + Map args = + _prepareOpenRequest(options: options, settings: settings); + args.putIfAbsent('urlRequest', () => urlRequest.toMap()); + await _staticChannel.invokeMethod('open', args); + } + + @override + Future openFile( + {required String assetFilePath, + // ignore: deprecated_member_use_from_same_package + @Deprecated('Use settings instead') InAppBrowserClassOptions? options, + InAppBrowserClassSettings? settings}) async { + assert(assetFilePath.isNotEmpty); + + Map args = + _prepareOpenRequest(options: options, settings: settings); + args.putIfAbsent('assetFilePath', () => assetFilePath); + await _staticChannel.invokeMethod('open', args); + } + + @override + Future openData( + {required String data, + String mimeType = "text/html", + String encoding = "utf8", + WebUri? baseUrl, + @Deprecated("Use historyUrl instead") Uri? androidHistoryUrl, + WebUri? historyUrl, + // ignore: deprecated_member_use_from_same_package + @Deprecated('Use settings instead') InAppBrowserClassOptions? options, + InAppBrowserClassSettings? settings}) async { + Map args = + _prepareOpenRequest(options: options, settings: settings); + args.putIfAbsent('data', () => data); + args.putIfAbsent('mimeType', () => mimeType); + args.putIfAbsent('encoding', () => encoding); + args.putIfAbsent('baseUrl', () => baseUrl?.toString() ?? "about:blank"); + args.putIfAbsent('historyUrl', + () => (historyUrl ?? androidHistoryUrl)?.toString() ?? "about:blank"); + await _staticChannel.invokeMethod('open', args); + } + + @override + Future openWithSystemBrowser({required WebUri url}) async { + assert(url.toString().isNotEmpty); + + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + return await _staticChannel.invokeMethod('openWithSystemBrowser', args); + } + + @override + void addMenuItem(InAppBrowserMenuItem menuItem) { + _menuItems[menuItem.id] = menuItem; + } + + @override + void addMenuItems(List menuItems) { + menuItems.forEach((menuItem) { + _menuItems[menuItem.id] = menuItem; + }); + } + + @override + bool removeMenuItem(InAppBrowserMenuItem menuItem) { + return _menuItems.remove(menuItem.id) != null; + } + + @override + void removeMenuItems(List menuItems) { + for (final menuItem in menuItems) { + removeMenuItem(menuItem); + } + } + + @override + void removeAllMenuItem() { + _menuItems.clear(); + } + + @override + bool hasMenuItem(InAppBrowserMenuItem menuItem) { + return _menuItems.containsKey(menuItem.id); + } + + @override + Future show() async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + await channel?.invokeMethod('show', args); + } + + @override + Future hide() async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + await channel?.invokeMethod('hide', args); + } + + @override + Future close() async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + await channel?.invokeMethod('close', args); + } + + @override + Future isHidden() async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + return await channel?.invokeMethod('isHidden', args) ?? false; + } + + @override + @Deprecated('Use setSettings instead') + Future setOptions({required InAppBrowserClassOptions options}) async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + args.putIfAbsent('settings', () => options.toMap()); + await channel?.invokeMethod('setSettings', args); + } + + @override + @Deprecated('Use getSettings instead') + Future getOptions() async { + assert(_isOpened, 'The browser is not opened.'); + Map args = {}; + + Map? options = + await channel?.invokeMethod('getSettings', args); + if (options != null) { + options = options.cast(); + return InAppBrowserClassOptions.fromMap(options as Map); + } + + return null; + } + + @override + Future setSettings( + {required InAppBrowserClassSettings settings}) async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + args.putIfAbsent('settings', () => settings.toMap()); + await channel?.invokeMethod('setSettings', args); + } + + @override + Future getSettings() async { + assert(_isOpened, 'The browser is not opened.'); + + Map args = {}; + + Map? settings = + await channel?.invokeMethod('getSettings', args); + if (settings != null) { + settings = settings.cast(); + return InAppBrowserClassSettings.fromMap( + settings as Map); + } + + return null; + } + + @override + bool isOpened() { + return this._isOpened; + } + + @override + @mustCallSuper + void dispose() { + disposeChannel(); + _webViewController?.dispose(); + _webViewController = null; + pullToRefreshController?.dispose(); + findInteractionController?.dispose(); + eventHandler = null; + } +} + +extension InternalInAppBrowser on IOSInAppBrowser { + void setContextMenu(ContextMenu? contextMenu) { + _contextMenu = contextMenu; + } +} diff --git a/flutter_inappwebview_ios/lib/src/in_app_browser/main.dart b/flutter_inappwebview_ios/lib/src/in_app_browser/main.dart new file mode 100644 index 00000000..e11eb8b1 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_browser/main.dart @@ -0,0 +1 @@ +export 'in_app_browser.dart' hide InternalInAppBrowser; diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/_static_channel.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/_static_channel.dart new file mode 100644 index 00000000..beb7de70 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/_static_channel.dart @@ -0,0 +1,4 @@ +import 'package:flutter/services.dart'; + +const IN_APP_WEBVIEW_STATIC_CHANNEL = + MethodChannel('com.pichillilorenzo/flutter_inappwebview_manager'); diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/headless_in_app_webview.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/headless_in_app_webview.dart new file mode 100644 index 00000000..f29896cb --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/headless_in_app_webview.dart @@ -0,0 +1,440 @@ +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; +import '../find_interaction/find_interaction_controller.dart'; +import '../pull_to_refresh/pull_to_refresh_controller.dart'; +import 'in_app_webview_controller.dart'; + +/// Object specifying creation parameters for creating a [IOSCookieManager]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformHeadlessInAppWebViewCreationParams] for +/// more information. +@immutable +class IOSHeadlessInAppWebViewCreationParams + extends PlatformHeadlessInAppWebViewCreationParams { + /// Creates a new [IOSHeadlessInAppWebViewCreationParams] instance. + IOSHeadlessInAppWebViewCreationParams( + {super.controllerFromPlatform, + super.initialSize, + super.windowId, + super.onWebViewCreated, + super.onLoadStart, + super.onLoadStop, + @Deprecated('Use onReceivedError instead') super.onLoadError, + super.onReceivedError, + @Deprecated("Use onReceivedHttpError instead") super.onLoadHttpError, + super.onReceivedHttpError, + super.onProgressChanged, + super.onConsoleMessage, + super.shouldOverrideUrlLoading, + super.onLoadResource, + super.onScrollChanged, + @Deprecated('Use onDownloadStartRequest instead') super.onDownloadStart, + super.onDownloadStartRequest, + @Deprecated('Use onLoadResourceWithCustomScheme instead') + super.onLoadResourceCustomScheme, + super.onLoadResourceWithCustomScheme, + super.onCreateWindow, + super.onCloseWindow, + super.onJsAlert, + super.onJsConfirm, + super.onJsPrompt, + super.onReceivedHttpAuthRequest, + super.onReceivedServerTrustAuthRequest, + super.onReceivedClientCertRequest, + @Deprecated('Use FindInteractionController.onFindResultReceived instead') + super.onFindResultReceived, + super.shouldInterceptAjaxRequest, + super.onAjaxReadyStateChange, + super.onAjaxProgress, + super.shouldInterceptFetchRequest, + super.onUpdateVisitedHistory, + @Deprecated("Use onPrintRequest instead") super.onPrint, + super.onPrintRequest, + super.onLongPressHitTestResult, + super.onEnterFullscreen, + super.onExitFullscreen, + super.onPageCommitVisible, + super.onTitleChanged, + super.onWindowFocus, + super.onWindowBlur, + super.onOverScrolled, + super.onZoomScaleChanged, + @Deprecated('Use onSafeBrowsingHit instead') + super.androidOnSafeBrowsingHit, + super.onSafeBrowsingHit, + @Deprecated('Use onPermissionRequest instead') + super.androidOnPermissionRequest, + super.onPermissionRequest, + @Deprecated('Use onGeolocationPermissionsShowPrompt instead') + super.androidOnGeolocationPermissionsShowPrompt, + super.onGeolocationPermissionsShowPrompt, + @Deprecated('Use onGeolocationPermissionsHidePrompt instead') + super.androidOnGeolocationPermissionsHidePrompt, + super.onGeolocationPermissionsHidePrompt, + @Deprecated('Use shouldInterceptRequest instead') + super.androidShouldInterceptRequest, + super.shouldInterceptRequest, + @Deprecated('Use onRenderProcessGone instead') + super.androidOnRenderProcessGone, + super.onRenderProcessGone, + @Deprecated('Use onRenderProcessResponsive instead') + super.androidOnRenderProcessResponsive, + super.onRenderProcessResponsive, + @Deprecated('Use onRenderProcessUnresponsive instead') + super.androidOnRenderProcessUnresponsive, + super.onRenderProcessUnresponsive, + @Deprecated('Use onFormResubmission instead') + super.androidOnFormResubmission, + super.onFormResubmission, + @Deprecated('Use onZoomScaleChanged instead') super.androidOnScaleChanged, + @Deprecated('Use onReceivedIcon instead') super.androidOnReceivedIcon, + super.onReceivedIcon, + @Deprecated('Use onReceivedTouchIconUrl instead') + super.androidOnReceivedTouchIconUrl, + super.onReceivedTouchIconUrl, + @Deprecated('Use onJsBeforeUnload instead') super.androidOnJsBeforeUnload, + super.onJsBeforeUnload, + @Deprecated('Use onReceivedLoginRequest instead') + super.androidOnReceivedLoginRequest, + super.onReceivedLoginRequest, + super.onPermissionRequestCanceled, + super.onRequestFocus, + @Deprecated('Use onWebContentProcessDidTerminate instead') + super.iosOnWebContentProcessDidTerminate, + super.onWebContentProcessDidTerminate, + @Deprecated( + 'Use onDidReceiveServerRedirectForProvisionalNavigation instead') + super.iosOnDidReceiveServerRedirectForProvisionalNavigation, + super.onDidReceiveServerRedirectForProvisionalNavigation, + @Deprecated('Use onNavigationResponse instead') + super.iosOnNavigationResponse, + super.onNavigationResponse, + @Deprecated('Use shouldAllowDeprecatedTLS instead') + super.iosShouldAllowDeprecatedTLS, + super.shouldAllowDeprecatedTLS, + super.onCameraCaptureStateChanged, + super.onMicrophoneCaptureStateChanged, + super.onContentSizeChanged, + super.initialUrlRequest, + super.initialFile, + super.initialData, + @Deprecated('Use initialSettings instead') super.initialOptions, + super.initialSettings, + super.contextMenu, + super.initialUserScripts, + this.pullToRefreshController, + this.findInteractionController}); + + /// Creates a [IOSHeadlessInAppWebViewCreationParams] instance based on [PlatformHeadlessInAppWebViewCreationParams]. + IOSHeadlessInAppWebViewCreationParams.fromPlatformHeadlessInAppWebViewCreationParams( + PlatformHeadlessInAppWebViewCreationParams params) + : this( + controllerFromPlatform: params.controllerFromPlatform, + initialSize: params.initialSize, + windowId: params.windowId, + onWebViewCreated: params.onWebViewCreated, + onLoadStart: params.onLoadStart, + onLoadStop: params.onLoadStop, + onLoadError: params.onLoadError, + onReceivedError: params.onReceivedError, + onLoadHttpError: params.onLoadHttpError, + onReceivedHttpError: params.onReceivedHttpError, + onProgressChanged: params.onProgressChanged, + onConsoleMessage: params.onConsoleMessage, + shouldOverrideUrlLoading: params.shouldOverrideUrlLoading, + onLoadResource: params.onLoadResource, + onScrollChanged: params.onScrollChanged, + onDownloadStart: params.onDownloadStart, + onDownloadStartRequest: params.onDownloadStartRequest, + onLoadResourceCustomScheme: params.onLoadResourceCustomScheme, + onLoadResourceWithCustomScheme: + params.onLoadResourceWithCustomScheme, + onCreateWindow: params.onCreateWindow, + onCloseWindow: params.onCloseWindow, + onJsAlert: params.onJsAlert, + onJsConfirm: params.onJsConfirm, + onJsPrompt: params.onJsPrompt, + onReceivedHttpAuthRequest: params.onReceivedHttpAuthRequest, + onReceivedServerTrustAuthRequest: + params.onReceivedServerTrustAuthRequest, + onReceivedClientCertRequest: params.onReceivedClientCertRequest, + onFindResultReceived: params.onFindResultReceived, + shouldInterceptAjaxRequest: params.shouldInterceptAjaxRequest, + onAjaxReadyStateChange: params.onAjaxReadyStateChange, + onAjaxProgress: params.onAjaxProgress, + shouldInterceptFetchRequest: params.shouldInterceptFetchRequest, + onUpdateVisitedHistory: params.onUpdateVisitedHistory, + onPrint: params.onPrint, + onPrintRequest: params.onPrintRequest, + onLongPressHitTestResult: params.onLongPressHitTestResult, + onEnterFullscreen: params.onEnterFullscreen, + onExitFullscreen: params.onExitFullscreen, + onPageCommitVisible: params.onPageCommitVisible, + onTitleChanged: params.onTitleChanged, + onWindowFocus: params.onWindowFocus, + onWindowBlur: params.onWindowBlur, + onOverScrolled: params.onOverScrolled, + onZoomScaleChanged: params.onZoomScaleChanged, + androidOnSafeBrowsingHit: params.androidOnSafeBrowsingHit, + onSafeBrowsingHit: params.onSafeBrowsingHit, + androidOnPermissionRequest: params.androidOnPermissionRequest, + onPermissionRequest: params.onPermissionRequest, + androidOnGeolocationPermissionsShowPrompt: + params.androidOnGeolocationPermissionsShowPrompt, + onGeolocationPermissionsShowPrompt: + params.onGeolocationPermissionsShowPrompt, + androidOnGeolocationPermissionsHidePrompt: + params.androidOnGeolocationPermissionsHidePrompt, + onGeolocationPermissionsHidePrompt: + params.onGeolocationPermissionsHidePrompt, + androidShouldInterceptRequest: params.androidShouldInterceptRequest, + shouldInterceptRequest: params.shouldInterceptRequest, + androidOnRenderProcessGone: params.androidOnRenderProcessGone, + onRenderProcessGone: params.onRenderProcessGone, + androidOnRenderProcessResponsive: + params.androidOnRenderProcessResponsive, + onRenderProcessResponsive: params.onRenderProcessResponsive, + androidOnRenderProcessUnresponsive: + params.androidOnRenderProcessUnresponsive, + onRenderProcessUnresponsive: params.onRenderProcessUnresponsive, + androidOnFormResubmission: params.androidOnFormResubmission, + onFormResubmission: params.onFormResubmission, + androidOnScaleChanged: params.androidOnScaleChanged, + androidOnReceivedIcon: params.androidOnReceivedIcon, + onReceivedIcon: params.onReceivedIcon, + androidOnReceivedTouchIconUrl: params.androidOnReceivedTouchIconUrl, + onReceivedTouchIconUrl: params.onReceivedTouchIconUrl, + androidOnJsBeforeUnload: params.androidOnJsBeforeUnload, + onJsBeforeUnload: params.onJsBeforeUnload, + androidOnReceivedLoginRequest: params.androidOnReceivedLoginRequest, + onReceivedLoginRequest: params.onReceivedLoginRequest, + onPermissionRequestCanceled: params.onPermissionRequestCanceled, + onRequestFocus: params.onRequestFocus, + iosOnWebContentProcessDidTerminate: + params.iosOnWebContentProcessDidTerminate, + onWebContentProcessDidTerminate: + params.onWebContentProcessDidTerminate, + iosOnDidReceiveServerRedirectForProvisionalNavigation: + params.iosOnDidReceiveServerRedirectForProvisionalNavigation, + onDidReceiveServerRedirectForProvisionalNavigation: + params.onDidReceiveServerRedirectForProvisionalNavigation, + iosOnNavigationResponse: params.iosOnNavigationResponse, + onNavigationResponse: params.onNavigationResponse, + iosShouldAllowDeprecatedTLS: params.iosShouldAllowDeprecatedTLS, + shouldAllowDeprecatedTLS: params.shouldAllowDeprecatedTLS, + onCameraCaptureStateChanged: params.onCameraCaptureStateChanged, + onMicrophoneCaptureStateChanged: + params.onMicrophoneCaptureStateChanged, + onContentSizeChanged: params.onContentSizeChanged, + initialUrlRequest: params.initialUrlRequest, + initialFile: params.initialFile, + initialData: params.initialData, + initialOptions: params.initialOptions, + initialSettings: params.initialSettings, + contextMenu: params.contextMenu, + initialUserScripts: params.initialUserScripts, + pullToRefreshController: params.pullToRefreshController + as IOSPullToRefreshController?, + findInteractionController: params.findInteractionController + as IOSFindInteractionController?); + + @override + final IOSFindInteractionController? findInteractionController; + + @override + final IOSPullToRefreshController? pullToRefreshController; +} + +///{@macro flutter_inappwebview_platform_interface.PlatformHeadlessInAppWebView} +class IOSHeadlessInAppWebView extends PlatformHeadlessInAppWebView + with ChannelController { + @override + late final String id; + + bool _started = false; + bool _running = false; + + static const MethodChannel _sharedChannel = + const MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview'); + + IOSInAppWebViewController? _webViewController; + + /// Constructs a [IOSHeadlessInAppWebView]. + IOSHeadlessInAppWebView(PlatformHeadlessInAppWebViewCreationParams params) + : super.implementation( + params is IOSHeadlessInAppWebViewCreationParams + ? params + : IOSHeadlessInAppWebViewCreationParams + .fromPlatformHeadlessInAppWebViewCreationParams(params), + ) { + id = IdGenerator.generate(); + } + + @override + IOSInAppWebViewController? get webViewController => _webViewController; + + dynamic _controllerFromPlatform; + + IOSHeadlessInAppWebViewCreationParams get _iosParams => + params as IOSHeadlessInAppWebViewCreationParams; + + _init() { + _webViewController = IOSInAppWebViewController( + IOSInAppWebViewControllerCreationParams( + id: id, webviewParams: params), + ); + _controllerFromPlatform = + params.controllerFromPlatform?.call(_webViewController!) ?? + _webViewController!; + _iosParams.pullToRefreshController?.init(id); + _iosParams.findInteractionController?.init(id); + channel = + MethodChannel('com.pichillilorenzo/flutter_headless_inappwebview_$id'); + handler = _handleMethod; + initMethodCallHandler(); + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onWebViewCreated": + if (params.onWebViewCreated != null && _webViewController != null) { + params.onWebViewCreated!(_controllerFromPlatform); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + Future run() async { + if (_started) { + return; + } + _started = true; + _init(); + + final initialSettings = params.initialSettings ?? InAppWebViewSettings(); + _inferInitialSettings(initialSettings); + + Map settingsMap = + (params.initialSettings != null ? initialSettings.toMap() : null) ?? + params.initialOptions?.toMap() ?? + initialSettings.toMap(); + + Map pullToRefreshSettings = + _iosParams.pullToRefreshController?.params.settings.toMap() ?? + _iosParams.pullToRefreshController?.params.options.toMap() ?? + PullToRefreshSettings(enabled: false).toMap(); + + Map args = {}; + args.putIfAbsent('id', () => id); + args.putIfAbsent( + 'params', + () => { + 'initialUrlRequest': params.initialUrlRequest?.toMap(), + 'initialFile': params.initialFile, + 'initialData': params.initialData?.toMap(), + 'initialSettings': settingsMap, + 'contextMenu': params.contextMenu?.toMap() ?? {}, + 'windowId': params.windowId, + 'initialUserScripts': + params.initialUserScripts?.map((e) => e.toMap()).toList() ?? + [], + 'pullToRefreshSettings': pullToRefreshSettings, + 'initialSize': params.initialSize.toMap() + }); + await _sharedChannel.invokeMethod('run', args); + _running = true; + } + + void _inferInitialSettings(InAppWebViewSettings settings) { + if (params.shouldOverrideUrlLoading != null && + settings.useShouldOverrideUrlLoading == null) { + settings.useShouldOverrideUrlLoading = true; + } + if (params.onLoadResource != null && settings.useOnLoadResource == null) { + settings.useOnLoadResource = true; + } + if (params.onDownloadStartRequest != null && + settings.useOnDownloadStart == null) { + settings.useOnDownloadStart = true; + } + if (params.shouldInterceptAjaxRequest != null && + settings.useShouldInterceptAjaxRequest == null) { + settings.useShouldInterceptAjaxRequest = true; + } + if (params.shouldInterceptFetchRequest != null && + settings.useShouldInterceptFetchRequest == null) { + settings.useShouldInterceptFetchRequest = true; + } + if (params.shouldInterceptRequest != null && + settings.useShouldInterceptRequest == null) { + settings.useShouldInterceptRequest = true; + } + if (params.onRenderProcessGone != null && + settings.useOnRenderProcessGone == null) { + settings.useOnRenderProcessGone = true; + } + if (params.onNavigationResponse != null && + settings.useOnNavigationResponse == null) { + settings.useOnNavigationResponse = true; + } + } + + @override + bool isRunning() { + return _running; + } + + @override + Future setSize(Size size) async { + if (!_running) { + return; + } + + Map args = {}; + args.putIfAbsent('size', () => size.toMap()); + await channel?.invokeMethod('setSize', args); + } + + @override + Future getSize() async { + if (!_running) { + return null; + } + + Map args = {}; + Map sizeMap = + (await channel?.invokeMethod('getSize', args))?.cast(); + return MapSize.fromMap(sizeMap); + } + + @override + Future dispose() async { + if (!_running) { + return; + } + Map args = {}; + await channel?.invokeMethod('dispose', args); + disposeChannel(); + _started = false; + _running = false; + _webViewController?.dispose(); + _webViewController = null; + _controllerFromPlatform = null; + _iosParams.pullToRefreshController?.dispose(); + _iosParams.findInteractionController?.dispose(); + } +} + +extension InternalHeadlessInAppWebView on IOSHeadlessInAppWebView { + Future internalDispose() async { + _started = false; + _running = false; + } +} diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart new file mode 100755 index 00000000..d86ce979 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview.dart @@ -0,0 +1,425 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; +import 'headless_in_app_webview.dart'; + +import '../find_interaction/find_interaction_controller.dart'; +import 'in_app_webview_controller.dart'; +import '../pull_to_refresh/main.dart'; +import '../pull_to_refresh/pull_to_refresh_controller.dart'; + +/// Object specifying creation parameters for creating a [PlatformInAppWebViewWidget]. +/// +/// Platform specific implementations can add additional fields by extending +/// this class. +class IOSInAppWebViewWidgetCreationParams + extends PlatformInAppWebViewWidgetCreationParams { + IOSInAppWebViewWidgetCreationParams( + {super.controllerFromPlatform, + super.key, + super.layoutDirection, + super.gestureRecognizers, + super.headlessWebView, + super.keepAlive, + super.preventGestureDelay, + super.windowId, + super.onWebViewCreated, + super.onLoadStart, + super.onLoadStop, + @Deprecated('Use onReceivedError instead') super.onLoadError, + super.onReceivedError, + @Deprecated("Use onReceivedHttpError instead") super.onLoadHttpError, + super.onReceivedHttpError, + super.onProgressChanged, + super.onConsoleMessage, + super.shouldOverrideUrlLoading, + super.onLoadResource, + super.onScrollChanged, + @Deprecated('Use onDownloadStartRequest instead') super.onDownloadStart, + super.onDownloadStartRequest, + @Deprecated('Use onLoadResourceWithCustomScheme instead') + super.onLoadResourceCustomScheme, + super.onLoadResourceWithCustomScheme, + super.onCreateWindow, + super.onCloseWindow, + super.onJsAlert, + super.onJsConfirm, + super.onJsPrompt, + super.onReceivedHttpAuthRequest, + super.onReceivedServerTrustAuthRequest, + super.onReceivedClientCertRequest, + @Deprecated('Use FindInteractionController.onFindResultReceived instead') + super.onFindResultReceived, + super.shouldInterceptAjaxRequest, + super.onAjaxReadyStateChange, + super.onAjaxProgress, + super.shouldInterceptFetchRequest, + super.onUpdateVisitedHistory, + @Deprecated("Use onPrintRequest instead") super.onPrint, + super.onPrintRequest, + super.onLongPressHitTestResult, + super.onEnterFullscreen, + super.onExitFullscreen, + super.onPageCommitVisible, + super.onTitleChanged, + super.onWindowFocus, + super.onWindowBlur, + super.onOverScrolled, + super.onZoomScaleChanged, + @Deprecated('Use onSafeBrowsingHit instead') + super.androidOnSafeBrowsingHit, + super.onSafeBrowsingHit, + @Deprecated('Use onPermissionRequest instead') + super.androidOnPermissionRequest, + super.onPermissionRequest, + @Deprecated('Use onGeolocationPermissionsShowPrompt instead') + super.androidOnGeolocationPermissionsShowPrompt, + super.onGeolocationPermissionsShowPrompt, + @Deprecated('Use onGeolocationPermissionsHidePrompt instead') + super.androidOnGeolocationPermissionsHidePrompt, + super.onGeolocationPermissionsHidePrompt, + @Deprecated('Use shouldInterceptRequest instead') + super.androidShouldInterceptRequest, + super.shouldInterceptRequest, + @Deprecated('Use onRenderProcessGone instead') + super.androidOnRenderProcessGone, + super.onRenderProcessGone, + @Deprecated('Use onRenderProcessResponsive instead') + super.androidOnRenderProcessResponsive, + super.onRenderProcessResponsive, + @Deprecated('Use onRenderProcessUnresponsive instead') + super.androidOnRenderProcessUnresponsive, + super.onRenderProcessUnresponsive, + @Deprecated('Use onFormResubmission instead') + super.androidOnFormResubmission, + super.onFormResubmission, + @Deprecated('Use onZoomScaleChanged instead') super.androidOnScaleChanged, + @Deprecated('Use onReceivedIcon instead') super.androidOnReceivedIcon, + super.onReceivedIcon, + @Deprecated('Use onReceivedTouchIconUrl instead') + super.androidOnReceivedTouchIconUrl, + super.onReceivedTouchIconUrl, + @Deprecated('Use onJsBeforeUnload instead') super.androidOnJsBeforeUnload, + super.onJsBeforeUnload, + @Deprecated('Use onReceivedLoginRequest instead') + super.androidOnReceivedLoginRequest, + super.onReceivedLoginRequest, + super.onPermissionRequestCanceled, + super.onRequestFocus, + @Deprecated('Use onWebContentProcessDidTerminate instead') + super.iosOnWebContentProcessDidTerminate, + super.onWebContentProcessDidTerminate, + @Deprecated( + 'Use onDidReceiveServerRedirectForProvisionalNavigation instead') + super.iosOnDidReceiveServerRedirectForProvisionalNavigation, + super.onDidReceiveServerRedirectForProvisionalNavigation, + @Deprecated('Use onNavigationResponse instead') + super.iosOnNavigationResponse, + super.onNavigationResponse, + @Deprecated('Use shouldAllowDeprecatedTLS instead') + super.iosShouldAllowDeprecatedTLS, + super.shouldAllowDeprecatedTLS, + super.onCameraCaptureStateChanged, + super.onMicrophoneCaptureStateChanged, + super.onContentSizeChanged, + super.initialUrlRequest, + super.initialFile, + super.initialData, + @Deprecated('Use initialSettings instead') super.initialOptions, + super.initialSettings, + super.contextMenu, + super.initialUserScripts, + this.pullToRefreshController, + this.findInteractionController}); + + /// Constructs a [IOSInAppWebViewWidgetCreationParams] using a + /// [PlatformInAppWebViewWidgetCreationParams]. + IOSInAppWebViewWidgetCreationParams.fromPlatformInAppWebViewWidgetCreationParams( + PlatformInAppWebViewWidgetCreationParams params) + : this( + controllerFromPlatform: params.controllerFromPlatform, + key: params.key, + layoutDirection: params.layoutDirection, + gestureRecognizers: params.gestureRecognizers, + headlessWebView: params.headlessWebView, + keepAlive: params.keepAlive, + preventGestureDelay: params.preventGestureDelay, + windowId: params.windowId, + onWebViewCreated: params.onWebViewCreated, + onLoadStart: params.onLoadStart, + onLoadStop: params.onLoadStop, + onLoadError: params.onLoadError, + onReceivedError: params.onReceivedError, + onLoadHttpError: params.onLoadHttpError, + onReceivedHttpError: params.onReceivedHttpError, + onProgressChanged: params.onProgressChanged, + onConsoleMessage: params.onConsoleMessage, + shouldOverrideUrlLoading: params.shouldOverrideUrlLoading, + onLoadResource: params.onLoadResource, + onScrollChanged: params.onScrollChanged, + onDownloadStart: params.onDownloadStart, + onDownloadStartRequest: params.onDownloadStartRequest, + onLoadResourceCustomScheme: params.onLoadResourceCustomScheme, + onLoadResourceWithCustomScheme: + params.onLoadResourceWithCustomScheme, + onCreateWindow: params.onCreateWindow, + onCloseWindow: params.onCloseWindow, + onJsAlert: params.onJsAlert, + onJsConfirm: params.onJsConfirm, + onJsPrompt: params.onJsPrompt, + onReceivedHttpAuthRequest: params.onReceivedHttpAuthRequest, + onReceivedServerTrustAuthRequest: + params.onReceivedServerTrustAuthRequest, + onReceivedClientCertRequest: params.onReceivedClientCertRequest, + onFindResultReceived: params.onFindResultReceived, + shouldInterceptAjaxRequest: params.shouldInterceptAjaxRequest, + onAjaxReadyStateChange: params.onAjaxReadyStateChange, + onAjaxProgress: params.onAjaxProgress, + shouldInterceptFetchRequest: params.shouldInterceptFetchRequest, + onUpdateVisitedHistory: params.onUpdateVisitedHistory, + onPrint: params.onPrint, + onPrintRequest: params.onPrintRequest, + onLongPressHitTestResult: params.onLongPressHitTestResult, + onEnterFullscreen: params.onEnterFullscreen, + onExitFullscreen: params.onExitFullscreen, + onPageCommitVisible: params.onPageCommitVisible, + onTitleChanged: params.onTitleChanged, + onWindowFocus: params.onWindowFocus, + onWindowBlur: params.onWindowBlur, + onOverScrolled: params.onOverScrolled, + onZoomScaleChanged: params.onZoomScaleChanged, + androidOnSafeBrowsingHit: params.androidOnSafeBrowsingHit, + onSafeBrowsingHit: params.onSafeBrowsingHit, + androidOnPermissionRequest: params.androidOnPermissionRequest, + onPermissionRequest: params.onPermissionRequest, + androidOnGeolocationPermissionsShowPrompt: + params.androidOnGeolocationPermissionsShowPrompt, + onGeolocationPermissionsShowPrompt: + params.onGeolocationPermissionsShowPrompt, + androidOnGeolocationPermissionsHidePrompt: + params.androidOnGeolocationPermissionsHidePrompt, + onGeolocationPermissionsHidePrompt: + params.onGeolocationPermissionsHidePrompt, + androidShouldInterceptRequest: params.androidShouldInterceptRequest, + shouldInterceptRequest: params.shouldInterceptRequest, + androidOnRenderProcessGone: params.androidOnRenderProcessGone, + onRenderProcessGone: params.onRenderProcessGone, + androidOnRenderProcessResponsive: + params.androidOnRenderProcessResponsive, + onRenderProcessResponsive: params.onRenderProcessResponsive, + androidOnRenderProcessUnresponsive: + params.androidOnRenderProcessUnresponsive, + onRenderProcessUnresponsive: params.onRenderProcessUnresponsive, + androidOnFormResubmission: params.androidOnFormResubmission, + onFormResubmission: params.onFormResubmission, + androidOnScaleChanged: params.androidOnScaleChanged, + androidOnReceivedIcon: params.androidOnReceivedIcon, + onReceivedIcon: params.onReceivedIcon, + androidOnReceivedTouchIconUrl: params.androidOnReceivedTouchIconUrl, + onReceivedTouchIconUrl: params.onReceivedTouchIconUrl, + androidOnJsBeforeUnload: params.androidOnJsBeforeUnload, + onJsBeforeUnload: params.onJsBeforeUnload, + androidOnReceivedLoginRequest: params.androidOnReceivedLoginRequest, + onReceivedLoginRequest: params.onReceivedLoginRequest, + onPermissionRequestCanceled: params.onPermissionRequestCanceled, + onRequestFocus: params.onRequestFocus, + iosOnWebContentProcessDidTerminate: + params.iosOnWebContentProcessDidTerminate, + onWebContentProcessDidTerminate: + params.onWebContentProcessDidTerminate, + iosOnDidReceiveServerRedirectForProvisionalNavigation: + params.iosOnDidReceiveServerRedirectForProvisionalNavigation, + onDidReceiveServerRedirectForProvisionalNavigation: + params.onDidReceiveServerRedirectForProvisionalNavigation, + iosOnNavigationResponse: params.iosOnNavigationResponse, + onNavigationResponse: params.onNavigationResponse, + iosShouldAllowDeprecatedTLS: params.iosShouldAllowDeprecatedTLS, + shouldAllowDeprecatedTLS: params.shouldAllowDeprecatedTLS, + onCameraCaptureStateChanged: params.onCameraCaptureStateChanged, + onMicrophoneCaptureStateChanged: + params.onMicrophoneCaptureStateChanged, + onContentSizeChanged: params.onContentSizeChanged, + initialUrlRequest: params.initialUrlRequest, + initialFile: params.initialFile, + initialData: params.initialData, + initialOptions: params.initialOptions, + initialSettings: params.initialSettings, + contextMenu: params.contextMenu, + initialUserScripts: params.initialUserScripts, + pullToRefreshController: params.pullToRefreshController + as IOSPullToRefreshController?, + findInteractionController: params.findInteractionController + as IOSFindInteractionController?); + + @override + final IOSFindInteractionController? findInteractionController; + + @override + final IOSPullToRefreshController? pullToRefreshController; +} + +///{@template flutter_inappwebview.InAppWebView} +///Flutter Widget for adding an **inline native WebView** integrated in the flutter widget tree. +/// +///**Supported Platforms/Implementations**: +///- IOS native WebView +///- iOS +///- Web +///{@endtemplate} +class IOSInAppWebViewWidget extends PlatformInAppWebViewWidget { + /// Constructs a [IOSInAppWebViewWidget]. + IOSInAppWebViewWidget(PlatformInAppWebViewWidgetCreationParams params) + : super.implementation( + params is IOSInAppWebViewWidgetCreationParams + ? params + : IOSInAppWebViewWidgetCreationParams + .fromPlatformInAppWebViewWidgetCreationParams(params), + ); + + IOSInAppWebViewWidgetCreationParams get _iosParams => + params as IOSInAppWebViewWidgetCreationParams; + + IOSInAppWebViewController? _controller; + + IOSHeadlessInAppWebView? get _iosHeadlessInAppWebView => + _iosParams.headlessWebView as IOSHeadlessInAppWebView?; + + @override + Widget build(BuildContext context) { + final initialSettings = + _iosParams.initialSettings ?? InAppWebViewSettings(); + _inferInitialSettings(initialSettings); + + Map settingsMap = (_iosParams.initialSettings != null + ? initialSettings.toMap() + : null) ?? + // ignore: deprecated_member_use_from_same_package + _iosParams.initialOptions?.toMap() ?? + initialSettings.toMap(); + + Map pullToRefreshSettings = + _iosParams.pullToRefreshController?.params.settings.toMap() ?? + // ignore: deprecated_member_use_from_same_package + _iosParams.pullToRefreshController?.params.options.toMap() ?? + PullToRefreshSettings(enabled: false).toMap(); + + if ((_iosParams.headlessWebView?.isRunning() ?? false) && + _iosParams.keepAlive != null) { + final headlessId = _iosParams.headlessWebView?.id; + if (headlessId != null) { + // force keep alive id to match headless webview id + _iosParams.keepAlive?.id = headlessId; + } + } + + return UiKitView( + viewType: 'com.pichillilorenzo/flutter_inappwebview', + onPlatformViewCreated: _onPlatformViewCreated, + gestureRecognizers: _iosParams.gestureRecognizers, + creationParams: { + 'initialUrlRequest': _iosParams.initialUrlRequest?.toMap(), + 'initialFile': _iosParams.initialFile, + 'initialData': _iosParams.initialData?.toMap(), + 'initialSettings': settingsMap, + 'contextMenu': _iosParams.contextMenu?.toMap() ?? {}, + 'windowId': _iosParams.windowId, + 'headlessWebViewId': _iosParams.headlessWebView?.isRunning() ?? false + ? _iosParams.headlessWebView?.id + : null, + 'initialUserScripts': + _iosParams.initialUserScripts?.map((e) => e.toMap()).toList() ?? [], + 'pullToRefreshSettings': pullToRefreshSettings, + 'keepAliveId': _iosParams.keepAlive?.id, + 'preventGestureDelay': _iosParams.preventGestureDelay + }, + creationParamsCodec: const StandardMessageCodec(), + ); + } + + void _onPlatformViewCreated(int id) { + dynamic viewId = id; + if (!kIsWeb) { + if (_iosParams.headlessWebView?.isRunning() ?? false) { + viewId = _iosParams.headlessWebView?.id; + } + viewId = _iosParams.keepAlive?.id ?? viewId ?? id; + } + _iosHeadlessInAppWebView?.internalDispose(); + _controller = IOSInAppWebViewController( + PlatformInAppWebViewControllerCreationParams( + id: viewId, webviewParams: params)); + _iosParams.pullToRefreshController?.init(viewId); + _iosParams.findInteractionController?.init(viewId); + debugLog( + className: runtimeType.toString(), + id: viewId?.toString(), + debugLoggingSettings: + PlatformInAppWebViewController.debugLoggingSettings, + method: "onWebViewCreated", + args: []); + if (_iosParams.onWebViewCreated != null) { + _iosParams.onWebViewCreated!( + params.controllerFromPlatform?.call(_controller!) ?? _controller!); + } + } + + void _inferInitialSettings(InAppWebViewSettings settings) { + if (_iosParams.shouldOverrideUrlLoading != null && + settings.useShouldOverrideUrlLoading == null) { + settings.useShouldOverrideUrlLoading = true; + } + if (_iosParams.onLoadResource != null && + settings.useOnLoadResource == null) { + settings.useOnLoadResource = true; + } + if (_iosParams.onDownloadStartRequest != null && + settings.useOnDownloadStart == null) { + settings.useOnDownloadStart = true; + } + if (_iosParams.shouldInterceptAjaxRequest != null && + settings.useShouldInterceptAjaxRequest == null) { + settings.useShouldInterceptAjaxRequest = true; + } + if (_iosParams.shouldInterceptFetchRequest != null && + settings.useShouldInterceptFetchRequest == null) { + settings.useShouldInterceptFetchRequest = true; + } + if (_iosParams.shouldInterceptRequest != null && + settings.useShouldInterceptRequest == null) { + settings.useShouldInterceptRequest = true; + } + if (_iosParams.onRenderProcessGone != null && + settings.useOnRenderProcessGone == null) { + settings.useOnRenderProcessGone = true; + } + if (_iosParams.onNavigationResponse != null && + settings.useOnNavigationResponse == null) { + settings.useOnNavigationResponse = true; + } + } + + @override + void dispose() { + dynamic viewId = _controller?.getViewId(); + debugLog( + className: runtimeType.toString(), + id: viewId?.toString(), + debugLoggingSettings: + PlatformInAppWebViewController.debugLoggingSettings, + method: "dispose", + args: []); + final isKeepAlive = _iosParams.keepAlive != null; + _controller?.dispose(isKeepAlive: isKeepAlive); + _controller = null; + _iosParams.pullToRefreshController?.dispose(isKeepAlive: isKeepAlive); + _iosParams.findInteractionController?.dispose(isKeepAlive: isKeepAlive); + } + + @override + T controllerFromPlatform(PlatformInAppWebViewController controller) { + // unused + throw UnimplementedError(); + } +} diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart new file mode 100644 index 00000000..064acee2 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart @@ -0,0 +1,2893 @@ +import 'dart:io'; +import 'dart:collection'; +import 'dart:convert'; +import 'dart:core'; +import 'dart:developer' as developer; +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import '../web_message/main.dart'; + +import '../in_app_browser/in_app_browser.dart'; +import '../web_storage/web_storage.dart'; + +import 'headless_in_app_webview.dart'; +import '_static_channel.dart'; + +import '../print_job/main.dart'; + +///List of forbidden names for JavaScript handlers. +// ignore: non_constant_identifier_names +final _JAVASCRIPT_HANDLER_FORBIDDEN_NAMES = UnmodifiableListView([ + "onLoadResource", + "shouldInterceptAjaxRequest", + "onAjaxReadyStateChange", + "onAjaxProgress", + "shouldInterceptFetchRequest", + "onPrintRequest", + "onWindowFocus", + "onWindowBlur", + "callAsyncJavaScript", + "evaluateJavaScriptWithContentWorld" +]); + +/// Object specifying creation parameters for creating a [IOSInAppWebViewController]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformInAppWebViewControllerCreationParams] for +/// more information. +@immutable +class IOSInAppWebViewControllerCreationParams + extends PlatformInAppWebViewControllerCreationParams { + /// Creates a new [IOSInAppWebViewControllerCreationParams] instance. + const IOSInAppWebViewControllerCreationParams( + {required super.id, super.webviewParams}); + + /// Creates a [IOSInAppWebViewControllerCreationParams] instance based on [PlatformInAppWebViewControllerCreationParams]. + factory IOSInAppWebViewControllerCreationParams.fromPlatformInAppWebViewControllerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformInAppWebViewControllerCreationParams params) { + return IOSInAppWebViewControllerCreationParams( + id: params.id, webviewParams: params.webviewParams); + } +} + +///Controls a WebView, such as an [InAppWebView] widget instance, a [IOSHeadlessInAppWebView] instance or [IOSInAppBrowser] WebView instance. +/// +///If you are using the [InAppWebView] widget, an [InAppWebViewController] instance can be obtained by setting the [InAppWebView.onWebViewCreated] +///callback. Instead, if you are using an [IOSInAppBrowser] instance, you can get it through the [IOSInAppBrowser.webViewController] attribute. +class IOSInAppWebViewController extends PlatformInAppWebViewController + with ChannelController { + static final MethodChannel _staticChannel = IN_APP_WEBVIEW_STATIC_CHANNEL; + + // List of properties to be saved and restored for keep alive feature + Map _javaScriptHandlersMap = + HashMap(); + Map> _userScripts = { + UserScriptInjectionTime.AT_DOCUMENT_START: [], + UserScriptInjectionTime.AT_DOCUMENT_END: [] + }; + Set _webMessageListenerObjNames = Set(); + Map _injectedScriptsFromURL = {}; + Set _webMessageChannels = Set(); + Set _webMessageListeners = Set(); + + // static map that contains the properties to be saved and restored for keep alive feature + static final Map + _keepAliveMap = {}; + + IOSInAppBrowser? _inAppBrowser; + + PlatformInAppBrowserEvents? get _inAppBrowserEventHandler => + _inAppBrowser?.eventHandler; + + dynamic _controllerFromPlatform; + + @override + late IOSWebStorage webStorage; + + IOSInAppWebViewController( + PlatformInAppWebViewControllerCreationParams params) + : super.implementation(params + is IOSInAppWebViewControllerCreationParams + ? params + : IOSInAppWebViewControllerCreationParams + .fromPlatformInAppWebViewControllerCreationParams(params)) { + channel = MethodChannel('com.pichillilorenzo/flutter_inappwebview_$id'); + handler = handleMethod; + initMethodCallHandler(); + + final initialUserScripts = webviewParams?.initialUserScripts; + if (initialUserScripts != null) { + for (final userScript in initialUserScripts) { + if (userScript.injectionTime == + UserScriptInjectionTime.AT_DOCUMENT_START) { + this + ._userScripts[UserScriptInjectionTime.AT_DOCUMENT_START] + ?.add(userScript); + } else { + this + ._userScripts[UserScriptInjectionTime.AT_DOCUMENT_END] + ?.add(userScript); + } + } + } + + this._init(params); + } + + static final IOSInAppWebViewController _staticValue = + IOSInAppWebViewController( + IOSInAppWebViewControllerCreationParams(id: null)); + + factory IOSInAppWebViewController.static() { + return _staticValue; + } + + IOSInAppWebViewController.fromInAppBrowser( + PlatformInAppWebViewControllerCreationParams params, + MethodChannel channel, + IOSInAppBrowser inAppBrowser, + UnmodifiableListView? initialUserScripts) + : super.implementation( + params is IOSInAppWebViewControllerCreationParams + ? params + : IOSInAppWebViewControllerCreationParams + .fromPlatformInAppWebViewControllerCreationParams(params)) { + this.channel = channel; + this._inAppBrowser = inAppBrowser; + + if (initialUserScripts != null) { + for (final userScript in initialUserScripts) { + if (userScript.injectionTime == + UserScriptInjectionTime.AT_DOCUMENT_START) { + this + ._userScripts[UserScriptInjectionTime.AT_DOCUMENT_START] + ?.add(userScript); + } else { + this + ._userScripts[UserScriptInjectionTime.AT_DOCUMENT_END] + ?.add(userScript); + } + } + } + this._init(params); + } + + void _init(PlatformInAppWebViewControllerCreationParams params) { + _controllerFromPlatform = + params.webviewParams?.controllerFromPlatform?.call(this) ?? this; + + webStorage = IOSWebStorage(IOSWebStorageCreationParams( + localStorage: IOSLocalStorage.defaultStorage(controller: this), + sessionStorage: + IOSSessionStorage.defaultStorage(controller: this))); + + if (params.webviewParams is PlatformInAppWebViewWidgetCreationParams) { + final keepAlive = + (params.webviewParams as PlatformInAppWebViewWidgetCreationParams) + .keepAlive; + if (keepAlive != null) { + InAppWebViewControllerKeepAliveProps? props = _keepAliveMap[keepAlive]; + if (props == null) { + // save controller properties to restore it later + _keepAliveMap[keepAlive] = InAppWebViewControllerKeepAliveProps( + injectedScriptsFromURL: _injectedScriptsFromURL, + javaScriptHandlersMap: _javaScriptHandlersMap, + userScripts: _userScripts, + webMessageListenerObjNames: _webMessageListenerObjNames, + webMessageChannels: _webMessageChannels, + webMessageListeners: _webMessageListeners); + } else { + // restore controller properties + _injectedScriptsFromURL = props.injectedScriptsFromURL; + _javaScriptHandlersMap = props.javaScriptHandlersMap; + _userScripts = props.userScripts; + _webMessageListenerObjNames = props.webMessageListenerObjNames; + _webMessageChannels = + props.webMessageChannels as Set; + _webMessageListeners = + props.webMessageListeners as Set; + } + } + } + } + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + name: _inAppBrowser == null + ? "WebView" + : _inAppBrowser.runtimeType.toString(), + id: (getViewId() ?? _inAppBrowser?.id).toString(), + debugLoggingSettings: + PlatformInAppWebViewController.debugLoggingSettings, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + if (PlatformInAppWebViewController.debugLoggingSettings.enabled && + call.method != "onCallJsHandler") { + _debugLog(call.method, call.arguments); + } + + switch (call.method) { + case "onLoadStart": + _injectedScriptsFromURL.clear(); + if ((webviewParams != null && webviewParams!.onLoadStart != null) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + if (webviewParams != null && webviewParams!.onLoadStart != null) + webviewParams!.onLoadStart!(_controllerFromPlatform, uri); + else + _inAppBrowserEventHandler!.onLoadStart(uri); + } + break; + case "onLoadStop": + if ((webviewParams != null && webviewParams!.onLoadStop != null) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + if (webviewParams != null && webviewParams!.onLoadStop != null) + webviewParams!.onLoadStop!(_controllerFromPlatform, uri); + else + _inAppBrowserEventHandler!.onLoadStop(uri); + } + break; + case "onReceivedError": + if ((webviewParams != null && + (webviewParams!.onReceivedError != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.onLoadError != null)) || + _inAppBrowserEventHandler != null) { + WebResourceRequest request = WebResourceRequest.fromMap( + call.arguments["request"].cast())!; + WebResourceError error = WebResourceError.fromMap( + call.arguments["error"].cast())!; + var isForMainFrame = request.isForMainFrame ?? false; + + if (webviewParams != null) { + if (webviewParams!.onReceivedError != null) + webviewParams!.onReceivedError!( + _controllerFromPlatform, request, error); + else if (isForMainFrame) { + // ignore: deprecated_member_use_from_same_package + webviewParams!.onLoadError!(_controllerFromPlatform, request.url, + error.type.toNativeValue() ?? -1, error.description); + } + } else { + if (isForMainFrame) { + _inAppBrowserEventHandler!.onLoadError(request.url, + error.type.toNativeValue() ?? -1, error.description); + } + _inAppBrowserEventHandler!.onReceivedError(request, error); + } + } + break; + case "onReceivedHttpError": + if ((webviewParams != null && + (webviewParams!.onReceivedHttpError != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.onLoadHttpError != null)) || + _inAppBrowserEventHandler != null) { + WebResourceRequest request = WebResourceRequest.fromMap( + call.arguments["request"].cast())!; + WebResourceResponse errorResponse = WebResourceResponse.fromMap( + call.arguments["errorResponse"].cast())!; + var isForMainFrame = request.isForMainFrame ?? false; + + if (webviewParams != null) { + if (webviewParams!.onReceivedHttpError != null) + webviewParams!.onReceivedHttpError!( + _controllerFromPlatform, request, errorResponse); + else if (isForMainFrame) { + // ignore: deprecated_member_use_from_same_package + webviewParams!.onLoadHttpError!( + _controllerFromPlatform, + request.url, + errorResponse.statusCode ?? -1, + errorResponse.reasonPhrase ?? ''); + } + } else { + if (isForMainFrame) { + _inAppBrowserEventHandler!.onLoadHttpError( + request.url, + errorResponse.statusCode ?? -1, + errorResponse.reasonPhrase ?? ''); + } + _inAppBrowserEventHandler! + .onReceivedHttpError(request, errorResponse); + } + } + break; + case "onProgressChanged": + if ((webviewParams != null && + webviewParams!.onProgressChanged != null) || + _inAppBrowserEventHandler != null) { + int progress = call.arguments["progress"]; + if (webviewParams != null && webviewParams!.onProgressChanged != null) + webviewParams!.onProgressChanged!( + _controllerFromPlatform, progress); + else + _inAppBrowserEventHandler!.onProgressChanged(progress); + } + break; + case "shouldOverrideUrlLoading": + if ((webviewParams != null && + webviewParams!.shouldOverrideUrlLoading != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + NavigationAction navigationAction = + NavigationAction.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.shouldOverrideUrlLoading != null) + return (await webviewParams!.shouldOverrideUrlLoading!( + _controllerFromPlatform, navigationAction)) + ?.toNativeValue(); + return (await _inAppBrowserEventHandler! + .shouldOverrideUrlLoading(navigationAction)) + ?.toNativeValue(); + } + break; + case "onConsoleMessage": + if ((webviewParams != null && + webviewParams!.onConsoleMessage != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + ConsoleMessage consoleMessage = ConsoleMessage.fromMap(arguments)!; + if (webviewParams != null && webviewParams!.onConsoleMessage != null) + webviewParams!.onConsoleMessage!( + _controllerFromPlatform, consoleMessage); + else + _inAppBrowserEventHandler!.onConsoleMessage(consoleMessage); + } + break; + case "onScrollChanged": + if ((webviewParams != null && webviewParams!.onScrollChanged != null) || + _inAppBrowserEventHandler != null) { + int x = call.arguments["x"]; + int y = call.arguments["y"]; + if (webviewParams != null && webviewParams!.onScrollChanged != null) + webviewParams!.onScrollChanged!(_controllerFromPlatform, x, y); + else + _inAppBrowserEventHandler!.onScrollChanged(x, y); + } + break; + case "onDownloadStartRequest": + if ((webviewParams != null && + // ignore: deprecated_member_use_from_same_package + (webviewParams!.onDownloadStart != null || + webviewParams!.onDownloadStartRequest != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + DownloadStartRequest downloadStartRequest = + DownloadStartRequest.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onDownloadStartRequest != null) + webviewParams!.onDownloadStartRequest!( + _controllerFromPlatform, downloadStartRequest); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.onDownloadStart!( + _controllerFromPlatform, downloadStartRequest.url); + } + } else { + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler! + .onDownloadStart(downloadStartRequest.url); + _inAppBrowserEventHandler! + .onDownloadStartRequest(downloadStartRequest); + } + } + break; + case "onLoadResourceWithCustomScheme": + if ((webviewParams != null && + (webviewParams!.onLoadResourceWithCustomScheme != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.onLoadResourceCustomScheme != null)) || + _inAppBrowserEventHandler != null) { + Map requestMap = + call.arguments["request"].cast(); + WebResourceRequest request = WebResourceRequest.fromMap(requestMap)!; + + if (webviewParams != null) { + if (webviewParams!.onLoadResourceWithCustomScheme != null) + return (await webviewParams!.onLoadResourceWithCustomScheme!( + _controllerFromPlatform, request)) + ?.toMap(); + else { + return (await params + .webviewParams! + // ignore: deprecated_member_use_from_same_package + .onLoadResourceCustomScheme!( + _controllerFromPlatform, request.url)) + ?.toMap(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onLoadResourceWithCustomScheme(request)) ?? + (await _inAppBrowserEventHandler! + .onLoadResourceCustomScheme(request.url))) + ?.toMap(); + } + } + break; + case "onCreateWindow": + if ((webviewParams != null && webviewParams!.onCreateWindow != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + CreateWindowAction createWindowAction = + CreateWindowAction.fromMap(arguments)!; + + if (webviewParams != null && webviewParams!.onCreateWindow != null) + return await webviewParams!.onCreateWindow!( + _controllerFromPlatform, createWindowAction); + else + return await _inAppBrowserEventHandler! + .onCreateWindow(createWindowAction); + } + break; + case "onCloseWindow": + if (webviewParams != null && webviewParams!.onCloseWindow != null) + webviewParams!.onCloseWindow!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onCloseWindow(); + break; + case "onTitleChanged": + if ((webviewParams != null && webviewParams!.onTitleChanged != null) || + _inAppBrowserEventHandler != null) { + String? title = call.arguments["title"]; + if (webviewParams != null && webviewParams!.onTitleChanged != null) + webviewParams!.onTitleChanged!(_controllerFromPlatform, title); + else + _inAppBrowserEventHandler!.onTitleChanged(title); + } + break; + case "onGeolocationPermissionsShowPrompt": + if ((webviewParams != null && + (webviewParams!.onGeolocationPermissionsShowPrompt != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnGeolocationPermissionsShowPrompt != + null)) || + _inAppBrowserEventHandler != null) { + String origin = call.arguments["origin"]; + + if (webviewParams != null) { + if (webviewParams!.onGeolocationPermissionsShowPrompt != null) + return (await webviewParams!.onGeolocationPermissionsShowPrompt!( + _controllerFromPlatform, origin)) + ?.toMap(); + else { + return (await params + .webviewParams! + // ignore: deprecated_member_use_from_same_package + .androidOnGeolocationPermissionsShowPrompt!( + _controllerFromPlatform, origin)) + ?.toMap(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onGeolocationPermissionsShowPrompt(origin)) ?? + (await _inAppBrowserEventHandler! + .androidOnGeolocationPermissionsShowPrompt(origin))) + ?.toMap(); + } + } + break; + case "onGeolocationPermissionsHidePrompt": + if (webviewParams != null && + (webviewParams!.onGeolocationPermissionsHidePrompt != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnGeolocationPermissionsHidePrompt != + null)) { + if (webviewParams!.onGeolocationPermissionsHidePrompt != null) + webviewParams! + .onGeolocationPermissionsHidePrompt!(_controllerFromPlatform); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnGeolocationPermissionsHidePrompt!( + _controllerFromPlatform); + } + } else if (_inAppBrowserEventHandler != null) { + _inAppBrowserEventHandler!.onGeolocationPermissionsHidePrompt(); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler! + .androidOnGeolocationPermissionsHidePrompt(); + } + break; + case "shouldInterceptRequest": + if ((webviewParams != null && + (webviewParams!.shouldInterceptRequest != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidShouldInterceptRequest != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + WebResourceRequest request = WebResourceRequest.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.shouldInterceptRequest != null) + return (await webviewParams!.shouldInterceptRequest!( + _controllerFromPlatform, request)) + ?.toMap(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidShouldInterceptRequest!( + _controllerFromPlatform, request)) + ?.toMap(); + } + } else { + return ((await _inAppBrowserEventHandler! + .shouldInterceptRequest(request)) ?? + (await _inAppBrowserEventHandler! + .androidShouldInterceptRequest(request))) + ?.toMap(); + } + } + break; + case "onRenderProcessUnresponsive": + if ((webviewParams != null && + (webviewParams!.onRenderProcessUnresponsive != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnRenderProcessUnresponsive != + null)) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + + if (webviewParams != null) { + if (webviewParams!.onRenderProcessUnresponsive != null) + return (await webviewParams!.onRenderProcessUnresponsive!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidOnRenderProcessUnresponsive!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onRenderProcessUnresponsive(uri)) ?? + (await _inAppBrowserEventHandler! + .androidOnRenderProcessUnresponsive(uri))) + ?.toNativeValue(); + } + } + break; + case "onRenderProcessResponsive": + if ((webviewParams != null && + (webviewParams!.onRenderProcessResponsive != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnRenderProcessResponsive != null)) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + + if (webviewParams != null) { + if (webviewParams!.onRenderProcessResponsive != null) + return (await webviewParams!.onRenderProcessResponsive!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidOnRenderProcessResponsive!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onRenderProcessResponsive(uri)) ?? + (await _inAppBrowserEventHandler! + .androidOnRenderProcessResponsive(uri))) + ?.toNativeValue(); + } + } + break; + case "onRenderProcessGone": + if ((webviewParams != null && + (webviewParams!.onRenderProcessGone != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnRenderProcessGone != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + RenderProcessGoneDetail detail = + RenderProcessGoneDetail.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onRenderProcessGone != null) + webviewParams!.onRenderProcessGone!( + _controllerFromPlatform, detail); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnRenderProcessGone!( + _controllerFromPlatform, detail); + } + } else if (_inAppBrowserEventHandler != null) { + _inAppBrowserEventHandler!.onRenderProcessGone(detail); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler!.androidOnRenderProcessGone(detail); + } + } + break; + case "onFormResubmission": + if ((webviewParams != null && + (webviewParams!.onFormResubmission != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnFormResubmission != null)) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + + if (webviewParams != null) { + if (webviewParams!.onFormResubmission != null) + return (await webviewParams!.onFormResubmission!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidOnFormResubmission!( + _controllerFromPlatform, uri)) + ?.toNativeValue(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onFormResubmission(uri)) ?? + // ignore: deprecated_member_use_from_same_package + (await _inAppBrowserEventHandler! + .androidOnFormResubmission(uri))) + ?.toNativeValue(); + } + } + break; + case "onZoomScaleChanged": + if ((webviewParams != null && + // ignore: deprecated_member_use_from_same_package + (webviewParams!.androidOnScaleChanged != null || + webviewParams!.onZoomScaleChanged != null)) || + _inAppBrowserEventHandler != null) { + double oldScale = call.arguments["oldScale"]; + double newScale = call.arguments["newScale"]; + + if (webviewParams != null) { + if (webviewParams!.onZoomScaleChanged != null) + webviewParams!.onZoomScaleChanged!( + _controllerFromPlatform, oldScale, newScale); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnScaleChanged!( + _controllerFromPlatform, oldScale, newScale); + } + } else { + _inAppBrowserEventHandler!.onZoomScaleChanged(oldScale, newScale); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler! + .androidOnScaleChanged(oldScale, newScale); + } + } + break; + case "onReceivedIcon": + if ((webviewParams != null && + (webviewParams!.onReceivedIcon != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedIcon != null)) || + _inAppBrowserEventHandler != null) { + Uint8List icon = + Uint8List.fromList(call.arguments["icon"].cast()); + + if (webviewParams != null) { + if (webviewParams!.onReceivedIcon != null) + webviewParams!.onReceivedIcon!(_controllerFromPlatform, icon); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedIcon!( + _controllerFromPlatform, icon); + } + } else { + _inAppBrowserEventHandler!.onReceivedIcon(icon); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler!.androidOnReceivedIcon(icon); + } + } + break; + case "onReceivedTouchIconUrl": + if ((webviewParams != null && + (webviewParams!.onReceivedTouchIconUrl != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedTouchIconUrl != null)) || + _inAppBrowserEventHandler != null) { + String url = call.arguments["url"]; + bool precomposed = call.arguments["precomposed"]; + WebUri uri = WebUri(url); + + if (webviewParams != null) { + if (webviewParams!.onReceivedTouchIconUrl != null) + webviewParams!.onReceivedTouchIconUrl!( + _controllerFromPlatform, uri, precomposed); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedTouchIconUrl!( + _controllerFromPlatform, uri, precomposed); + } + } else { + _inAppBrowserEventHandler!.onReceivedTouchIconUrl(uri, precomposed); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler! + .androidOnReceivedTouchIconUrl(uri, precomposed); + } + } + break; + case "onJsAlert": + if ((webviewParams != null && webviewParams!.onJsAlert != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + JsAlertRequest jsAlertRequest = JsAlertRequest.fromMap(arguments)!; + + if (webviewParams != null && webviewParams!.onJsAlert != null) + return (await webviewParams!.onJsAlert!( + _controllerFromPlatform, jsAlertRequest)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler!.onJsAlert(jsAlertRequest)) + ?.toMap(); + } + break; + case "onJsConfirm": + if ((webviewParams != null && webviewParams!.onJsConfirm != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + JsConfirmRequest jsConfirmRequest = + JsConfirmRequest.fromMap(arguments)!; + + if (webviewParams != null && webviewParams!.onJsConfirm != null) + return (await webviewParams!.onJsConfirm!( + _controllerFromPlatform, jsConfirmRequest)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler! + .onJsConfirm(jsConfirmRequest)) + ?.toMap(); + } + break; + case "onJsPrompt": + if ((webviewParams != null && webviewParams!.onJsPrompt != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + JsPromptRequest jsPromptRequest = JsPromptRequest.fromMap(arguments)!; + + if (webviewParams != null && webviewParams!.onJsPrompt != null) + return (await webviewParams!.onJsPrompt!( + _controllerFromPlatform, jsPromptRequest)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler! + .onJsPrompt(jsPromptRequest)) + ?.toMap(); + } + break; + case "onJsBeforeUnload": + if ((webviewParams != null && + (webviewParams!.onJsBeforeUnload != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnJsBeforeUnload != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + JsBeforeUnloadRequest jsBeforeUnloadRequest = + JsBeforeUnloadRequest.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onJsBeforeUnload != null) + return (await webviewParams!.onJsBeforeUnload!( + _controllerFromPlatform, jsBeforeUnloadRequest)) + ?.toMap(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidOnJsBeforeUnload!( + _controllerFromPlatform, jsBeforeUnloadRequest)) + ?.toMap(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onJsBeforeUnload(jsBeforeUnloadRequest)) ?? + (await _inAppBrowserEventHandler! + .androidOnJsBeforeUnload(jsBeforeUnloadRequest))) + ?.toMap(); + } + } + break; + case "onSafeBrowsingHit": + if ((webviewParams != null && + (webviewParams!.onSafeBrowsingHit != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnSafeBrowsingHit != null)) || + _inAppBrowserEventHandler != null) { + String url = call.arguments["url"]; + SafeBrowsingThreat? threatType = + SafeBrowsingThreat.fromNativeValue(call.arguments["threatType"]); + WebUri uri = WebUri(url); + + if (webviewParams != null) { + if (webviewParams!.onSafeBrowsingHit != null) + return (await webviewParams!.onSafeBrowsingHit!( + _controllerFromPlatform, uri, threatType)) + ?.toMap(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.androidOnSafeBrowsingHit!( + _controllerFromPlatform, uri, threatType)) + ?.toMap(); + } + } else { + return ((await _inAppBrowserEventHandler! + .onSafeBrowsingHit(uri, threatType)) ?? + (await _inAppBrowserEventHandler! + .androidOnSafeBrowsingHit(uri, threatType))) + ?.toMap(); + } + } + break; + case "onReceivedLoginRequest": + if ((webviewParams != null && + (webviewParams!.onReceivedLoginRequest != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedLoginRequest != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + LoginRequest loginRequest = LoginRequest.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onReceivedLoginRequest != null) + webviewParams!.onReceivedLoginRequest!( + _controllerFromPlatform, loginRequest); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnReceivedLoginRequest!( + _controllerFromPlatform, loginRequest); + } + } else { + _inAppBrowserEventHandler!.onReceivedLoginRequest(loginRequest); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler! + .androidOnReceivedLoginRequest(loginRequest); + } + } + break; + case "onPermissionRequestCanceled": + if ((webviewParams != null && + webviewParams!.onPermissionRequestCanceled != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + PermissionRequest permissionRequest = + PermissionRequest.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onPermissionRequestCanceled != null) + webviewParams!.onPermissionRequestCanceled!( + _controllerFromPlatform, permissionRequest); + else + _inAppBrowserEventHandler! + .onPermissionRequestCanceled(permissionRequest); + } + break; + case "onRequestFocus": + if ((webviewParams != null && webviewParams!.onRequestFocus != null) || + _inAppBrowserEventHandler != null) { + if (webviewParams != null && webviewParams!.onRequestFocus != null) + webviewParams!.onRequestFocus!(_controllerFromPlatform); + else + _inAppBrowserEventHandler!.onRequestFocus(); + } + break; + case "onReceivedHttpAuthRequest": + if ((webviewParams != null && + webviewParams!.onReceivedHttpAuthRequest != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + HttpAuthenticationChallenge challenge = + HttpAuthenticationChallenge.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onReceivedHttpAuthRequest != null) + return (await webviewParams!.onReceivedHttpAuthRequest!( + _controllerFromPlatform, challenge)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler! + .onReceivedHttpAuthRequest(challenge)) + ?.toMap(); + } + break; + case "onReceivedServerTrustAuthRequest": + if ((webviewParams != null && + webviewParams!.onReceivedServerTrustAuthRequest != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + ServerTrustChallenge challenge = + ServerTrustChallenge.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onReceivedServerTrustAuthRequest != null) + return (await webviewParams!.onReceivedServerTrustAuthRequest!( + _controllerFromPlatform, challenge)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler! + .onReceivedServerTrustAuthRequest(challenge)) + ?.toMap(); + } + break; + case "onReceivedClientCertRequest": + if ((webviewParams != null && + webviewParams!.onReceivedClientCertRequest != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + ClientCertChallenge challenge = + ClientCertChallenge.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onReceivedClientCertRequest != null) + return (await webviewParams!.onReceivedClientCertRequest!( + _controllerFromPlatform, challenge)) + ?.toMap(); + else + return (await _inAppBrowserEventHandler! + .onReceivedClientCertRequest(challenge)) + ?.toMap(); + } + break; + case "onFindResultReceived": + if ((webviewParams != null && + (webviewParams!.onFindResultReceived != null || + (webviewParams!.findInteractionController != null && + webviewParams!.findInteractionController!.params + .onFindResultReceived != + null))) || + _inAppBrowserEventHandler != null) { + int activeMatchOrdinal = call.arguments["activeMatchOrdinal"]; + int numberOfMatches = call.arguments["numberOfMatches"]; + bool isDoneCounting = call.arguments["isDoneCounting"]; + if (webviewParams != null) { + if (webviewParams!.findInteractionController != null && + webviewParams!.findInteractionController!.params + .onFindResultReceived != + null) + webviewParams! + .findInteractionController!.params.onFindResultReceived!( + webviewParams!.findInteractionController!, + activeMatchOrdinal, + numberOfMatches, + isDoneCounting); + else + webviewParams!.onFindResultReceived!(_controllerFromPlatform, + activeMatchOrdinal, numberOfMatches, isDoneCounting); + } else { + if (_inAppBrowser!.findInteractionController != null && + _inAppBrowser! + .findInteractionController!.onFindResultReceived != + null) + _inAppBrowser!.findInteractionController!.onFindResultReceived!( + webviewParams!.findInteractionController!, + activeMatchOrdinal, + numberOfMatches, + isDoneCounting); + else + _inAppBrowserEventHandler!.onFindResultReceived( + activeMatchOrdinal, numberOfMatches, isDoneCounting); + } + } + break; + case "onPermissionRequest": + if ((webviewParams != null && + (webviewParams!.onPermissionRequest != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.androidOnPermissionRequest != null)) || + _inAppBrowserEventHandler != null) { + String origin = call.arguments["origin"]; + List resources = call.arguments["resources"].cast(); + + Map arguments = + call.arguments.cast(); + PermissionRequest permissionRequest = + PermissionRequest.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onPermissionRequest != null) + return (await webviewParams!.onPermissionRequest!( + _controllerFromPlatform, permissionRequest)) + ?.toMap(); + else { + return (await webviewParams!.androidOnPermissionRequest!( + _controllerFromPlatform, origin, resources)) + ?.toMap(); + } + } else { + return (await _inAppBrowserEventHandler! + .onPermissionRequest(permissionRequest)) + ?.toMap() ?? + (await _inAppBrowserEventHandler! + .androidOnPermissionRequest(origin, resources)) + ?.toMap(); + } + } + break; + case "onUpdateVisitedHistory": + if ((webviewParams != null && + webviewParams!.onUpdateVisitedHistory != null) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + bool? isReload = call.arguments["isReload"]; + WebUri? uri = url != null ? WebUri(url) : null; + if (webviewParams != null && + webviewParams!.onUpdateVisitedHistory != null) + webviewParams!.onUpdateVisitedHistory!( + _controllerFromPlatform, uri, isReload); + else + _inAppBrowserEventHandler!.onUpdateVisitedHistory(uri, isReload); + } + break; + case "onWebContentProcessDidTerminate": + if (webviewParams != null && + (webviewParams!.onWebContentProcessDidTerminate != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.iosOnWebContentProcessDidTerminate != null)) { + if (webviewParams!.onWebContentProcessDidTerminate != null) + webviewParams! + .onWebContentProcessDidTerminate!(_controllerFromPlatform); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams! + .iosOnWebContentProcessDidTerminate!(_controllerFromPlatform); + } + } else if (_inAppBrowserEventHandler != null) { + _inAppBrowserEventHandler!.onWebContentProcessDidTerminate(); + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler!.iosOnWebContentProcessDidTerminate(); + } + break; + case "onPageCommitVisible": + if ((webviewParams != null && + webviewParams!.onPageCommitVisible != null) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + if (webviewParams != null && + webviewParams!.onPageCommitVisible != null) + webviewParams!.onPageCommitVisible!(_controllerFromPlatform, uri); + else + _inAppBrowserEventHandler!.onPageCommitVisible(uri); + } + break; + case "onDidReceiveServerRedirectForProvisionalNavigation": + if (webviewParams != null && + (webviewParams! + .onDidReceiveServerRedirectForProvisionalNavigation != + null || + params + .webviewParams! + // ignore: deprecated_member_use_from_same_package + .iosOnDidReceiveServerRedirectForProvisionalNavigation != + null)) { + if (webviewParams! + .onDidReceiveServerRedirectForProvisionalNavigation != + null) + webviewParams!.onDidReceiveServerRedirectForProvisionalNavigation!( + _controllerFromPlatform); + else { + params + .webviewParams! + // ignore: deprecated_member_use_from_same_package + .iosOnDidReceiveServerRedirectForProvisionalNavigation!( + _controllerFromPlatform); + } + } else if (_inAppBrowserEventHandler != null) { + _inAppBrowserEventHandler! + .onDidReceiveServerRedirectForProvisionalNavigation(); + _inAppBrowserEventHandler! + .iosOnDidReceiveServerRedirectForProvisionalNavigation(); + } + break; + case "onNavigationResponse": + if ((webviewParams != null && + (webviewParams!.onNavigationResponse != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.iosOnNavigationResponse != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + // ignore: deprecated_member_use_from_same_package + IOSWKNavigationResponse iosOnNavigationResponse = + // ignore: deprecated_member_use_from_same_package + IOSWKNavigationResponse.fromMap(arguments)!; + + NavigationResponse navigationResponse = + NavigationResponse.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.onNavigationResponse != null) + return (await webviewParams!.onNavigationResponse!( + _controllerFromPlatform, navigationResponse)) + ?.toNativeValue(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.iosOnNavigationResponse!( + _controllerFromPlatform, iosOnNavigationResponse)) + ?.toNativeValue(); + } + } else { + return (await _inAppBrowserEventHandler! + .onNavigationResponse(navigationResponse)) + ?.toNativeValue() ?? + (await _inAppBrowserEventHandler! + .iosOnNavigationResponse(iosOnNavigationResponse)) + ?.toNativeValue(); + } + } + break; + case "shouldAllowDeprecatedTLS": + if ((webviewParams != null && + (webviewParams!.shouldAllowDeprecatedTLS != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.iosShouldAllowDeprecatedTLS != null)) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + URLAuthenticationChallenge challenge = + URLAuthenticationChallenge.fromMap(arguments)!; + + if (webviewParams != null) { + if (webviewParams!.shouldAllowDeprecatedTLS != null) + return (await webviewParams!.shouldAllowDeprecatedTLS!( + _controllerFromPlatform, challenge)) + ?.toNativeValue(); + else { + // ignore: deprecated_member_use_from_same_package + return (await webviewParams!.iosShouldAllowDeprecatedTLS!( + _controllerFromPlatform, challenge)) + ?.toNativeValue(); + } + } else { + return (await _inAppBrowserEventHandler! + .shouldAllowDeprecatedTLS(challenge)) + ?.toNativeValue() ?? + // ignore: deprecated_member_use_from_same_package + (await _inAppBrowserEventHandler! + .iosShouldAllowDeprecatedTLS(challenge)) + ?.toNativeValue(); + } + } + break; + case "onLongPressHitTestResult": + if ((webviewParams != null && + webviewParams!.onLongPressHitTestResult != null) || + _inAppBrowserEventHandler != null) { + Map arguments = + call.arguments.cast(); + InAppWebViewHitTestResult hitTestResult = + InAppWebViewHitTestResult.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onLongPressHitTestResult != null) + webviewParams!.onLongPressHitTestResult!( + _controllerFromPlatform, hitTestResult); + else + _inAppBrowserEventHandler!.onLongPressHitTestResult(hitTestResult); + } + break; + case "onCreateContextMenu": + ContextMenu? contextMenu; + if (webviewParams != null && webviewParams!.contextMenu != null) { + contextMenu = webviewParams!.contextMenu; + } else if (_inAppBrowserEventHandler != null && + _inAppBrowser!.contextMenu != null) { + contextMenu = _inAppBrowser!.contextMenu; + } + + if (contextMenu != null && contextMenu.onCreateContextMenu != null) { + Map arguments = + call.arguments.cast(); + InAppWebViewHitTestResult hitTestResult = + InAppWebViewHitTestResult.fromMap(arguments)!; + + contextMenu.onCreateContextMenu!(hitTestResult); + } + break; + case "onHideContextMenu": + ContextMenu? contextMenu; + if (webviewParams != null && webviewParams!.contextMenu != null) { + contextMenu = webviewParams!.contextMenu; + } else if (_inAppBrowserEventHandler != null && + _inAppBrowser!.contextMenu != null) { + contextMenu = _inAppBrowser!.contextMenu; + } + + if (contextMenu != null && contextMenu.onHideContextMenu != null) { + contextMenu.onHideContextMenu!(); + } + break; + case "onContextMenuActionItemClicked": + ContextMenu? contextMenu; + if (webviewParams != null && webviewParams!.contextMenu != null) { + contextMenu = webviewParams!.contextMenu; + } else if (_inAppBrowserEventHandler != null && + _inAppBrowser!.contextMenu != null) { + contextMenu = _inAppBrowser!.contextMenu; + } + + if (contextMenu != null) { + int? androidId = call.arguments["androidId"]; + String? iosId = call.arguments["iosId"]; + dynamic id = call.arguments["id"]; + String title = call.arguments["title"]; + + ContextMenuItem menuItemClicked = ContextMenuItem( + id: id, + // ignore: deprecated_member_use_from_same_package + androidId: androidId, + // ignore: deprecated_member_use_from_same_package + iosId: iosId, + title: title, + action: null); + + for (var menuItem in contextMenu.menuItems) { + if (menuItem.id == id) { + menuItemClicked = menuItem; + if (menuItem.action != null) { + menuItem.action!(); + } + break; + } + } + + if (contextMenu.onContextMenuActionItemClicked != null) { + contextMenu.onContextMenuActionItemClicked!(menuItemClicked); + } + } + break; + case "onEnterFullscreen": + if (webviewParams != null && webviewParams!.onEnterFullscreen != null) + webviewParams!.onEnterFullscreen!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onEnterFullscreen(); + break; + case "onExitFullscreen": + if (webviewParams != null && webviewParams!.onExitFullscreen != null) + webviewParams!.onExitFullscreen!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onExitFullscreen(); + break; + case "onOverScrolled": + if ((webviewParams != null && webviewParams!.onOverScrolled != null) || + _inAppBrowserEventHandler != null) { + int x = call.arguments["x"]; + int y = call.arguments["y"]; + bool clampedX = call.arguments["clampedX"]; + bool clampedY = call.arguments["clampedY"]; + + if (webviewParams != null && webviewParams!.onOverScrolled != null) + webviewParams!.onOverScrolled!( + _controllerFromPlatform, x, y, clampedX, clampedY); + else + _inAppBrowserEventHandler!.onOverScrolled(x, y, clampedX, clampedY); + } + break; + case "onWindowFocus": + if (webviewParams != null && webviewParams!.onWindowFocus != null) + webviewParams!.onWindowFocus!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onWindowFocus(); + break; + case "onWindowBlur": + if (webviewParams != null && webviewParams!.onWindowBlur != null) + webviewParams!.onWindowBlur!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onWindowBlur(); + break; + case "onPrintRequest": + if ((webviewParams != null && + (webviewParams!.onPrintRequest != null || + // ignore: deprecated_member_use_from_same_package + webviewParams!.onPrint != null)) || + _inAppBrowserEventHandler != null) { + String? url = call.arguments["url"]; + String? printJobId = call.arguments["printJobId"]; + WebUri? uri = url != null ? WebUri(url) : null; + IOSPrintJobController? printJob = printJobId != null + ? IOSPrintJobController( + IOSPrintJobControllerCreationParams(id: printJobId)) + : null; + + if (webviewParams != null) { + if (webviewParams!.onPrintRequest != null) + return await webviewParams!.onPrintRequest!( + _controllerFromPlatform, uri, printJob); + else { + // ignore: deprecated_member_use_from_same_package + webviewParams!.onPrint!(_controllerFromPlatform, uri); + return false; + } + } else { + // ignore: deprecated_member_use_from_same_package + _inAppBrowserEventHandler!.onPrint(uri); + return await _inAppBrowserEventHandler! + .onPrintRequest(uri, printJob); + } + } + break; + case "onInjectedScriptLoaded": + String id = call.arguments[0]; + var onLoadCallback = _injectedScriptsFromURL[id]?.onLoad; + if ((webviewParams != null || _inAppBrowserEventHandler != null) && + onLoadCallback != null) { + onLoadCallback(); + } + break; + case "onInjectedScriptError": + String id = call.arguments[0]; + var onErrorCallback = _injectedScriptsFromURL[id]?.onError; + if ((webviewParams != null || _inAppBrowserEventHandler != null) && + onErrorCallback != null) { + onErrorCallback(); + } + break; + case "onCameraCaptureStateChanged": + if ((webviewParams != null && + webviewParams!.onCameraCaptureStateChanged != null) || + _inAppBrowserEventHandler != null) { + var oldState = + MediaCaptureState.fromNativeValue(call.arguments["oldState"]); + var newState = + MediaCaptureState.fromNativeValue(call.arguments["newState"]); + + if (webviewParams != null && + webviewParams!.onCameraCaptureStateChanged != null) + webviewParams!.onCameraCaptureStateChanged!( + _controllerFromPlatform, oldState, newState); + else + _inAppBrowserEventHandler! + .onCameraCaptureStateChanged(oldState, newState); + } + break; + case "onMicrophoneCaptureStateChanged": + if ((webviewParams != null && + webviewParams!.onMicrophoneCaptureStateChanged != null) || + _inAppBrowserEventHandler != null) { + var oldState = + MediaCaptureState.fromNativeValue(call.arguments["oldState"]); + var newState = + MediaCaptureState.fromNativeValue(call.arguments["newState"]); + + if (webviewParams != null && + webviewParams!.onMicrophoneCaptureStateChanged != null) + webviewParams!.onMicrophoneCaptureStateChanged!( + _controllerFromPlatform, oldState, newState); + else + _inAppBrowserEventHandler! + .onMicrophoneCaptureStateChanged(oldState, newState); + } + break; + case "onContentSizeChanged": + if ((webviewParams != null && + webviewParams!.onContentSizeChanged != null) || + _inAppBrowserEventHandler != null) { + var oldContentSize = MapSize.fromMap( + call.arguments["oldContentSize"]?.cast())!; + var newContentSize = MapSize.fromMap( + call.arguments["newContentSize"]?.cast())!; + + if (webviewParams != null && + webviewParams!.onContentSizeChanged != null) + webviewParams!.onContentSizeChanged!( + _controllerFromPlatform, oldContentSize, newContentSize); + else + _inAppBrowserEventHandler! + .onContentSizeChanged(oldContentSize, newContentSize); + } + break; + case "onCallJsHandler": + String handlerName = call.arguments["handlerName"]; + // decode args to json + List args = jsonDecode(call.arguments["args"]); + + _debugLog(handlerName, args); + + switch (handlerName) { + case "onLoadResource": + if ((webviewParams != null && + webviewParams!.onLoadResource != null) || + _inAppBrowserEventHandler != null) { + Map arguments = args[0].cast(); + arguments["startTime"] = arguments["startTime"] is int + ? arguments["startTime"].toDouble() + : arguments["startTime"]; + arguments["duration"] = arguments["duration"] is int + ? arguments["duration"].toDouble() + : arguments["duration"]; + + var response = LoadedResource.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onLoadResource != null) + webviewParams!.onLoadResource!( + _controllerFromPlatform, response); + else + _inAppBrowserEventHandler!.onLoadResource(response); + } + return null; + case "shouldInterceptAjaxRequest": + if ((webviewParams != null && + webviewParams!.shouldInterceptAjaxRequest != null) || + _inAppBrowserEventHandler != null) { + Map arguments = args[0].cast(); + AjaxRequest request = AjaxRequest.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.shouldInterceptAjaxRequest != null) + return jsonEncode( + await params.webviewParams!.shouldInterceptAjaxRequest!( + _controllerFromPlatform, request)); + else + return jsonEncode(await _inAppBrowserEventHandler! + .shouldInterceptAjaxRequest(request)); + } + return null; + case "onAjaxReadyStateChange": + if ((webviewParams != null && + webviewParams!.onAjaxReadyStateChange != null) || + _inAppBrowserEventHandler != null) { + Map arguments = args[0].cast(); + AjaxRequest request = AjaxRequest.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onAjaxReadyStateChange != null) + return (await webviewParams!.onAjaxReadyStateChange!( + _controllerFromPlatform, request)) + ?.toNativeValue(); + else + return (await _inAppBrowserEventHandler! + .onAjaxReadyStateChange(request)) + ?.toNativeValue(); + } + return null; + case "onAjaxProgress": + if ((webviewParams != null && + webviewParams!.onAjaxProgress != null) || + _inAppBrowserEventHandler != null) { + Map arguments = args[0].cast(); + AjaxRequest request = AjaxRequest.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.onAjaxProgress != null) + return (await webviewParams!.onAjaxProgress!( + _controllerFromPlatform, request)) + ?.toNativeValue(); + else + return (await _inAppBrowserEventHandler! + .onAjaxProgress(request)) + ?.toNativeValue(); + } + return null; + case "shouldInterceptFetchRequest": + if ((webviewParams != null && + webviewParams!.shouldInterceptFetchRequest != null) || + _inAppBrowserEventHandler != null) { + Map arguments = args[0].cast(); + FetchRequest request = FetchRequest.fromMap(arguments)!; + + if (webviewParams != null && + webviewParams!.shouldInterceptFetchRequest != null) + return jsonEncode( + await webviewParams!.shouldInterceptFetchRequest!( + _controllerFromPlatform, request)); + else + return jsonEncode(await _inAppBrowserEventHandler! + .shouldInterceptFetchRequest(request)); + } + return null; + case "onWindowFocus": + if (webviewParams != null && webviewParams!.onWindowFocus != null) + webviewParams!.onWindowFocus!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onWindowFocus(); + return null; + case "onWindowBlur": + if (webviewParams != null && webviewParams!.onWindowBlur != null) + webviewParams!.onWindowBlur!(_controllerFromPlatform); + else if (_inAppBrowserEventHandler != null) + _inAppBrowserEventHandler!.onWindowBlur(); + return null; + case "onInjectedScriptLoaded": + String id = args[0]; + var onLoadCallback = _injectedScriptsFromURL[id]?.onLoad; + if ((webviewParams != null || _inAppBrowserEventHandler != null) && + onLoadCallback != null) { + onLoadCallback(); + } + return null; + case "onInjectedScriptError": + String id = args[0]; + var onErrorCallback = _injectedScriptsFromURL[id]?.onError; + if ((webviewParams != null || _inAppBrowserEventHandler != null) && + onErrorCallback != null) { + onErrorCallback(); + } + return null; + } + + if (_javaScriptHandlersMap.containsKey(handlerName)) { + // convert result to json + try { + return jsonEncode(await _javaScriptHandlersMap[handlerName]!(args)); + } catch (error, stacktrace) { + developer.log(error.toString() + '\n' + stacktrace.toString(), + name: 'JavaScript Handler "$handlerName"'); + throw Exception(error.toString().replaceFirst('Exception: ', '')); + } + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + @override + Future getUrl() async { + Map args = {}; + String? url = await channel?.invokeMethod('getUrl', args); + return url != null ? WebUri(url) : null; + } + + @override + Future getTitle() async { + Map args = {}; + return await channel?.invokeMethod('getTitle', args); + } + + @override + Future getProgress() async { + Map args = {}; + return await channel?.invokeMethod('getProgress', args); + } + + @override + Future getHtml() async { + String? html; + + InAppWebViewSettings? settings = await getSettings(); + if (settings != null && settings.javaScriptEnabled == true) { + html = await evaluateJavascript( + source: "window.document.getElementsByTagName('html')[0].outerHTML;"); + if (html != null && html.isNotEmpty) return html; + } + + var webviewUrl = await getUrl(); + if (webviewUrl == null) { + return html; + } + + if (webviewUrl.isScheme("file")) { + var assetPathSplitted = webviewUrl.toString().split("/flutter_assets/"); + var assetPath = assetPathSplitted[assetPathSplitted.length - 1]; + try { + var bytes = await rootBundle.load(assetPath); + html = utf8.decode(bytes.buffer.asUint8List()); + } catch (e) {} + } else { + try { + HttpClient client = HttpClient(); + var htmlRequest = await client.getUrl(webviewUrl); + html = + await (await htmlRequest.close()).transform(Utf8Decoder()).join(); + } catch (e) { + developer.log(e.toString(), name: this.runtimeType.toString()); + } + } + + return html; + } + + @override + Future> getFavicons() async { + List favicons = []; + + var webviewUrl = await getUrl(); + + if (webviewUrl == null) { + return favicons; + } + + String? manifestUrl; + + var html = await getHtml(); + if (html == null || html.isEmpty) { + return favicons; + } + var assetPathBase; + + if (webviewUrl.isScheme("file")) { + var assetPathSplitted = webviewUrl.toString().split("/flutter_assets/"); + assetPathBase = assetPathSplitted[0] + "/flutter_assets/"; + } + + InAppWebViewSettings? settings = await getSettings(); + if (settings != null && settings.javaScriptEnabled == true) { + List> links = (await evaluateJavascript(source: """ +(function() { + var linkNodes = document.head.getElementsByTagName("link"); + var links = []; + for (var i = 0; i < linkNodes.length; i++) { + var linkNode = linkNodes[i]; + if (linkNode.rel === 'manifest') { + links.push( + { + rel: linkNode.rel, + href: linkNode.href, + sizes: null + } + ); + } else if (linkNode.rel != null && linkNode.rel.indexOf('icon') >= 0) { + links.push( + { + rel: linkNode.rel, + href: linkNode.href, + sizes: linkNode.sizes != null && linkNode.sizes.value != "" ? linkNode.sizes.value : null + } + ); + } + } + return links; +})(); +"""))?.cast>() ?? []; + for (var link in links) { + if (link["rel"] == "manifest") { + manifestUrl = link["href"]; + if (!_isUrlAbsolute(manifestUrl!)) { + if (manifestUrl.startsWith("/")) { + manifestUrl = manifestUrl.substring(1); + } + manifestUrl = ((assetPathBase == null) + ? webviewUrl.scheme + "://" + webviewUrl.host + "/" + : assetPathBase) + + manifestUrl; + } + continue; + } + favicons.addAll(_createFavicons(webviewUrl, assetPathBase, link["href"], + link["rel"], link["sizes"], false)); + } + } + + // try to get /favicon.ico + try { + HttpClient client = HttpClient(); + var faviconUrl = + webviewUrl.scheme + "://" + webviewUrl.host + "/favicon.ico"; + var faviconUri = WebUri(faviconUrl); + var headRequest = await client.headUrl(faviconUri); + var headResponse = await headRequest.close(); + if (headResponse.statusCode == 200) { + favicons.add(Favicon(url: faviconUri, rel: "shortcut icon")); + } + } catch (e) { + developer.log("/favicon.ico file not found: " + e.toString(), + name: this.runtimeType.toString()); + } + + // try to get the manifest file + HttpClientRequest? manifestRequest; + HttpClientResponse? manifestResponse; + bool manifestFound = false; + if (manifestUrl == null) { + manifestUrl = + webviewUrl.scheme + "://" + webviewUrl.host + "/manifest.json"; + } + try { + HttpClient client = HttpClient(); + manifestRequest = await client.getUrl(Uri.parse(manifestUrl)); + manifestResponse = await manifestRequest.close(); + manifestFound = manifestResponse.statusCode == 200 && + manifestResponse.headers.contentType?.mimeType == "application/json"; + } catch (e) { + developer.log("Manifest file not found: " + e.toString(), + name: this.runtimeType.toString()); + } + + if (manifestFound) { + try { + Map manifest = json + .decode(await manifestResponse!.transform(Utf8Decoder()).join()); + if (manifest.containsKey("icons")) { + for (Map icon in manifest["icons"]) { + favicons.addAll(_createFavicons(webviewUrl, assetPathBase, + icon["src"], icon["rel"], icon["sizes"], true)); + } + } + } on FormatException catch (_) { + /// The [manifestResponse] might not has a valid JSON string, catch and + /// ignore the error + } + } + + return favicons; + } + + bool _isUrlAbsolute(String url) { + return url.startsWith("http://") || url.startsWith("https://"); + } + + List _createFavicons(WebUri url, String? assetPathBase, + String urlIcon, String? rel, String? sizes, bool isManifest) { + List favicons = []; + + List urlSplitted = urlIcon.split("/"); + if (!_isUrlAbsolute(urlIcon)) { + if (urlIcon.startsWith("/")) { + urlIcon = urlIcon.substring(1); + } + urlIcon = ((assetPathBase == null) + ? url.scheme + "://" + url.host + "/" + : assetPathBase) + + urlIcon; + } + if (isManifest) { + rel = (sizes != null) + ? urlSplitted[urlSplitted.length - 1] + .replaceFirst("-" + sizes, "") + .split(" ")[0] + .split(".")[0] + : null; + } + if (sizes != null && sizes.isNotEmpty && sizes != "any") { + List sizesSplitted = sizes.split(" "); + for (String size in sizesSplitted) { + int width = int.parse(size.split("x")[0]); + int height = int.parse(size.split("x")[1]); + favicons.add(Favicon( + url: WebUri(urlIcon), rel: rel, width: width, height: height)); + } + } else { + favicons.add( + Favicon(url: WebUri(urlIcon), rel: rel, width: null, height: null)); + } + + return favicons; + } + + @override + Future loadUrl( + {required URLRequest urlRequest, + @Deprecated('Use allowingReadAccessTo instead') + Uri? iosAllowingReadAccessTo, + WebUri? allowingReadAccessTo}) async { + assert(urlRequest.url != null && urlRequest.url.toString().isNotEmpty); + assert( + allowingReadAccessTo == null || allowingReadAccessTo.isScheme("file")); + assert(iosAllowingReadAccessTo == null || + iosAllowingReadAccessTo.isScheme("file")); + + Map args = {}; + args.putIfAbsent('urlRequest', () => urlRequest.toMap()); + args.putIfAbsent( + 'allowingReadAccessTo', + () => + allowingReadAccessTo?.toString() ?? + iosAllowingReadAccessTo?.toString()); + await channel?.invokeMethod('loadUrl', args); + } + + @override + Future postUrl( + {required WebUri url, required Uint8List postData}) async { + assert(url.toString().isNotEmpty); + Map args = {}; + args.putIfAbsent('url', () => url.toString()); + args.putIfAbsent('postData', () => postData); + await channel?.invokeMethod('postUrl', args); + } + + @override + Future loadData( + {required String data, + String mimeType = "text/html", + String encoding = "utf8", + WebUri? baseUrl, + @Deprecated('Use historyUrl instead') Uri? androidHistoryUrl, + WebUri? historyUrl, + @Deprecated('Use allowingReadAccessTo instead') + Uri? iosAllowingReadAccessTo, + WebUri? allowingReadAccessTo}) async { + assert( + allowingReadAccessTo == null || allowingReadAccessTo.isScheme("file")); + assert(iosAllowingReadAccessTo == null || + iosAllowingReadAccessTo.isScheme("file")); + + Map args = {}; + args.putIfAbsent('data', () => data); + args.putIfAbsent('mimeType', () => mimeType); + args.putIfAbsent('encoding', () => encoding); + args.putIfAbsent('baseUrl', () => baseUrl?.toString() ?? "about:blank"); + args.putIfAbsent( + 'historyUrl', + () => + historyUrl?.toString() ?? + androidHistoryUrl?.toString() ?? + "about:blank"); + args.putIfAbsent( + 'allowingReadAccessTo', + () => + allowingReadAccessTo?.toString() ?? + iosAllowingReadAccessTo?.toString()); + await channel?.invokeMethod('loadData', args); + } + + @override + Future loadFile({required String assetFilePath}) async { + assert(assetFilePath.isNotEmpty); + Map args = {}; + args.putIfAbsent('assetFilePath', () => assetFilePath); + await channel?.invokeMethod('loadFile', args); + } + + @override + Future reload() async { + Map args = {}; + await channel?.invokeMethod('reload', args); + } + + @override + Future goBack() async { + Map args = {}; + await channel?.invokeMethod('goBack', args); + } + + @override + Future canGoBack() async { + Map args = {}; + return await channel?.invokeMethod('canGoBack', args) ?? false; + } + + @override + Future goForward() async { + Map args = {}; + await channel?.invokeMethod('goForward', args); + } + + @override + Future canGoForward() async { + Map args = {}; + return await channel?.invokeMethod('canGoForward', args) ?? false; + } + + @override + Future goBackOrForward({required int steps}) async { + Map args = {}; + args.putIfAbsent('steps', () => steps); + await channel?.invokeMethod('goBackOrForward', args); + } + + @override + Future canGoBackOrForward({required int steps}) async { + Map args = {}; + args.putIfAbsent('steps', () => steps); + return await channel?.invokeMethod('canGoBackOrForward', args) ?? + false; + } + + @override + Future goTo({required WebHistoryItem historyItem}) async { + var steps = historyItem.offset; + if (steps != null) { + await goBackOrForward(steps: steps); + } + } + + @override + Future isLoading() async { + Map args = {}; + return await channel?.invokeMethod('isLoading', args) ?? false; + } + + @override + Future stopLoading() async { + Map args = {}; + await channel?.invokeMethod('stopLoading', args); + } + + @override + Future evaluateJavascript( + {required String source, ContentWorld? contentWorld}) async { + Map args = {}; + args.putIfAbsent('source', () => source); + args.putIfAbsent('contentWorld', () => contentWorld?.toMap()); + var data = await channel?.invokeMethod('evaluateJavascript', args); + if (data != null && (Util.isAndroid || Util.isWeb)) { + try { + // try to json decode the data coming from JavaScript + // otherwise return it as it is. + data = json.decode(data); + } catch (e) {} + } + return data; + } + + @override + Future injectJavascriptFileFromUrl( + {required WebUri urlFile, + ScriptHtmlTagAttributes? scriptHtmlTagAttributes}) async { + assert(urlFile.toString().isNotEmpty); + var id = scriptHtmlTagAttributes?.id; + if (scriptHtmlTagAttributes != null && id != null) { + _injectedScriptsFromURL[id] = scriptHtmlTagAttributes; + } + Map args = {}; + args.putIfAbsent('urlFile', () => urlFile.toString()); + args.putIfAbsent( + 'scriptHtmlTagAttributes', () => scriptHtmlTagAttributes?.toMap()); + await channel?.invokeMethod('injectJavascriptFileFromUrl', args); + } + + @override + Future injectJavascriptFileFromAsset( + {required String assetFilePath}) async { + String source = await rootBundle.loadString(assetFilePath); + return await evaluateJavascript(source: source); + } + + @override + Future injectCSSCode({required String source}) async { + Map args = {}; + args.putIfAbsent('source', () => source); + await channel?.invokeMethod('injectCSSCode', args); + } + + @override + Future injectCSSFileFromUrl( + {required WebUri urlFile, + CSSLinkHtmlTagAttributes? cssLinkHtmlTagAttributes}) async { + assert(urlFile.toString().isNotEmpty); + Map args = {}; + args.putIfAbsent('urlFile', () => urlFile.toString()); + args.putIfAbsent( + 'cssLinkHtmlTagAttributes', () => cssLinkHtmlTagAttributes?.toMap()); + await channel?.invokeMethod('injectCSSFileFromUrl', args); + } + + @override + Future injectCSSFileFromAsset({required String assetFilePath}) async { + String source = await rootBundle.loadString(assetFilePath); + await injectCSSCode(source: source); + } + + @override + void addJavaScriptHandler( + {required String handlerName, + required JavaScriptHandlerCallback callback}) { + assert(!_JAVASCRIPT_HANDLER_FORBIDDEN_NAMES.contains(handlerName), + '"$handlerName" is a forbidden name!'); + this._javaScriptHandlersMap[handlerName] = (callback); + } + + @override + JavaScriptHandlerCallback? removeJavaScriptHandler( + {required String handlerName}) { + return this._javaScriptHandlersMap.remove(handlerName); + } + + @override + bool hasJavaScriptHandler({required String handlerName}) { + return this._javaScriptHandlersMap.containsKey(handlerName); + } + + @override + Future takeScreenshot( + {ScreenshotConfiguration? screenshotConfiguration}) async { + Map args = {}; + args.putIfAbsent( + 'screenshotConfiguration', () => screenshotConfiguration?.toMap()); + return await channel?.invokeMethod('takeScreenshot', args); + } + + @override + @Deprecated('Use setSettings instead') + Future setOptions({required InAppWebViewGroupOptions options}) async { + InAppWebViewSettings settings = + InAppWebViewSettings.fromMap(options.toMap()) ?? InAppWebViewSettings(); + await setSettings(settings: settings); + } + + @override + @Deprecated('Use getSettings instead') + Future getOptions() async { + InAppWebViewSettings? settings = await getSettings(); + + Map? options = settings?.toMap(); + if (options != null) { + options = options.cast(); + return InAppWebViewGroupOptions.fromMap(options as Map); + } + + return null; + } + + @override + Future setSettings({required InAppWebViewSettings settings}) async { + Map args = {}; + + args.putIfAbsent('settings', () => settings.toMap()); + await channel?.invokeMethod('setSettings', args); + } + + @override + Future getSettings() async { + Map args = {}; + + Map? settings = + await channel?.invokeMethod('getSettings', args); + if (settings != null) { + settings = settings.cast(); + return InAppWebViewSettings.fromMap(settings as Map); + } + + return null; + } + + @override + Future getCopyBackForwardList() async { + Map args = {}; + Map? result = + (await channel?.invokeMethod('getCopyBackForwardList', args)) + ?.cast(); + return WebHistory.fromMap(result); + } + + @override + Future clearCache() async { + Map args = {}; + await channel?.invokeMethod('clearCache', args); + } + + @override + @Deprecated("Use FindInteractionController.findAll instead") + Future findAllAsync({required String find}) async { + Map args = {}; + args.putIfAbsent('find', () => find); + await channel?.invokeMethod('findAll', args); + } + + @override + @Deprecated("Use FindInteractionController.findNext instead") + Future findNext({required bool forward}) async { + Map args = {}; + args.putIfAbsent('forward', () => forward); + await channel?.invokeMethod('findNext', args); + } + + @override + @Deprecated("Use FindInteractionController.clearMatches instead") + Future clearMatches() async { + Map args = {}; + await channel?.invokeMethod('clearMatches', args); + } + + @override + @Deprecated("Use tRexRunnerHtml instead") + Future getTRexRunnerHtml() async { + return await tRexRunnerHtml; + } + + @override + @Deprecated("Use tRexRunnerCss instead") + Future getTRexRunnerCss() async { + return await tRexRunnerCss; + } + + @override + Future scrollTo( + {required int x, required int y, bool animated = false}) async { + Map args = {}; + args.putIfAbsent('x', () => x); + args.putIfAbsent('y', () => y); + args.putIfAbsent('animated', () => animated); + await channel?.invokeMethod('scrollTo', args); + } + + @override + Future scrollBy( + {required int x, required int y, bool animated = false}) async { + Map args = {}; + args.putIfAbsent('x', () => x); + args.putIfAbsent('y', () => y); + args.putIfAbsent('animated', () => animated); + await channel?.invokeMethod('scrollBy', args); + } + + @override + Future pauseTimers() async { + Map args = {}; + await channel?.invokeMethod('pauseTimers', args); + } + + @override + Future resumeTimers() async { + Map args = {}; + await channel?.invokeMethod('resumeTimers', args); + } + + @override + Future printCurrentPage( + {PrintJobSettings? settings}) async { + Map args = {}; + args.putIfAbsent("settings", () => settings?.toMap()); + String? jobId = + await channel?.invokeMethod('printCurrentPage', args); + if (jobId != null) { + return IOSPrintJobController( + PlatformPrintJobControllerCreationParams(id: jobId)); + } + return null; + } + + @override + Future getContentHeight() async { + Map args = {}; + var height = await channel?.invokeMethod('getContentHeight', args); + if (height == null || height == 0) { + // try to use javascript + var scrollHeight = await evaluateJavascript( + source: "document.documentElement.scrollHeight;"); + if (scrollHeight != null && scrollHeight is num) { + height = scrollHeight.toInt(); + } + } + return height; + } + + @override + Future getContentWidth() async { + Map args = {}; + var height = await channel?.invokeMethod('getContentWidth', args); + if (height == null || height == 0) { + // try to use javascript + var scrollHeight = await evaluateJavascript( + source: "document.documentElement.scrollWidth;"); + if (scrollHeight != null && scrollHeight is num) { + height = scrollHeight.toInt(); + } + } + return height; + } + + @override + Future zoomBy( + {required double zoomFactor, + @Deprecated('Use animated instead') bool? iosAnimated, + bool animated = false}) async { + assert(!Util.isAndroid || + (Util.isAndroid && zoomFactor > 0.01 && zoomFactor <= 100.0)); + + Map args = {}; + args.putIfAbsent('zoomFactor', () => zoomFactor); + args.putIfAbsent('animated', () => iosAnimated ?? animated); + return await channel?.invokeMethod('zoomBy', args); + } + + @override + Future getOriginalUrl() async { + Map args = {}; + String? url = await channel?.invokeMethod('getOriginalUrl', args); + return url != null ? WebUri(url) : null; + } + + @override + Future getZoomScale() async { + Map args = {}; + return await channel?.invokeMethod('getZoomScale', args); + } + + @override + @Deprecated('Use getZoomScale instead') + Future getScale() async { + return await getZoomScale(); + } + + @override + Future getSelectedText() async { + Map args = {}; + return await channel?.invokeMethod('getSelectedText', args); + } + + @override + Future getHitTestResult() async { + Map args = {}; + Map? hitTestResultMap = + await channel?.invokeMethod('getHitTestResult', args); + + if (hitTestResultMap == null) { + return null; + } + + hitTestResultMap = hitTestResultMap.cast(); + + InAppWebViewHitTestResultType? type = + InAppWebViewHitTestResultType.fromNativeValue( + hitTestResultMap["type"]?.toInt()); + String? extra = hitTestResultMap["extra"]; + return InAppWebViewHitTestResult(type: type, extra: extra); + } + + @override + Future clearFocus() async { + Map args = {}; + return await channel?.invokeMethod('clearFocus', args); + } + + @override + Future setContextMenu(ContextMenu? contextMenu) async { + Map args = {}; + args.putIfAbsent("contextMenu", () => contextMenu?.toMap()); + await channel?.invokeMethod('setContextMenu', args); + _inAppBrowser?.setContextMenu(contextMenu); + } + + @override + Future requestFocusNodeHref() async { + Map args = {}; + Map? result = + await channel?.invokeMethod('requestFocusNodeHref', args); + return result != null + ? RequestFocusNodeHrefResult( + url: result['url'] != null ? WebUri(result['url']) : null, + title: result['title'], + src: result['src'], + ) + : null; + } + + @override + Future requestImageRef() async { + Map args = {}; + Map? result = + await channel?.invokeMethod('requestImageRef', args); + return result != null + ? RequestImageRefResult( + url: result['url'] != null ? WebUri(result['url']) : null, + ) + : null; + } + + @override + Future> getMetaTags() async { + List metaTags = []; + + List>? metaTagList = + (await evaluateJavascript(source: """ +(function() { + var metaTags = []; + var metaTagNodes = document.head.getElementsByTagName('meta'); + for (var i = 0; i < metaTagNodes.length; i++) { + var metaTagNode = metaTagNodes[i]; + + var otherAttributes = metaTagNode.getAttributeNames(); + var nameIndex = otherAttributes.indexOf("name"); + if (nameIndex !== -1) otherAttributes.splice(nameIndex, 1); + var contentIndex = otherAttributes.indexOf("content"); + if (contentIndex !== -1) otherAttributes.splice(contentIndex, 1); + + var attrs = []; + for (var j = 0; j < otherAttributes.length; j++) { + var otherAttribute = otherAttributes[j]; + attrs.push( + { + name: otherAttribute, + value: metaTagNode.getAttribute(otherAttribute) + } + ); + } + + metaTags.push( + { + name: metaTagNode.name, + content: metaTagNode.content, + attrs: attrs + } + ); + } + return metaTags; +})(); + """))?.cast>(); + + if (metaTagList == null) { + return metaTags; + } + + for (var metaTag in metaTagList) { + var attrs = []; + + for (var metaTagAttr in metaTag["attrs"]) { + attrs.add(MetaTagAttribute( + name: metaTagAttr["name"], value: metaTagAttr["value"])); + } + + metaTags.add(MetaTag( + name: metaTag["name"], content: metaTag["content"], attrs: attrs)); + } + + return metaTags; + } + + @override + Future getMetaThemeColor() async { + Color? themeColor; + + try { + Map args = {}; + themeColor = UtilColor.fromStringRepresentation( + await channel?.invokeMethod('getMetaThemeColor', args)); + return themeColor; + } catch (e) { + // not implemented + } + + // try using javascript + var metaTags = await getMetaTags(); + MetaTag? metaTagThemeColor; + + for (var metaTag in metaTags) { + if (metaTag.name == "theme-color") { + metaTagThemeColor = metaTag; + break; + } + } + + if (metaTagThemeColor == null) { + return null; + } + + var colorValue = metaTagThemeColor.content; + + themeColor = colorValue != null + ? UtilColor.fromStringRepresentation(colorValue) + : null; + + return themeColor; + } + + @override + Future getScrollX() async { + Map args = {}; + return await channel?.invokeMethod('getScrollX', args); + } + + @override + Future getScrollY() async { + Map args = {}; + return await channel?.invokeMethod('getScrollY', args); + } + + @override + Future getCertificate() async { + Map args = {}; + Map? sslCertificateMap = + (await channel?.invokeMethod('getCertificate', args)) + ?.cast(); + return SslCertificate.fromMap(sslCertificateMap); + } + + @override + Future addUserScript({required UserScript userScript}) async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + Map args = {}; + args.putIfAbsent('userScript', () => userScript.toMap()); + if (!(_userScripts[userScript.injectionTime]?.contains(userScript) ?? + false)) { + _userScripts[userScript.injectionTime]?.add(userScript); + await channel?.invokeMethod('addUserScript', args); + } + } + + @override + Future addUserScripts({required List userScripts}) async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + for (var i = 0; i < userScripts.length; i++) { + await addUserScript(userScript: userScripts[i]); + } + } + + @override + Future removeUserScript({required UserScript userScript}) async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + var index = _userScripts[userScript.injectionTime]?.indexOf(userScript); + if (index == null || index == -1) { + return false; + } + + _userScripts[userScript.injectionTime]?.remove(userScript); + Map args = {}; + args.putIfAbsent('userScript', () => userScript.toMap()); + args.putIfAbsent('index', () => index); + await channel?.invokeMethod('removeUserScript', args); + + return true; + } + + @override + Future removeUserScriptsByGroupName({required String groupName}) async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + final List userScriptsAtDocumentStart = List.from( + _userScripts[UserScriptInjectionTime.AT_DOCUMENT_START] ?? []); + for (final userScript in userScriptsAtDocumentStart) { + if (userScript.groupName == groupName) { + _userScripts[userScript.injectionTime]?.remove(userScript); + } + } + + final List userScriptsAtDocumentEnd = + List.from(_userScripts[UserScriptInjectionTime.AT_DOCUMENT_END] ?? []); + for (final userScript in userScriptsAtDocumentEnd) { + if (userScript.groupName == groupName) { + _userScripts[userScript.injectionTime]?.remove(userScript); + } + } + + Map args = {}; + args.putIfAbsent('groupName', () => groupName); + await channel?.invokeMethod('removeUserScriptsByGroupName', args); + } + + @override + Future removeUserScripts( + {required List userScripts}) async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + for (final userScript in userScripts) { + await removeUserScript(userScript: userScript); + } + } + + @override + Future removeAllUserScripts() async { + assert(webviewParams?.windowId == null || (!Util.isIOS && !Util.isMacOS)); + + _userScripts[UserScriptInjectionTime.AT_DOCUMENT_START]?.clear(); + _userScripts[UserScriptInjectionTime.AT_DOCUMENT_END]?.clear(); + + Map args = {}; + await channel?.invokeMethod('removeAllUserScripts', args); + } + + @override + bool hasUserScript({required UserScript userScript}) { + return _userScripts[userScript.injectionTime]?.contains(userScript) ?? + false; + } + + @override + Future callAsyncJavaScript( + {required String functionBody, + Map arguments = const {}, + ContentWorld? contentWorld}) async { + Map args = {}; + args.putIfAbsent('functionBody', () => functionBody); + args.putIfAbsent('arguments', () => arguments); + args.putIfAbsent('contentWorld', () => contentWorld?.toMap()); + var data = await channel?.invokeMethod('callAsyncJavaScript', args); + if (data == null) { + return null; + } + if (Util.isAndroid) { + data = json.decode(data); + } + return CallAsyncJavaScriptResult( + value: data["value"], error: data["error"]); + } + + @override + Future saveWebArchive( + {required String filePath, bool autoname = false}) async { + if (!autoname) { + if (Util.isAndroid) { + assert(filePath.endsWith("." + WebArchiveFormat.MHT.toNativeValue())); + } else if (Util.isIOS || Util.isMacOS) { + assert(filePath + .endsWith("." + WebArchiveFormat.WEBARCHIVE.toNativeValue())); + } + } + + Map args = {}; + args.putIfAbsent("filePath", () => filePath); + args.putIfAbsent("autoname", () => autoname); + return await channel?.invokeMethod('saveWebArchive', args); + } + + @override + Future isSecureContext() async { + Map args = {}; + return await channel?.invokeMethod('isSecureContext', args) ?? false; + } + + @override + Future createWebMessageChannel() async { + Map args = {}; + Map? result = + (await channel?.invokeMethod('createWebMessageChannel', args)) + ?.cast(); + final webMessageChannel = IOSWebMessageChannel.static().fromMap(result); + if (webMessageChannel != null) { + _webMessageChannels.add(webMessageChannel); + } + return webMessageChannel; + } + + @override + Future postWebMessage( + {required WebMessage message, WebUri? targetOrigin}) async { + if (targetOrigin == null) { + targetOrigin = WebUri(''); + } + Map args = {}; + args.putIfAbsent('message', () => message.toMap()); + args.putIfAbsent('targetOrigin', () => targetOrigin.toString()); + await channel?.invokeMethod('postWebMessage', args); + } + + @override + Future addWebMessageListener( + PlatformWebMessageListener webMessageListener) async { + assert(!_webMessageListeners.contains(webMessageListener), + "${webMessageListener} was already added."); + assert( + !_webMessageListenerObjNames + .contains(webMessageListener.params.jsObjectName), + "jsObjectName ${webMessageListener.params.jsObjectName} was already added."); + _webMessageListeners.add(webMessageListener as IOSWebMessageListener); + _webMessageListenerObjNames.add(webMessageListener.params.jsObjectName); + + Map args = {}; + args.putIfAbsent('webMessageListener', () => webMessageListener.toMap()); + await channel?.invokeMethod('addWebMessageListener', args); + } + + @override + bool hasWebMessageListener(PlatformWebMessageListener webMessageListener) { + return _webMessageListeners.contains(webMessageListener) || + _webMessageListenerObjNames + .contains(webMessageListener.params.jsObjectName); + } + + @override + Future canScrollVertically() async { + Map args = {}; + return await channel?.invokeMethod('canScrollVertically', args) ?? + false; + } + + @override + Future canScrollHorizontally() async { + Map args = {}; + return await channel?.invokeMethod('canScrollHorizontally', args) ?? + false; + } + + @override + Future startSafeBrowsing() async { + Map args = {}; + return await channel?.invokeMethod('startSafeBrowsing', args) ?? + false; + } + + @override + Future clearSslPreferences() async { + Map args = {}; + await channel?.invokeMethod('clearSslPreferences', args); + } + + @override + Future pause() async { + Map args = {}; + await channel?.invokeMethod('pause', args); + } + + @override + Future resume() async { + Map args = {}; + await channel?.invokeMethod('resume', args); + } + + @override + Future pageDown({required bool bottom}) async { + Map args = {}; + args.putIfAbsent("bottom", () => bottom); + return await channel?.invokeMethod('pageDown', args) ?? false; + } + + @override + Future pageUp({required bool top}) async { + Map args = {}; + args.putIfAbsent("top", () => top); + return await channel?.invokeMethod('pageUp', args) ?? false; + } + + @override + Future zoomIn() async { + Map args = {}; + return await channel?.invokeMethod('zoomIn', args) ?? false; + } + + @override + Future zoomOut() async { + Map args = {}; + return await channel?.invokeMethod('zoomOut', args) ?? false; + } + + @override + Future clearHistory() async { + Map args = {}; + return await channel?.invokeMethod('clearHistory', args); + } + + @override + Future reloadFromOrigin() async { + Map args = {}; + await channel?.invokeMethod('reloadFromOrigin', args); + } + + @override + Future createPdf( + {@Deprecated("Use pdfConfiguration instead") + // ignore: deprecated_member_use_from_same_package + IOSWKPDFConfiguration? iosWKPdfConfiguration, + PDFConfiguration? pdfConfiguration}) async { + Map args = {}; + args.putIfAbsent('pdfConfiguration', + () => pdfConfiguration?.toMap() ?? iosWKPdfConfiguration?.toMap()); + return await channel?.invokeMethod('createPdf', args); + } + + @override + Future createWebArchiveData() async { + Map args = {}; + return await channel?.invokeMethod('createWebArchiveData', args); + } + + @override + Future hasOnlySecureContent() async { + Map args = {}; + return await channel?.invokeMethod('hasOnlySecureContent', args) ?? + false; + } + + @override + Future pauseAllMediaPlayback() async { + Map args = {}; + return await channel?.invokeMethod('pauseAllMediaPlayback', args); + } + + @override + Future setAllMediaPlaybackSuspended({required bool suspended}) async { + Map args = {}; + args.putIfAbsent("suspended", () => suspended); + return await channel?.invokeMethod('setAllMediaPlaybackSuspended', args); + } + + @override + Future closeAllMediaPresentations() async { + Map args = {}; + return await channel?.invokeMethod('closeAllMediaPresentations', args); + } + + @override + Future requestMediaPlaybackState() async { + Map args = {}; + return MediaPlaybackState.fromNativeValue( + await channel?.invokeMethod('requestMediaPlaybackState', args)); + } + + @override + Future isInFullscreen() async { + Map args = {}; + return await channel?.invokeMethod('isInFullscreen', args) ?? false; + } + + @override + Future getCameraCaptureState() async { + Map args = {}; + return MediaCaptureState.fromNativeValue( + await channel?.invokeMethod('getCameraCaptureState', args)); + } + + @override + Future setCameraCaptureState({required MediaCaptureState state}) async { + Map args = {}; + args.putIfAbsent('state', () => state.toNativeValue()); + await channel?.invokeMethod('setCameraCaptureState', args); + } + + @override + Future getMicrophoneCaptureState() async { + Map args = {}; + return MediaCaptureState.fromNativeValue( + await channel?.invokeMethod('getMicrophoneCaptureState', args)); + } + + @override + Future setMicrophoneCaptureState( + {required MediaCaptureState state}) async { + Map args = {}; + args.putIfAbsent('state', () => state.toNativeValue()); + await channel?.invokeMethod('setMicrophoneCaptureState', args); + } + + @override + Future loadSimulatedRequest( + {required URLRequest urlRequest, + required Uint8List data, + URLResponse? urlResponse}) async { + Map args = {}; + args.putIfAbsent('urlRequest', () => urlRequest.toMap()); + args.putIfAbsent('data', () => data); + args.putIfAbsent('urlResponse', () => urlResponse?.toMap()); + await channel?.invokeMethod('loadSimulatedRequest', args); + } + + @override + Future getIFrameId() async { + Map args = {}; + return await channel?.invokeMethod('getIFrameId', args); + } + + @override + Future getDefaultUserAgent() async { + Map args = {}; + return await _staticChannel.invokeMethod( + 'getDefaultUserAgent', args) ?? + ''; + } + + @override + Future clearClientCertPreferences() async { + Map args = {}; + await _staticChannel.invokeMethod('clearClientCertPreferences', args); + } + + @override + Future getSafeBrowsingPrivacyPolicyUrl() async { + Map args = {}; + String? url = await _staticChannel.invokeMethod( + 'getSafeBrowsingPrivacyPolicyUrl', args); + return url != null ? WebUri(url) : null; + } + + @override + @Deprecated("Use setSafeBrowsingAllowlist instead") + Future setSafeBrowsingWhitelist({required List hosts}) async { + return await setSafeBrowsingAllowlist(hosts: hosts); + } + + @override + Future setSafeBrowsingAllowlist({required List hosts}) async { + Map args = {}; + args.putIfAbsent('hosts', () => hosts); + return await _staticChannel.invokeMethod( + 'setSafeBrowsingAllowlist', args) ?? + false; + } + + @override + Future getCurrentWebViewPackage() async { + Map args = {}; + Map? packageInfo = + (await _staticChannel.invokeMethod('getCurrentWebViewPackage', args)) + ?.cast(); + return WebViewPackageInfo.fromMap(packageInfo); + } + + @override + Future setWebContentsDebuggingEnabled(bool debuggingEnabled) async { + Map args = {}; + args.putIfAbsent('debuggingEnabled', () => debuggingEnabled); + return await _staticChannel.invokeMethod( + 'setWebContentsDebuggingEnabled', args); + } + + @override + Future getVariationsHeader() async { + Map args = {}; + return await _staticChannel.invokeMethod( + 'getVariationsHeader', args); + } + + @override + Future isMultiProcessEnabled() async { + Map args = {}; + return await _staticChannel.invokeMethod( + 'isMultiProcessEnabled', args) ?? + false; + } + + @override + Future disableWebView() async { + Map args = {}; + await _staticChannel.invokeMethod('disableWebView', args); + } + + @override + Future handlesURLScheme(String urlScheme) async { + Map args = {}; + args.putIfAbsent('urlScheme', () => urlScheme); + return await _staticChannel.invokeMethod('handlesURLScheme', args); + } + + @override + Future disposeKeepAlive(InAppWebViewKeepAlive keepAlive) async { + Map args = {}; + args.putIfAbsent('keepAliveId', () => keepAlive.id); + await _staticChannel.invokeMethod('disposeKeepAlive', args); + _keepAliveMap[keepAlive] = null; + } + + @override + Future get tRexRunnerHtml async => await rootBundle.loadString( + 'packages/flutter_inappwebview/assets/t_rex_runner/t-rex.html'); + + @override + Future get tRexRunnerCss async => await rootBundle.loadString( + 'packages/flutter_inappwebview/assets/t_rex_runner/t-rex.css'); + + @override + dynamic getViewId() { + return id; + } + + @override + void dispose({bool isKeepAlive = false}) { + disposeChannel(removeMethodCallHandler: !isKeepAlive); + _inAppBrowser = null; + webStorage.dispose(); + if (!isKeepAlive) { + _controllerFromPlatform = null; + _javaScriptHandlersMap.clear(); + _userScripts.clear(); + _webMessageListenerObjNames.clear(); + _injectedScriptsFromURL.clear(); + for (final webMessageChannel in _webMessageChannels) { + webMessageChannel.dispose(); + } + _webMessageChannels.clear(); + for (final webMessageListener in _webMessageListeners) { + webMessageListener.dispose(); + } + _webMessageListeners.clear(); + } + } +} + +extension InternalInAppWebViewController on IOSInAppWebViewController { + get handleMethod => _handleMethod; +} diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/main.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/main.dart new file mode 100644 index 00000000..b83b0611 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/main.dart @@ -0,0 +1,3 @@ +export 'in_app_webview_controller.dart' hide InternalInAppWebViewController; +export 'in_app_webview.dart'; +export 'headless_in_app_webview.dart' hide InternalHeadlessInAppWebView; diff --git a/flutter_inappwebview_ios/lib/src/inappwebview_platform.dart b/flutter_inappwebview_ios/lib/src/inappwebview_platform.dart new file mode 100644 index 00000000..504f1f1a --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/inappwebview_platform.dart @@ -0,0 +1,273 @@ +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import 'chrome_safari_browser/chrome_safari_browser.dart'; +import 'cookie_manager.dart'; +import 'http_auth_credentials_database.dart'; +import 'find_interaction/main.dart'; +import 'in_app_browser/in_app_browser.dart'; +import 'in_app_webview/main.dart'; +import 'print_job/main.dart'; +import 'pull_to_refresh/main.dart'; +import 'web_message/main.dart'; +import 'web_storage/main.dart'; +import 'web_authentication_session/main.dart'; + +/// Implementation of [InAppWebViewPlatform] using the WebKit API. +class IOSInAppWebViewPlatform extends InAppWebViewPlatform { + /// Registers this class as the default instance of [InAppWebViewPlatform]. + static void registerWith() { + InAppWebViewPlatform.instance = IOSInAppWebViewPlatform(); + } + + /// Creates a new [IOSCookieManager]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [CookieManager] in `flutter_inappwebview` instead. + @override + IOSCookieManager createPlatformCookieManager( + PlatformCookieManagerCreationParams params, + ) { + return IOSCookieManager(params); + } + + /// Creates a new [IOSInAppWebViewController]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [InAppWebViewController] in `flutter_inappwebview` instead. + @override + IOSInAppWebViewController createPlatformInAppWebViewController( + PlatformInAppWebViewControllerCreationParams params, + ) { + return IOSInAppWebViewController(params); + } + + /// Creates a new empty [IOSInAppWebViewController] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [InAppWebViewController] in `flutter_inappwebview` instead. + @override + IOSInAppWebViewController createPlatformInAppWebViewControllerStatic() { + return IOSInAppWebViewController.static(); + } + + /// Creates a new [IOSInAppWebViewWidget]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [InAppWebView] in `flutter_inappwebview` instead. + @override + IOSInAppWebViewWidget createPlatformInAppWebViewWidget( + PlatformInAppWebViewWidgetCreationParams params, + ) { + return IOSInAppWebViewWidget(params); + } + + /// Creates a new [IOSFindInteractionController]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [FindInteractionController] in `flutter_inappwebview` instead. + @override + IOSFindInteractionController createPlatformFindInteractionController( + PlatformFindInteractionControllerCreationParams params, + ) { + return IOSFindInteractionController(params); + } + + /// Creates a new [IOSPrintJobController]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [PrintJobController] in `flutter_inappwebview` instead. + @override + IOSPrintJobController createPlatformPrintJobController( + PlatformPrintJobControllerCreationParams params, + ) { + return IOSPrintJobController(params); + } + + /// Creates a new [IOSPullToRefreshController]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [PullToRefreshController] in `flutter_inappwebview` instead. + @override + IOSPullToRefreshController createPlatformPullToRefreshController( + PlatformPullToRefreshControllerCreationParams params, + ) { + return IOSPullToRefreshController(params); + } + + /// Creates a new [IOSWebMessageChannel]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebMessageChannel] in `flutter_inappwebview` instead. + @override + IOSWebMessageChannel createPlatformWebMessageChannel( + PlatformWebMessageChannelCreationParams params, + ) { + return IOSWebMessageChannel(params); + } + + /// Creates a new empty [IOSWebMessageChannel] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebMessageChannel] in `flutter_inappwebview` instead. + @override + IOSWebMessageChannel createPlatformWebMessageChannelStatic() { + return IOSWebMessageChannel.static(); + } + + /// Creates a new [IOSWebMessageListener]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebMessageListener] in `flutter_inappwebview` instead. + @override + IOSWebMessageListener createPlatformWebMessageListener( + PlatformWebMessageListenerCreationParams params, + ) { + return IOSWebMessageListener(params); + } + + /// Creates a new [IOSJavaScriptReplyProxy]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [JavaScriptReplyProxy] in `flutter_inappwebview` instead. + @override + IOSJavaScriptReplyProxy createPlatformJavaScriptReplyProxy( + PlatformJavaScriptReplyProxyCreationParams params, + ) { + return IOSJavaScriptReplyProxy(params); + } + + /// Creates a new [IOSWebMessagePort]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebMessagePort] in `flutter_inappwebview` instead. + @override + IOSWebMessagePort createPlatformWebMessagePort( + PlatformWebMessagePortCreationParams params, + ) { + return IOSWebMessagePort(params); + } + + /// Creates a new [IOSWebStorage]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [IOSWebStorage] in `flutter_inappwebview` instead. + @override + IOSWebStorage createPlatformWebStorage( + PlatformWebStorageCreationParams params, + ) { + return IOSWebStorage(params); + } + + /// Creates a new [IOSLocalStorage]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [IOSLocalStorage] in `flutter_inappwebview` instead. + @override + IOSLocalStorage createPlatformLocalStorage( + PlatformLocalStorageCreationParams params, + ) { + return IOSLocalStorage(params); + } + + /// Creates a new [IOSSessionStorage]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [PlatformSessionStorage] in `flutter_inappwebview` instead. + @override + IOSSessionStorage createPlatformSessionStorage( + PlatformSessionStorageCreationParams params, + ) { + return IOSSessionStorage(params); + } + + /// Creates a new [IOSHeadlessInAppWebView]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [HeadlessInAppWebView] in `flutter_inappwebview` instead. + @override + IOSHeadlessInAppWebView createPlatformHeadlessInAppWebView( + PlatformHeadlessInAppWebViewCreationParams params, + ) { + return IOSHeadlessInAppWebView(params); + } + + /// Creates a new [IOSHttpAuthCredentialDatabase]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [HttpAuthCredentialDatabase] in `flutter_inappwebview` instead. + @override + IOSHttpAuthCredentialDatabase createPlatformHttpAuthCredentialDatabase( + PlatformHttpAuthCredentialDatabaseCreationParams params, + ) { + return IOSHttpAuthCredentialDatabase(params); + } + + /// Creates a new [IOSInAppBrowser]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [InAppBrowser] in `flutter_inappwebview` instead. + @override + IOSInAppBrowser createPlatformInAppBrowser( + PlatformInAppBrowserCreationParams params, + ) { + return IOSInAppBrowser(params); + } + + /// Creates a new empty [IOSInAppBrowser] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [InAppBrowser] in `flutter_inappwebview` instead. + @override + IOSInAppBrowser createPlatformInAppBrowserStatic() { + return IOSInAppBrowser.static(); + } + + /// Creates a new [IOSChromeSafariBrowser]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [ChromeSafariBrowser] in `flutter_inappwebview` instead. + @override + IOSChromeSafariBrowser createPlatformChromeSafariBrowser( + PlatformChromeSafariBrowserCreationParams params, + ) { + return IOSChromeSafariBrowser(params); + } + + /// Creates a new empty [IOSChromeSafariBrowser] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [ChromeSafariBrowser] in `flutter_inappwebview` instead. + @override + IOSChromeSafariBrowser createPlatformChromeSafariBrowserStatic() { + return IOSChromeSafariBrowser.static(); + } + + /// Creates a new empty [IOSWebStorageManager] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebStorageManager] in `flutter_inappwebview` instead. + @override + IOSWebStorageManager createPlatformWebStorageManager( + PlatformWebStorageManagerCreationParams params) { + return IOSWebStorageManager(params); + } + + /// Creates a new [IOSWebAuthenticationSession]. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebAuthenticationSession] in `flutter_inappwebview` instead. + @override + IOSWebAuthenticationSession createPlatformWebAuthenticationSession( + PlatformWebAuthenticationSessionCreationParams params) { + return IOSWebAuthenticationSession(params); + } + + /// Creates a new empty [IOSWebAuthenticationSession] to access static methods. + /// + /// This function should only be called by the app-facing package. + /// Look at using [WebAuthenticationSession] in `flutter_inappwebview` instead. + @override + IOSWebAuthenticationSession createPlatformWebAuthenticationSessionStatic() { + return IOSWebAuthenticationSession.static(); + } +} diff --git a/flutter_inappwebview_ios/lib/src/main.dart b/flutter_inappwebview_ios/lib/src/main.dart new file mode 100644 index 00000000..17f32781 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/main.dart @@ -0,0 +1,13 @@ +export 'inappwebview_platform.dart'; +export 'in_app_webview/main.dart'; +export 'in_app_browser/main.dart'; +export 'chrome_safari_browser/main.dart'; +export 'web_storage/main.dart'; +export 'cookie_manager.dart' hide InternalCookieManager; +export 'http_auth_credentials_database.dart' + hide InternalHttpAuthCredentialDatabase; +export 'pull_to_refresh/main.dart'; +export 'web_message/main.dart'; +export 'print_job/main.dart'; +export 'find_interaction/main.dart'; +export 'web_authentication_session/main.dart'; diff --git a/flutter_inappwebview_ios/lib/src/platform_util.dart b/flutter_inappwebview_ios/lib/src/platform_util.dart new file mode 100644 index 00000000..27e96478 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/platform_util.dart @@ -0,0 +1,64 @@ +import 'package:flutter/services.dart'; + +///Platform native utilities +class PlatformUtil { + static PlatformUtil? _instance; + static const MethodChannel _channel = + MethodChannel('com.pichillilorenzo/flutter_inappwebview_platformutil'); + + PlatformUtil._(); + + ///Get [PlatformUtil] instance. + static PlatformUtil instance() { + return (_instance != null) ? _instance! : _init(); + } + + static PlatformUtil _init() { + _channel.setMethodCallHandler((call) async { + try { + return await _handleMethod(call); + } on Error catch (e) { + print(e); + print(e.stackTrace); + } + }); + _instance = PlatformUtil._(); + return _instance!; + } + + static Future _handleMethod(MethodCall call) async {} + + String? _cachedSystemVersion; + + ///Get current platform system version. + Future getSystemVersion() async { + if (_cachedSystemVersion != null) { + return _cachedSystemVersion!; + } + Map args = {}; + _cachedSystemVersion = + await _channel.invokeMethod('getSystemVersion', args); + return _cachedSystemVersion!; + } + + ///Format date. + Future formatDate( + {required DateTime date, + required String format, + String locale = "en_US", + String timezone = "UTC"}) async { + Map args = {}; + args.putIfAbsent('date', () => date.millisecondsSinceEpoch); + args.putIfAbsent('format', () => format); + args.putIfAbsent('locale', () => locale); + args.putIfAbsent('timezone', () => timezone); + return await _channel.invokeMethod('formatDate', args); + } + + ///Get cookie expiration date used by Web platform. + Future getWebCookieExpirationDate({required DateTime date}) async { + Map args = {}; + args.putIfAbsent('date', () => date.millisecondsSinceEpoch); + return await _channel.invokeMethod('getWebCookieExpirationDate', args); + } +} diff --git a/flutter_inappwebview_ios/lib/src/print_job/main.dart b/flutter_inappwebview_ios/lib/src/print_job/main.dart new file mode 100644 index 00000000..4e70ad94 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/print_job/main.dart @@ -0,0 +1 @@ +export 'print_job_controller.dart'; diff --git a/flutter_inappwebview_ios/lib/src/print_job/print_job_controller.dart b/flutter_inappwebview_ios/lib/src/print_job/print_job_controller.dart new file mode 100644 index 00000000..7e74218e --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/print_job/print_job_controller.dart @@ -0,0 +1,91 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSPrintJobController]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformPrintJobControllerCreationParams] for +/// more information. +@immutable +class IOSPrintJobControllerCreationParams + extends PlatformPrintJobControllerCreationParams { + /// Creates a new [IOSPrintJobControllerCreationParams] instance. + const IOSPrintJobControllerCreationParams( + {required super.id, super.onComplete}); + + /// Creates a [IOSPrintJobControllerCreationParams] instance based on [PlatformPrintJobControllerCreationParams]. + factory IOSPrintJobControllerCreationParams.fromPlatformPrintJobControllerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformPrintJobControllerCreationParams params) { + return IOSPrintJobControllerCreationParams( + id: params.id, onComplete: params.onComplete); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformPrintJobController} +class IOSPrintJobController extends PlatformPrintJobController + with ChannelController { + /// Constructs a [IOSPrintJobController]. + IOSPrintJobController(PlatformPrintJobControllerCreationParams params) + : super.implementation( + params is IOSPrintJobControllerCreationParams + ? params + : IOSPrintJobControllerCreationParams + .fromPlatformPrintJobControllerCreationParams(params), + ) { + channel = MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_printjobcontroller_${params.id}'); + handler = _handleMethod; + initMethodCallHandler(); + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onComplete": + bool completed = call.arguments["completed"]; + String? error = call.arguments["error"]; + if (params.onComplete != null) { + params.onComplete!(completed, error); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + } + + @override + Future cancel() async { + Map args = {}; + await channel?.invokeMethod('cancel', args); + } + + @override + Future restart() async { + Map args = {}; + await channel?.invokeMethod('restart', args); + } + + @override + Future dismiss({bool animated: true}) async { + Map args = {}; + args.putIfAbsent("animated", () => animated); + await channel?.invokeMethod('dismiss', args); + } + + @override + Future getInfo() async { + Map args = {}; + Map? infoMap = + (await channel?.invokeMethod('getInfo', args))?.cast(); + return PrintJobInfo.fromMap(infoMap); + } + + @override + Future dispose() async { + Map args = {}; + await channel?.invokeMethod('dispose', args); + disposeChannel(); + } +} diff --git a/flutter_inappwebview_ios/lib/src/pull_to_refresh/main.dart b/flutter_inappwebview_ios/lib/src/pull_to_refresh/main.dart new file mode 100644 index 00000000..586af9d8 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/pull_to_refresh/main.dart @@ -0,0 +1 @@ +export 'pull_to_refresh_controller.dart' hide InternalPullToRefreshController; diff --git a/flutter_inappwebview_ios/lib/src/pull_to_refresh/pull_to_refresh_controller.dart b/flutter_inappwebview_ios/lib/src/pull_to_refresh/pull_to_refresh_controller.dart new file mode 100644 index 00000000..5f3556cc --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/pull_to_refresh/pull_to_refresh_controller.dart @@ -0,0 +1,178 @@ +import 'dart:ui'; + +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSPullToRefreshController]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformPullToRefreshControllerCreationParams] for +/// more information. +class IOSPullToRefreshControllerCreationParams + extends PlatformPullToRefreshControllerCreationParams { + /// Creates a new [IOSPullToRefreshControllerCreationParams] instance. + IOSPullToRefreshControllerCreationParams( + {super.onRefresh, super.options, super.settings}); + + /// Creates a [IOSPullToRefreshControllerCreationParams] instance based on [PlatformPullToRefreshControllerCreationParams]. + factory IOSPullToRefreshControllerCreationParams.fromPlatformPullToRefreshControllerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformPullToRefreshControllerCreationParams params) { + return IOSPullToRefreshControllerCreationParams( + onRefresh: params.onRefresh, + options: params.options, + settings: params.settings); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformPullToRefreshController} +class IOSPullToRefreshController extends PlatformPullToRefreshController + with ChannelController { + /// Constructs a [IOSPullToRefreshController]. + IOSPullToRefreshController( + PlatformPullToRefreshControllerCreationParams params) + : super.implementation( + params is IOSPullToRefreshControllerCreationParams + ? params + : IOSPullToRefreshControllerCreationParams + .fromPlatformPullToRefreshControllerCreationParams(params), + ); + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + debugLoggingSettings: + PlatformPullToRefreshController.debugLoggingSettings, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + _debugLog(call.method, call.arguments); + + switch (call.method) { + case "onRefresh": + if (params.onRefresh != null) params.onRefresh!(); + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + @override + Future setEnabled(bool enabled) async { + Map args = {}; + args.putIfAbsent('enabled', () => enabled); + await channel?.invokeMethod('setEnabled', args); + } + + @override + Future isEnabled() async { + Map args = {}; + return await channel?.invokeMethod('isEnabled', args) ?? false; + } + + Future _setRefreshing(bool refreshing) async { + Map args = {}; + args.putIfAbsent('refreshing', () => refreshing); + await channel?.invokeMethod('setRefreshing', args); + } + + @override + Future beginRefreshing() async { + return await _setRefreshing(true); + } + + @override + Future endRefreshing() async { + await _setRefreshing(false); + } + + @override + Future isRefreshing() async { + Map args = {}; + return await channel?.invokeMethod('isRefreshing', args) ?? false; + } + + @override + Future setColor(Color color) async { + Map args = {}; + args.putIfAbsent('color', () => color.toHex()); + await channel?.invokeMethod('setColor', args); + } + + @override + Future setBackgroundColor(Color color) async { + Map args = {}; + args.putIfAbsent('color', () => color.toHex()); + await channel?.invokeMethod('setBackgroundColor', args); + } + + @override + Future setDistanceToTriggerSync(int distanceToTriggerSync) async { + Map args = {}; + args.putIfAbsent('distanceToTriggerSync', () => distanceToTriggerSync); + await channel?.invokeMethod('setDistanceToTriggerSync', args); + } + + @override + Future setSlingshotDistance(int slingshotDistance) async { + Map args = {}; + args.putIfAbsent('slingshotDistance', () => slingshotDistance); + await channel?.invokeMethod('setSlingshotDistance', args); + } + + @override + Future getDefaultSlingshotDistance() async { + Map args = {}; + return await channel?.invokeMethod( + 'getDefaultSlingshotDistance', args) ?? + 0; + } + + @Deprecated("Use setIndicatorSize instead") + @override + Future setSize(AndroidPullToRefreshSize size) async { + Map args = {}; + args.putIfAbsent('size', () => size.toNativeValue()); + await channel?.invokeMethod('setSize', args); + } + + @override + Future setIndicatorSize(PullToRefreshSize size) async { + Map args = {}; + args.putIfAbsent('size', () => size.toNativeValue()); + await channel?.invokeMethod('setSize', args); + } + + @Deprecated("Use setStyledTitle instead") + @override + Future setAttributedTitle(IOSNSAttributedString attributedTitle) async { + Map args = {}; + args.putIfAbsent('attributedTitle', () => attributedTitle.toMap()); + await channel?.invokeMethod('setStyledTitle', args); + } + + @override + Future setStyledTitle(AttributedString attributedTitle) async { + Map args = {}; + args.putIfAbsent('attributedTitle', () => attributedTitle.toMap()); + await channel?.invokeMethod('setStyledTitle', args); + } + + @override + void dispose({bool isKeepAlive = false}) { + disposeChannel(removeMethodCallHandler: !isKeepAlive); + } +} + +extension InternalPullToRefreshController on IOSPullToRefreshController { + void init(dynamic id) { + channel = MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_$id'); + handler = _handleMethod; + initMethodCallHandler(); + } +} diff --git a/flutter_inappwebview_ios/lib/src/web_authentication_session/main.dart b/flutter_inappwebview_ios/lib/src/web_authentication_session/main.dart new file mode 100644 index 00000000..37ca0c24 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_authentication_session/main.dart @@ -0,0 +1 @@ +export 'web_authenticate_session.dart'; diff --git a/flutter_inappwebview_ios/lib/src/web_authentication_session/web_authenticate_session.dart b/flutter_inappwebview_ios/lib/src/web_authentication_session/web_authenticate_session.dart new file mode 100755 index 00000000..7946d866 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_authentication_session/web_authenticate_session.dart @@ -0,0 +1,187 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSWebAuthenticationSession]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebAuthenticationSessionCreationParams] for +/// more information. +class IOSWebAuthenticationSessionCreationParams + extends PlatformWebAuthenticationSessionCreationParams { + /// Creates a new [IOSWebAuthenticationSessionCreationParams] instance. + const IOSWebAuthenticationSessionCreationParams(); + + /// Creates a [IOSWebAuthenticationSessionCreationParams] instance based on [PlatformWebAuthenticationSessionCreationParams]. + factory IOSWebAuthenticationSessionCreationParams.fromPlatformWebAuthenticationSessionCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebAuthenticationSessionCreationParams params) { + return IOSWebAuthenticationSessionCreationParams(); + } +} + +///A session that an app uses to authenticate a user through a web service. +/// +///It is implemented using [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) on iOS 12.0+ and MacOS 10.15+ +///and [SFAuthenticationSession](https://developer.apple.com/documentation/safariservices/sfauthenticationsession) on iOS 11.0. +/// +///Use an [IOSWebAuthenticationSession] instance to authenticate a user through a web service, including one run by a third party. +///Initialize the session with a URL that points to the authentication webpage. +///A browser loads and displays the page, from which the user can authenticate. +///In iOS, the browser is a secure, embedded web view. +///In macOS, the system opens the user’s default browser if it supports web authentication sessions, or Safari otherwise. +/// +///On completion, the service sends a callback URL to the session with an authentication token, and the session passes this URL back to the app through a completion handler. +///[IOSWebAuthenticationSession] ensures that only the calling app’s session receives the authentication callback, even when more than one app registers the same callback URL scheme. +/// +///**NOTE**: Remember to dispose it when you don't need it anymore. +/// +///**NOTE for iOS**: Available only on iOS 11.0+. +/// +///**NOTE for MacOS**: Available only on MacOS 10.15+. +/// +///**Supported Platforms/Implementations**: +///- iOS +///- MacOS +class IOSWebAuthenticationSession extends PlatformWebAuthenticationSession + with ChannelController { + /// Constructs a [IOSWebAuthenticationSession]. + IOSWebAuthenticationSession( + PlatformWebAuthenticationSessionCreationParams params) + : super.implementation( + params is IOSWebAuthenticationSessionCreationParams + ? params + : IOSWebAuthenticationSessionCreationParams + .fromPlatformWebAuthenticationSessionCreationParams(params), + ); + + static final IOSWebAuthenticationSession _staticValue = + IOSWebAuthenticationSession(IOSWebAuthenticationSessionCreationParams()); + + /// Provide static access. + factory IOSWebAuthenticationSession.static() { + return _staticValue; + } + + @override + final String id = IdGenerator.generate(); + + @override + late final WebUri url; + + @override + late final String? callbackURLScheme; + + @override + late final WebAuthenticationSessionSettings? initialSettings; + + @override + late final WebAuthenticationSessionCompletionHandler onComplete; + + static const MethodChannel _staticChannel = const MethodChannel( + 'com.pichillilorenzo/flutter_webauthenticationsession'); + + @override + Future create( + {required WebUri url, + String? callbackURLScheme, + WebAuthenticationSessionCompletionHandler onComplete, + WebAuthenticationSessionSettings? initialSettings}) async { + var session = IOSWebAuthenticationSession._create( + url: url, + callbackURLScheme: callbackURLScheme, + onComplete: onComplete, + initialSettings: initialSettings); + initialSettings = + session.initialSettings ?? WebAuthenticationSessionSettings(); + Map args = {}; + args.putIfAbsent("id", () => session.id); + args.putIfAbsent("url", () => session.url.toString()); + args.putIfAbsent("callbackURLScheme", () => session.callbackURLScheme); + args.putIfAbsent("initialSettings", () => initialSettings?.toMap()); + await _staticChannel.invokeMethod('create', args); + return session; + } + + IOSWebAuthenticationSession._create( + {required this.url, + this.callbackURLScheme, + this.onComplete, + WebAuthenticationSessionSettings? initialSettings}) + : super.implementation(IOSWebAuthenticationSessionCreationParams()) { + assert(url.toString().isNotEmpty); + if (Util.isIOS || Util.isMacOS) { + assert(['http', 'https'].contains(url.scheme), + 'The specified URL has an unsupported scheme. Only HTTP and HTTPS URLs are supported on iOS.'); + } + + this.initialSettings = + initialSettings ?? WebAuthenticationSessionSettings(); + channel = MethodChannel( + 'com.pichillilorenzo/flutter_webauthenticationsession_$id'); + handler = _handleMethod; + initMethodCallHandler(); + } + + _debugLog(String method, dynamic args) { + debugLog( + className: this.runtimeType.toString(), + debugLoggingSettings: + PlatformWebAuthenticationSession.debugLoggingSettings, + id: id, + method: method, + args: args); + } + + Future _handleMethod(MethodCall call) async { + _debugLog(call.method, call.arguments); + + switch (call.method) { + case "onComplete": + String? url = call.arguments["url"]; + WebUri? uri = url != null ? WebUri(url) : null; + var error = WebAuthenticationSessionError.fromNativeValue( + call.arguments["errorCode"]); + if (onComplete != null) { + onComplete!(uri, error); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + } + + @override + Future canStart() async { + Map args = {}; + return await channel?.invokeMethod('canStart', args) ?? false; + } + + @override + Future start() async { + Map args = {}; + return await channel?.invokeMethod('start', args) ?? false; + } + + @override + Future cancel() async { + Map args = {}; + await channel?.invokeMethod("cancel", args); + } + + @override + Future dispose() async { + Map args = {}; + await channel?.invokeMethod("dispose", args); + disposeChannel(); + } + + @override + Future isAvailable() async { + Map args = {}; + return await _staticChannel.invokeMethod("isAvailable", args) ?? + false; + } +} diff --git a/flutter_inappwebview_ios/lib/src/web_message/main.dart b/flutter_inappwebview_ios/lib/src/web_message/main.dart new file mode 100644 index 00000000..d41e30c7 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_message/main.dart @@ -0,0 +1,3 @@ +export 'web_message_port.dart' hide InternalWebMessagePort; +export 'web_message_channel.dart' hide InternalWebMessageChannel; +export 'web_message_listener.dart'; diff --git a/flutter_inappwebview_ios/lib/src/web_message/web_message_channel.dart b/flutter_inappwebview_ios/lib/src/web_message/web_message_channel.dart new file mode 100644 index 00000000..dec20653 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_message/web_message_channel.dart @@ -0,0 +1,120 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; +import 'web_message_port.dart'; + +/// Object specifying creation parameters for creating a [IOSWebMessageChannel]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebMessageChannelCreationParams] for +/// more information. +@immutable +class IOSWebMessageChannelCreationParams + extends PlatformWebMessageChannelCreationParams { + /// Creates a new [IOSWebMessageChannelCreationParams] instance. + const IOSWebMessageChannelCreationParams( + {required super.id, required super.port1, required super.port2}); + + /// Creates a [IOSWebMessageChannelCreationParams] instance based on [PlatformWebMessageChannelCreationParams]. + factory IOSWebMessageChannelCreationParams.fromPlatformWebMessageChannelCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebMessageChannelCreationParams params) { + return IOSWebMessageChannelCreationParams( + id: params.id, port1: params.port1, port2: params.port2); + } + + @override + String toString() { + return 'IOSWebMessageChannelCreationParams{id: $id, port1: $port1, port2: $port2}'; + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformWebMessageChannel} +class IOSWebMessageChannel extends PlatformWebMessageChannel + with ChannelController { + /// Constructs a [IOSWebMessageChannel]. + IOSWebMessageChannel(PlatformWebMessageChannelCreationParams params) + : super.implementation( + params is IOSWebMessageChannelCreationParams + ? params + : IOSWebMessageChannelCreationParams + .fromPlatformWebMessageChannelCreationParams(params), + ) { + channel = MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_web_message_channel_${params.id}'); + handler = _handleMethod; + initMethodCallHandler(); + } + + static final IOSWebMessageChannel _staticValue = IOSWebMessageChannel( + IOSWebMessageChannelCreationParams( + id: '', + port1: IOSWebMessagePort( + IOSWebMessagePortCreationParams(index: 0)), + port2: IOSWebMessagePort( + IOSWebMessagePortCreationParams(index: 1)))); + + /// Provide static access. + factory IOSWebMessageChannel.static() { + return _staticValue; + } + + IOSWebMessagePort get _iosPort1 => port1 as IOSWebMessagePort; + + IOSWebMessagePort get _iosPort2 => port2 as IOSWebMessagePort; + + static IOSWebMessageChannel? _fromMap(Map? map) { + if (map == null) { + return null; + } + var webMessageChannel = IOSWebMessageChannel( + IOSWebMessageChannelCreationParams( + id: map["id"], + port1: IOSWebMessagePort( + IOSWebMessagePortCreationParams(index: 0)), + port2: IOSWebMessagePort( + IOSWebMessagePortCreationParams(index: 1)))); + webMessageChannel._iosPort1.webMessageChannel = webMessageChannel; + webMessageChannel._iosPort2.webMessageChannel = webMessageChannel; + return webMessageChannel; + } + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onMessage": + int index = call.arguments["index"]; + var port = index == 0 ? _iosPort1 : _iosPort2; + if (port.onMessage != null) { + WebMessage? message = call.arguments["message"] != null + ? WebMessage.fromMap( + call.arguments["message"].cast()) + : null; + port.onMessage!(message); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + @override + IOSWebMessageChannel? fromMap(Map? map) { + return _fromMap(map); + } + + @override + void dispose() { + disposeChannel(); + } + + @override + String toString() { + return 'IOSWebMessageChannel{id: $id, port1: $port1, port2: $port2}'; + } +} + +extension InternalWebMessageChannel on IOSWebMessageChannel { + MethodChannel? get internalChannel => channel; +} diff --git a/flutter_inappwebview_ios/lib/src/web_message/web_message_listener.dart b/flutter_inappwebview_ios/lib/src/web_message/web_message_listener.dart new file mode 100644 index 00000000..38a27880 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_message/web_message_listener.dart @@ -0,0 +1,164 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSWebMessageListener]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebMessageListenerCreationParams] for +/// more information. +@immutable +class IOSWebMessageListenerCreationParams + extends PlatformWebMessageListenerCreationParams { + /// Creates a new [IOSWebMessageListenerCreationParams] instance. + const IOSWebMessageListenerCreationParams( + {required this.allowedOriginRules, + required super.jsObjectName, + super.onPostMessage}); + + /// Creates a [IOSWebMessageListenerCreationParams] instance based on [PlatformWebMessageListenerCreationParams]. + factory IOSWebMessageListenerCreationParams.fromPlatformWebMessageListenerCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebMessageListenerCreationParams params) { + return IOSWebMessageListenerCreationParams( + allowedOriginRules: params.allowedOriginRules ?? Set.from(["*"]), + jsObjectName: params.jsObjectName, + onPostMessage: params.onPostMessage); + } + + @override + final Set allowedOriginRules; + + @override + String toString() { + return 'IOSWebMessageListenerCreationParams{jsObjectName: $jsObjectName, allowedOriginRules: $allowedOriginRules, onPostMessage: $onPostMessage}'; + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformWebMessageListener} +class IOSWebMessageListener extends PlatformWebMessageListener + with ChannelController { + /// Constructs a [IOSWebMessageListener]. + IOSWebMessageListener(PlatformWebMessageListenerCreationParams params) + : super.implementation( + params is IOSWebMessageListenerCreationParams + ? params + : IOSWebMessageListenerCreationParams + .fromPlatformWebMessageListenerCreationParams(params), + ) { + assert(!this._iosParams.allowedOriginRules.contains(""), + "allowedOriginRules cannot contain empty strings"); + channel = MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_web_message_listener_${_id}_${params.jsObjectName}'); + handler = _handleMethod; + initMethodCallHandler(); + } + + ///Message Listener ID used internally. + final String _id = IdGenerator.generate(); + + IOSJavaScriptReplyProxy? _replyProxy; + + IOSWebMessageListenerCreationParams get _iosParams => + params as IOSWebMessageListenerCreationParams; + + Future _handleMethod(MethodCall call) async { + switch (call.method) { + case "onPostMessage": + if (_replyProxy == null) { + _replyProxy = IOSJavaScriptReplyProxy( + PlatformJavaScriptReplyProxyCreationParams( + webMessageListener: this)); + } + if (onPostMessage != null) { + WebMessage? message = call.arguments["message"] != null + ? WebMessage.fromMap( + call.arguments["message"].cast()) + : null; + WebUri? sourceOrigin = call.arguments["sourceOrigin"] != null + ? WebUri(call.arguments["sourceOrigin"]) + : null; + bool isMainFrame = call.arguments["isMainFrame"]; + onPostMessage!(message, sourceOrigin, isMainFrame, _replyProxy!); + } + break; + default: + throw UnimplementedError("Unimplemented ${call.method} method"); + } + return null; + } + + @override + void dispose() { + disposeChannel(); + } + + @override + Map toMap() { + return { + "id": _id, + "jsObjectName": params.jsObjectName, + "allowedOriginRules": _iosParams.allowedOriginRules.toList(), + }; + } + + @override + Map toJson() { + return this.toMap(); + } + + @override + String toString() { + return 'IOSWebMessageListener{id: ${_id}, jsObjectName: ${params.jsObjectName}, allowedOriginRules: ${params.allowedOriginRules}, replyProxy: $_replyProxy}'; + } +} + +/// Object specifying creation parameters for creating a [IOSJavaScriptReplyProxy]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformJavaScriptReplyProxyCreationParams] for +/// more information. +@immutable +class IOSJavaScriptReplyProxyCreationParams + extends PlatformJavaScriptReplyProxyCreationParams { + /// Creates a new [IOSJavaScriptReplyProxyCreationParams] instance. + const IOSJavaScriptReplyProxyCreationParams( + {required super.webMessageListener}); + + /// Creates a [IOSJavaScriptReplyProxyCreationParams] instance based on [PlatformJavaScriptReplyProxyCreationParams]. + factory IOSJavaScriptReplyProxyCreationParams.fromPlatformJavaScriptReplyProxyCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformJavaScriptReplyProxyCreationParams params) { + return IOSJavaScriptReplyProxyCreationParams( + webMessageListener: params.webMessageListener); + } +} + +///{@macro flutter_inappwebview_platform_interface.JavaScriptReplyProxy} +class IOSJavaScriptReplyProxy extends PlatformJavaScriptReplyProxy { + /// Constructs a [IOSWebMessageListener]. + IOSJavaScriptReplyProxy(PlatformJavaScriptReplyProxyCreationParams params) + : super.implementation( + params is IOSJavaScriptReplyProxyCreationParams + ? params + : IOSJavaScriptReplyProxyCreationParams + .fromPlatformJavaScriptReplyProxyCreationParams(params), + ); + + IOSWebMessageListener get _iosWebMessageListener => + params.webMessageListener as IOSWebMessageListener; + + @override + Future postMessage(WebMessage message) async { + Map args = {}; + args.putIfAbsent('message', () => message.toMap()); + await _iosWebMessageListener.channel?.invokeMethod('postMessage', args); + } + + @override + String toString() { + return 'IOSJavaScriptReplyProxy{}'; + } +} diff --git a/flutter_inappwebview_ios/lib/src/web_message/web_message_port.dart b/flutter_inappwebview_ios/lib/src/web_message/web_message_port.dart new file mode 100644 index 00000000..b16b3b75 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_message/web_message_port.dart @@ -0,0 +1,95 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import 'web_message_channel.dart'; + +/// Object specifying creation parameters for creating a [IOSWebMessagePort]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebMessagePortCreationParams] for +/// more information. +@immutable +class IOSWebMessagePortCreationParams + extends PlatformWebMessagePortCreationParams { + /// Creates a new [IOSWebMessagePortCreationParams] instance. + const IOSWebMessagePortCreationParams({required super.index}); + + /// Creates a [IOSWebMessagePortCreationParams] instance based on [PlatformWebMessagePortCreationParams]. + factory IOSWebMessagePortCreationParams.fromPlatformWebMessagePortCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebMessagePortCreationParams params) { + return IOSWebMessagePortCreationParams(index: params.index); + } + + @override + String toString() { + return 'IOSWebMessagePortCreationParams{index: $index}'; + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformWebMessagePort} +class IOSWebMessagePort extends PlatformWebMessagePort { + WebMessageCallback? _onMessage; + late IOSWebMessageChannel _webMessageChannel; + + /// Constructs a [IOSWebMessagePort]. + IOSWebMessagePort(PlatformWebMessagePortCreationParams params) + : super.implementation( + params is IOSWebMessagePortCreationParams + ? params + : IOSWebMessagePortCreationParams + .fromPlatformWebMessagePortCreationParams(params), + ); + + @override + Future setWebMessageCallback(WebMessageCallback? onMessage) async { + Map args = {}; + args.putIfAbsent('index', () => params.index); + await _webMessageChannel.internalChannel + ?.invokeMethod('setWebMessageCallback', args); + this._onMessage = onMessage; + } + + @override + Future postMessage(WebMessage message) async { + Map args = {}; + args.putIfAbsent('index', () => params.index); + args.putIfAbsent('message', () => message.toMap()); + await _webMessageChannel.internalChannel?.invokeMethod('postMessage', args); + } + + @override + Future close() async { + Map args = {}; + args.putIfAbsent('index', () => params.index); + await _webMessageChannel.internalChannel?.invokeMethod('close', args); + } + + @override + Map toMap() { + return { + "index": params.index, + "webMessageChannelId": this._webMessageChannel.params.id + }; + } + + @override + Map toJson() { + return toMap(); + } + + @override + String toString() { + return 'IOSWebMessagePort{index: ${params.index}}'; + } +} + +extension InternalWebMessagePort on IOSWebMessagePort { + WebMessageCallback? get onMessage => _onMessage; + void set onMessage(WebMessageCallback? value) => _onMessage = value; + + IOSWebMessageChannel get webMessageChannel => _webMessageChannel; + void set webMessageChannel(IOSWebMessageChannel value) => + _webMessageChannel = value; +} diff --git a/flutter_inappwebview_ios/lib/src/web_storage/main.dart b/flutter_inappwebview_ios/lib/src/web_storage/main.dart new file mode 100644 index 00000000..7265ae52 --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_storage/main.dart @@ -0,0 +1,2 @@ +export 'web_storage.dart'; +export 'web_storage_manager.dart' hide InternalWebStorageManager; diff --git a/flutter_inappwebview_ios/lib/src/web_storage/web_storage.dart b/flutter_inappwebview_ios/lib/src/web_storage/web_storage.dart new file mode 100644 index 00000000..45fa637b --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_storage/web_storage.dart @@ -0,0 +1,257 @@ +import 'dart:convert'; + +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +import '../in_app_webview/in_app_webview_controller.dart'; + +/// Object specifying creation parameters for creating a [IOSWebStorage]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebStorageCreationParams] for +/// more information. +class IOSWebStorageCreationParams extends PlatformWebStorageCreationParams { + /// Creates a new [IOSWebStorageCreationParams] instance. + IOSWebStorageCreationParams( + {required super.localStorage, required super.sessionStorage}); + + /// Creates a [IOSWebStorageCreationParams] instance based on [PlatformWebStorageCreationParams]. + factory IOSWebStorageCreationParams.fromPlatformWebStorageCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformWebStorageCreationParams params) { + return IOSWebStorageCreationParams( + localStorage: params.localStorage, + sessionStorage: params.sessionStorage); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformWebStorage} +class IOSWebStorage extends PlatformWebStorage { + /// Constructs a [IOSWebStorage]. + IOSWebStorage(PlatformWebStorageCreationParams params) + : super.implementation( + params is IOSWebStorageCreationParams + ? params + : IOSWebStorageCreationParams + .fromPlatformWebStorageCreationParams(params), + ); + + @override + PlatformLocalStorage get localStorage => params.localStorage; + + @override + PlatformSessionStorage get sessionStorage => params.sessionStorage; + + @override + void dispose() { + localStorage.dispose(); + sessionStorage.dispose(); + } +} + +/// Object specifying creation parameters for creating a [IOSStorage]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformStorageCreationParams] for +/// more information. +class IOSStorageCreationParams extends PlatformStorageCreationParams { + /// Creates a new [IOSStorageCreationParams] instance. + IOSStorageCreationParams( + {required super.controller, required super.webStorageType}); + + /// Creates a [IOSStorageCreationParams] instance based on [PlatformStorageCreationParams]. + factory IOSStorageCreationParams.fromPlatformStorageCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformStorageCreationParams params) { + return IOSStorageCreationParams( + controller: params.controller, webStorageType: params.webStorageType); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformStorage} +abstract class IOSStorage implements PlatformStorage { + @override + IOSInAppWebViewController? controller; + + @override + Future length() async { + var result = await controller?.evaluateJavascript(source: """ + window.$webStorageType.length; + """); + return result != null ? int.parse(json.decode(result)) : null; + } + + @override + Future setItem({required String key, required dynamic value}) async { + var encodedValue = json.encode(value); + await controller?.evaluateJavascript(source: """ + window.$webStorageType.setItem("$key", ${value is String ? encodedValue : "JSON.stringify($encodedValue)"}); + """); + } + + @override + Future getItem({required String key}) async { + var itemValue = await controller?.evaluateJavascript(source: """ + window.$webStorageType.getItem("$key"); + """); + + if (itemValue == null) { + return null; + } + + try { + return json.decode(itemValue); + } catch (e) {} + + return itemValue; + } + + @override + Future removeItem({required String key}) async { + await controller?.evaluateJavascript(source: """ + window.$webStorageType.removeItem("$key"); + """); + } + + @override + Future> getItems() async { + var webStorageItems = []; + + List>? items = + (await controller?.evaluateJavascript(source: """ +(function() { + var webStorageItems = []; + for(var i = 0; i < window.$webStorageType.length; i++){ + var key = window.$webStorageType.key(i); + webStorageItems.push( + { + key: key, + value: window.$webStorageType.getItem(key) + } + ); + } + return webStorageItems; +})(); + """))?.cast>(); + + if (items == null) { + return webStorageItems; + } + + for (var item in items) { + webStorageItems + .add(WebStorageItem(key: item["key"], value: item["value"])); + } + + return webStorageItems; + } + + @override + Future clear() async { + await controller?.evaluateJavascript(source: """ + window.$webStorageType.clear(); + """); + } + + @override + Future key({required int index}) async { + var result = await controller?.evaluateJavascript(source: """ + window.$webStorageType.key($index); + """); + return result != null ? json.decode(result) : null; + } + + @override + void dispose() { + controller = null; + } +} + +/// Object specifying creation parameters for creating a [IOSLocalStorage]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformLocalStorageCreationParams] for +/// more information. +class IOSLocalStorageCreationParams + extends PlatformLocalStorageCreationParams { + /// Creates a new [IOSLocalStorageCreationParams] instance. + IOSLocalStorageCreationParams(super.params); + + /// Creates a [IOSLocalStorageCreationParams] instance based on [PlatformLocalStorageCreationParams]. + factory IOSLocalStorageCreationParams.fromPlatformLocalStorageCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformLocalStorageCreationParams params) { + return IOSLocalStorageCreationParams(params); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformLocalStorage} +class IOSLocalStorage extends PlatformLocalStorage with IOSStorage { + /// Constructs a [IOSLocalStorage]. + IOSLocalStorage(PlatformLocalStorageCreationParams params) + : super.implementation( + params is IOSLocalStorageCreationParams + ? params + : IOSLocalStorageCreationParams + .fromPlatformLocalStorageCreationParams(params), + ); + + /// Default storage + factory IOSLocalStorage.defaultStorage( + {required PlatformInAppWebViewController? controller}) { + return IOSLocalStorage(IOSLocalStorageCreationParams( + PlatformLocalStorageCreationParams(PlatformStorageCreationParams( + controller: controller, + webStorageType: WebStorageType.LOCAL_STORAGE)))); + } + + @override + IOSInAppWebViewController? get controller => + params.controller as IOSInAppWebViewController?; +} + +/// Object specifying creation parameters for creating a [IOSSessionStorage]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformSessionStorageCreationParams] for +/// more information. +class IOSSessionStorageCreationParams + extends PlatformSessionStorageCreationParams { + /// Creates a new [IOSSessionStorageCreationParams] instance. + IOSSessionStorageCreationParams(super.params); + + /// Creates a [IOSSessionStorageCreationParams] instance based on [PlatformSessionStorageCreationParams]. + factory IOSSessionStorageCreationParams.fromPlatformSessionStorageCreationParams( + // Recommended placeholder to prevent being broken by platform interface. + // ignore: avoid_unused_constructor_parameters + PlatformSessionStorageCreationParams params) { + return IOSSessionStorageCreationParams(params); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformSessionStorage} +class IOSSessionStorage extends PlatformSessionStorage with IOSStorage { + /// Constructs a [IOSSessionStorage]. + IOSSessionStorage(PlatformSessionStorageCreationParams params) + : super.implementation( + params is IOSSessionStorageCreationParams + ? params + : IOSSessionStorageCreationParams + .fromPlatformSessionStorageCreationParams(params), + ); + + /// Default storage + factory IOSSessionStorage.defaultStorage( + {required PlatformInAppWebViewController? controller}) { + return IOSSessionStorage(IOSSessionStorageCreationParams( + PlatformSessionStorageCreationParams(PlatformStorageCreationParams( + controller: controller, + webStorageType: WebStorageType.SESSION_STORAGE)))); + } + + @override + IOSInAppWebViewController? get controller => + params.controller as IOSInAppWebViewController?; +} diff --git a/flutter_inappwebview_ios/lib/src/web_storage/web_storage_manager.dart b/flutter_inappwebview_ios/lib/src/web_storage/web_storage_manager.dart new file mode 100755 index 00000000..530b28dd --- /dev/null +++ b/flutter_inappwebview_ios/lib/src/web_storage/web_storage_manager.dart @@ -0,0 +1,181 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart'; + +/// Object specifying creation parameters for creating a [IOSWebStorageManager]. +/// +/// When adding additional fields make sure they can be null or have a default +/// value to avoid breaking changes. See [PlatformWebStorageManagerCreationParams] for +/// more information. +@immutable +class IOSWebStorageManagerCreationParams + extends PlatformWebStorageManagerCreationParams { + /// Creates a new [IOSWebStorageManagerCreationParams] instance. + const IOSWebStorageManagerCreationParams( + // This parameter prevents breaking changes later. + // ignore: avoid_unused_constructor_parameters + PlatformWebStorageManagerCreationParams params, + ) : super(); + + /// Creates a [IOSWebStorageManagerCreationParams] instance based on [PlatformWebStorageManagerCreationParams]. + factory IOSWebStorageManagerCreationParams.fromPlatformWebStorageManagerCreationParams( + PlatformWebStorageManagerCreationParams params) { + return IOSWebStorageManagerCreationParams(params); + } +} + +///{@macro flutter_inappwebview_platform_interface.PlatformWebStorageManager} +class IOSWebStorageManager extends PlatformWebStorageManager + with ChannelController { + /// Creates a new [IOSWebStorageManager]. + IOSWebStorageManager(PlatformWebStorageManagerCreationParams params) + : super.implementation( + params is IOSWebStorageManagerCreationParams + ? params + : IOSWebStorageManagerCreationParams + .fromPlatformWebStorageManagerCreationParams(params), + ) { + channel = const MethodChannel( + 'com.pichillilorenzo/flutter_inappwebview_webstoragemanager'); + handler = handleMethod; + initMethodCallHandler(); + } + + static IOSWebStorageManager? _instance; + + ///Gets the WebStorage manager shared instance. + static IOSWebStorageManager instance() { + return (_instance != null) ? _instance! : _init(); + } + + static IOSWebStorageManager _init() { + _instance = IOSWebStorageManager(IOSWebStorageManagerCreationParams( + const PlatformWebStorageManagerCreationParams())); + return _instance!; + } + + Future _handleMethod(MethodCall call) async {} + + @override + Future> getOrigins() async { + List originsList = []; + + Map args = {}; + List> origins = + (await channel?.invokeMethod('getOrigins', args)) + ?.cast>() ?? + []; + + for (var origin in origins) { + originsList.add(WebStorageOrigin( + origin: origin["origin"], + quota: origin["quota"], + usage: origin["usage"])); + } + + return originsList; + } + + @override + Future deleteAllData() async { + Map args = {}; + await channel?.invokeMethod('deleteAllData', args); + } + + @override + Future deleteOrigin({required String origin}) async { + Map args = {}; + args.putIfAbsent("origin", () => origin); + await channel?.invokeMethod('deleteOrigin', args); + } + + @override + Future getQuotaForOrigin({required String origin}) async { + Map args = {}; + args.putIfAbsent("origin", () => origin); + return await channel?.invokeMethod('getQuotaForOrigin', args) ?? 0; + } + + @override + Future getUsageForOrigin({required String origin}) async { + Map args = {}; + args.putIfAbsent("origin", () => origin); + return await channel?.invokeMethod('getUsageForOrigin', args) ?? 0; + } + + @override + Future> fetchDataRecords( + {required Set dataTypes}) async { + List recordList = []; + List dataTypesList = []; + for (var dataType in dataTypes) { + dataTypesList.add(dataType.toNativeValue()); + } + Map args = {}; + args.putIfAbsent("dataTypes", () => dataTypesList); + List> records = + (await channel?.invokeMethod('fetchDataRecords', args)) + ?.cast>() ?? + []; + for (var record in records) { + List dataTypesString = record["dataTypes"].cast(); + Set dataTypes = Set(); + for (var dataTypeValue in dataTypesString) { + var dataType = WebsiteDataType.fromNativeValue(dataTypeValue); + if (dataType != null) { + dataTypes.add(dataType); + } + } + recordList.add(WebsiteDataRecord( + displayName: record["displayName"], dataTypes: dataTypes)); + } + return recordList; + } + + @override + Future removeDataFor( + {required Set dataTypes, + required List dataRecords}) async { + List dataTypesList = []; + for (var dataType in dataTypes) { + dataTypesList.add(dataType.toNativeValue()); + } + + List> recordList = []; + for (var record in dataRecords) { + recordList.add(record.toMap()); + } + + Map args = {}; + args.putIfAbsent("dataTypes", () => dataTypesList); + args.putIfAbsent("recordList", () => recordList); + await channel?.invokeMethod('removeDataFor', args); + } + + @override + Future removeDataModifiedSince( + {required Set dataTypes, required DateTime date}) async { + List dataTypesList = []; + for (var dataType in dataTypes) { + dataTypesList.add(dataType.toNativeValue()); + } + + var timestamp = date.millisecondsSinceEpoch; + + Map args = {}; + args.putIfAbsent("dataTypes", () => dataTypesList); + args.putIfAbsent("timestamp", () => timestamp); + await channel?.invokeMethod('removeDataModifiedSince', args); + } + + @override + void dispose() { + // empty + } +} + +extension InternalWebStorageManager on IOSWebStorageManager { + get handleMethod => _handleMethod; +} diff --git a/flutter_inappwebview_ios/pubspec.yaml b/flutter_inappwebview_ios/pubspec.yaml new file mode 100644 index 00000000..6f4b141d --- /dev/null +++ b/flutter_inappwebview_ios/pubspec.yaml @@ -0,0 +1,72 @@ +name: flutter_inappwebview_ios +description: iOS implementation of the flutter_inappwebview plugin. +version: 0.0.1 +homepage: + +environment: + sdk: ">=2.17.0 <4.0.0" + flutter: ">=3.0.0" + +dependencies: + flutter: + sdk: flutter + flutter_inappwebview_platform_interface: + path: ../flutter_inappwebview_platform_interface + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + plugin_platform_interface: ^2.0.2 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + ios: + pluginClass: InAppWebViewFlutterPlugin + dartPluginClass: IOSInAppWebViewPlatform + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/flutter_inappwebview_ios/test/flutter_inappwebview_ios_test.dart b/flutter_inappwebview_ios/test/flutter_inappwebview_ios_test.dart new file mode 100644 index 00000000..e69de29b diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_localhost_server.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_localhost_server.dart index ffdb9abd..fff3757d 100755 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_localhost_server.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_localhost_server.dart @@ -47,11 +47,12 @@ class DefaultInAppLocalhostServer extends PlatformInAppLocalhostServer { : DefaultInAppLocalhostServerCreationParams .fromPlatformInAppLocalhostServerCreationParams(params), ) { - this._port = port; - this._directoryIndex = directoryIndex; - this._documentRoot = - (documentRoot.endsWith('/')) ? documentRoot : '$documentRoot/'; - this._shared = shared; + this._port = params.port; + this._directoryIndex = params.directoryIndex; + this._documentRoot = (params.documentRoot.endsWith('/')) + ? params.documentRoot + : '${params.documentRoot}/'; + this._shared = params.shared; } @override @@ -98,6 +99,7 @@ class DefaultInAppLocalhostServer extends PlatformInAppLocalhostServer { .buffer .asUint8List(); } catch (e) { + print(Uri.decodeFull(path)); print(e.toString()); request.response.close(); return; diff --git a/flutter_inappwebview_platform_interface/lib/src/web_authentication_session/platform_web_authenticate_session.dart b/flutter_inappwebview_platform_interface/lib/src/web_authentication_session/platform_web_authenticate_session.dart index 4aa25447..4e3c9155 100755 --- a/flutter_inappwebview_platform_interface/lib/src/web_authentication_session/platform_web_authenticate_session.dart +++ b/flutter_inappwebview_platform_interface/lib/src/web_authentication_session/platform_web_authenticate_session.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter_inappwebview_platform_interface/src/types/disposable.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import '../debug_logging_settings.dart'; import '../inappwebview_platform.dart'; @@ -19,28 +18,7 @@ typedef WebAuthenticationSessionCompletionHandler = Future Function( /// this class. class PlatformWebAuthenticationSessionCreationParams { /// Used by the platform implementation to create a new [PlatformWebAuthenticationSession]. - PlatformWebAuthenticationSessionCreationParams( - {required this.url, - this.callbackURLScheme, - this.onComplete, - WebAuthenticationSessionSettings? initialSettings}) - : this.initialSettings = - initialSettings ?? WebAuthenticationSessionSettings(); - - ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.id} - late final String id; - - ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.url} - final WebUri url; - - ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.callbackURLScheme} - final String? callbackURLScheme; - - ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.initialSettings} - late final WebAuthenticationSessionSettings? initialSettings; - - ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.onComplete} - WebAuthenticationSessionCompletionHandler onComplete; + const PlatformWebAuthenticationSessionCreationParams(); } ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession} @@ -122,28 +100,34 @@ abstract class PlatformWebAuthenticationSession extends PlatformInterface ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.id} ///ID used internally. ///{@endtemplate} - String get id => params.id; + String get id => + throw UnimplementedError('id is not implemented on the current platform'); ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.url} ///A URL with the `http` or `https` scheme pointing to the authentication webpage. ///{@endtemplate} - WebUri get url => params.url; + WebUri get url => throw UnimplementedError( + 'url is not implemented on the current platform'); ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.callbackURLScheme} ///The custom URL scheme that the app expects in the callback URL. ///{@endtemplate} - String? get callbackURLScheme => params.callbackURLScheme; + String? get callbackURLScheme => throw UnimplementedError( + 'callbackURLScheme is not implemented on the current platform'); ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.initialSettings} ///Initial settings. ///{@endtemplate} WebAuthenticationSessionSettings? get initialSettings => - params.initialSettings; + throw UnimplementedError( + 'initialSettings is not implemented on the current platform'); ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.onComplete} ///A completion handler the session calls when it completes successfully, or when the user cancels the session. ///{@endtemplate} - WebAuthenticationSessionCompletionHandler get onComplete => params.onComplete; + WebAuthenticationSessionCompletionHandler get onComplete => + throw UnimplementedError( + 'onComplete is not implemented on the current platform'); ///{@template flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession.create} ///Used to create and initialize a session. @@ -153,6 +137,8 @@ abstract class PlatformWebAuthenticationSession extends PlatformInterface ///[callbackURLScheme] represents the custom URL scheme that the app expects in the callback URL. /// ///[onComplete] represents a completion handler the session calls when it completes successfully, or when the user cancels the session. + /// + ///[initialSettings] represents initial settings. ///{@endtemplate} Future create( {required WebUri url, diff --git a/lib/src/web_authentication_session/web_authenticate_session.dart b/lib/src/web_authentication_session/web_authenticate_session.dart index 0733a1b3..f167748d 100755 --- a/lib/src/web_authentication_session/web_authenticate_session.dart +++ b/lib/src/web_authentication_session/web_authenticate_session.dart @@ -5,17 +5,9 @@ import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_pla ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession} class WebAuthenticationSession { ///{@macro flutter_inappwebview_platform_interface.PlatformWebAuthenticationSession} - WebAuthenticationSession( - {required WebUri url, - String? callbackURLScheme, - WebAuthenticationSessionSettings? initialSettings, - WebAuthenticationSessionCompletionHandler onComplete}) + WebAuthenticationSession() : this.fromPlatformCreationParams( - params: PlatformWebAuthenticationSessionCreationParams( - url: url, - callbackURLScheme: callbackURLScheme, - initialSettings: initialSettings, - onComplete: onComplete)); + params: PlatformWebAuthenticationSessionCreationParams()); /// Constructs a [WebAuthenticationSession]. /// diff --git a/pubspec.yaml b/pubspec.yaml index 548afb56..248f9307 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,8 @@ dependencies: path: flutter_inappwebview_platform_interface flutter_inappwebview_android: path: flutter_inappwebview_android + flutter_inappwebview_ios: + path: flutter_inappwebview_ios dev_dependencies: flutter_test: @@ -46,7 +48,7 @@ flutter: android: default_package: flutter_inappwebview_android ios: - pluginClass: InAppWebViewFlutterPlugin + default_package: flutter_inappwebview_ios macos: pluginClass: InAppWebViewFlutterPlugin web: