├── ios ├── Assets │ └── .gitkeep ├── Classes │ ├── PluginScriptsJS │ │ ├── WebMessageChannelJS.swift │ │ ├── WindowIdJS.swift │ │ ├── PrintJS.swift │ │ ├── OnWindowFocusEventJS.swift │ │ ├── OnWindowBlurEventJS.swift │ │ ├── CallAsyncJavaScriptBelowIOS14WrapperJS.swift │ │ ├── PluginScriptsUtil.swift │ │ ├── OriginalViewPortMetaTagContentJS.swift │ │ ├── EnableViewportScaleJS.swift │ │ ├── SupportZoomJS.swift │ │ ├── JavaScriptBridgeJS.swift │ │ ├── OnLoadResourceJS.swift │ │ └── ConsoleLogJS.swift │ ├── WKProcessPoolManager.swift │ ├── PullToRefresh │ │ ├── PullToRefreshDelegate.swift │ │ └── PullToRefreshOptions.swift │ ├── ContextMenuOptions.swift │ ├── FlutterMethodCallDelegate.swift │ ├── Types │ │ ├── WebViewTransport.swift │ │ ├── WKSecurityOrigin.swift │ │ ├── WKNavigationResponse.swift │ │ ├── SecCertificate.swift │ │ ├── ClientCertChallenge.swift │ │ ├── ServerTrustChallenge.swift │ │ ├── WebMessage.swift │ │ ├── WKNavigationAction.swift │ │ ├── URLAuthenticationChallenge.swift │ │ ├── WKWindowFeatures.swift │ │ ├── URLResponse.swift │ │ ├── URLCredential.swift │ │ ├── WKFrameInfo.swift │ │ ├── SslCertificate.swift │ │ ├── HitTestResult.swift │ │ ├── WKContentWorld.swift │ │ ├── SslError.swift │ │ └── UIColor.swift │ ├── InAppBrowser │ │ ├── InAppBrowserDelegate.swift │ │ └── InAppBrowserNavigationController.swift │ ├── LeakAvoider.swift │ ├── InAppWebViewFlutterPlugin.h │ ├── InAppWebView │ │ └── FlutterWebViewFactory.swift │ ├── HttpAuthenticationChallenge.swift │ ├── Options.swift │ ├── InAppWebViewFlutterPlugin.m │ ├── SafariViewController │ │ └── SafariBrowserOptions.swift │ └── CustomeSchemeHandler.swift ├── .gitignore └── flutter_inappwebview.podspec ├── .gradle ├── 5.1.1 │ ├── gc.properties │ ├── fileChanges │ │ └── last-build.bin │ └── fileHashes │ │ └── fileHashes.lock ├── vcs-1 │ └── gc.properties ├── 4.4.1 │ ├── fileChanges │ │ └── last-build.bin │ ├── fileHashes │ │ └── fileHashes.lock │ └── taskHistory │ │ └── taskHistory.lock └── buildOutputCleanup │ ├── cache.properties │ └── buildOutputCleanup.lock ├── lib ├── src │ ├── ios │ │ └── main.dart │ ├── web_storage │ │ ├── ios │ │ │ └── main.dart │ │ ├── android │ │ │ └── main.dart │ │ ├── main.dart │ │ ├── _static_channel.dart │ │ └── web_storage_manager.dart │ ├── chrome_safari_browser │ │ ├── ios │ │ │ └── main.dart │ │ ├── android │ │ │ └── main.dart │ │ ├── main.dart │ │ └── chrome_safari_browser_options.dart │ ├── in_app_browser │ │ ├── ios │ │ │ └── main.dart │ │ ├── android │ │ │ ├── main.dart │ │ │ └── in_app_browser_options.dart │ │ └── main.dart │ ├── web_message │ │ └── main.dart │ ├── android │ │ └── main.dart │ ├── in_app_webview │ │ ├── ios │ │ │ └── main.dart │ │ ├── android │ │ │ └── main.dart │ │ ├── _static_channel.dart │ │ └── main.dart │ ├── pull_to_refresh │ │ ├── main.dart │ │ └── pull_to_refresh_options.dart │ ├── x509_certificate │ │ ├── main.dart │ │ ├── asn1_der_encoder.dart │ │ ├── x509_public_key.dart │ │ └── key_usage.dart │ ├── main.dart │ └── platform_util.dart ├── flutter_inappwebview.dart └── t_rex_runner │ └── t-rex.css ├── android ├── .idea │ ├── .name │ ├── caches │ │ ├── gradle_models.ser │ │ └── build_file_checksums.ser │ ├── vcs.xml │ ├── modules.xml │ ├── misc.xml │ ├── runConfigurations.xml │ ├── gradle.xml │ └── codeStyles │ │ └── Project.xml ├── settings.gradle ├── gradle.properties ├── .gitignore ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── res │ │ ├── xml │ │ │ └── provider_paths.xml │ │ ├── layout │ │ │ ├── chrome_custom_tabs_layout.xml │ │ │ ├── floating_action_mode_item.xml │ │ │ ├── floating_action_mode.xml │ │ │ └── activity_web_view.xml │ │ ├── drawable │ │ │ └── floating_action_mode_shape.xml │ │ ├── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── menu │ │ │ └── menu_main.xml │ │ ├── java │ │ └── com │ │ │ └── pichillilorenzo │ │ │ └── flutter_inappwebview │ │ │ ├── InAppWebViewFileProvider.java │ │ │ ├── Options.java │ │ │ ├── in_app_browser │ │ │ ├── ActivityResultListener.java │ │ │ └── InAppBrowserDelegate.java │ │ │ ├── types │ │ │ ├── ServerTrustChallenge.java │ │ │ ├── UserScriptInjectionTime.java │ │ │ ├── PreferredContentModeOptionType.java │ │ │ ├── NavigationActionPolicy.java │ │ │ ├── URLAuthenticationChallenge.java │ │ │ ├── ContentWorld.java │ │ │ ├── PluginScript.java │ │ │ └── SslErrorExt.java │ │ │ ├── chrome_custom_tabs │ │ │ ├── KeepAliveService.java │ │ │ ├── ServiceConnectionCallback.java │ │ │ ├── ServiceConnection.java │ │ │ └── ActionBroadcastReceiver.java │ │ │ ├── credential_database │ │ │ ├── URLCredentialContract.java │ │ │ └── URLProtectionSpaceContract.java │ │ │ ├── Shared.java │ │ │ ├── content_blocker │ │ │ ├── ContentBlockerActionType.java │ │ │ ├── ContentBlockerTriggerResourceType.java │ │ │ └── ContentBlocker.java │ │ │ ├── plugin_scripts_js │ │ │ ├── PrintJS.java │ │ │ ├── OnWindowBlurEventJS.java │ │ │ ├── OnWindowFocusEventJS.java │ │ │ ├── ConsoleLogJS.java │ │ │ └── OnLoadResourceJS.java │ │ │ ├── in_app_webview │ │ │ ├── FlutterWebViewFactory.java │ │ │ └── ContextMenuOptions.java │ │ │ ├── WebViewFeatureManager.java │ │ │ └── RequestPermissionHandler.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── example ├── android │ ├── settings_aar.gradle │ ├── gradle.properties │ ├── app │ │ └── src │ │ │ └── main │ │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── java │ │ │ └── com │ │ │ └── pichillilorenzo │ │ │ └── flutterwebviewexample │ │ │ ├── MainActivity.java │ │ │ └── EmbedderV1Activity.java │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── ios │ ├── Flutter │ │ ├── .last_build_id │ │ ├── Release.xcconfig │ │ ├── Debug.xcconfig │ │ ├── flutter_export_environment.sh │ │ ├── Flutter.podspec │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ ├── AppDelegate.swift │ │ └── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ ├── Runner.xcodeproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Podfile ├── integration_test │ └── .env.dart ├── test_assets │ ├── css │ │ ├── blue-body.css │ │ └── style.css │ ├── favicon.ico │ ├── certificate.pfx │ ├── sample_audio.ogg │ ├── sample_video.mp4 │ ├── images │ │ ├── flutter-logo.jpg │ │ └── flutter-logo.png │ ├── in_app_webview_on_console_message_test.html │ ├── in_app_webview_on_create_window_test.html │ ├── in_app_webview_on_js_dialog_test.html │ ├── in_app_webview_javascript_handler_test.html │ ├── in_app_webview_on_navigation_state_change_test.html │ ├── in_app_webview_on_load_resource_custom_scheme_test.html │ ├── in_app_webview_on_load_resource_test.html │ ├── in_app_webview_initial_file_test.html │ ├── page-1.html │ └── page-2.html ├── assets │ ├── js │ │ └── main.js │ ├── favicon.ico │ ├── sample_audio.ogg │ ├── sample_video.mp4 │ ├── images │ │ ├── flutter-logo.jpg │ │ └── flutter-logo.png │ ├── page-1.html │ ├── page-2.html │ └── css │ │ └── style.css ├── README.md ├── .metadata ├── test_driver │ └── integration_test.dart └── .gitignore ├── nodejs_server_test_auth_basic_and_ssl ├── ca-crt.srl ├── public │ ├── css │ │ └── style.css │ ├── js │ │ └── main.js │ └── test-index.html ├── certificate.pfx ├── assets │ └── flutter_logo.png ├── package.json ├── client1.cnf ├── client2.cnf ├── server.cnf ├── ca.cnf ├── client1-csr.pem ├── client2-csr.pem ├── server-csr.pem ├── ca-crt.pem ├── client1-crt.pem ├── client2-crt.pem └── server-crt.pem ├── .gitignore ├── .idea ├── encodings.xml ├── codeStyles │ └── codeStyleConfig.xml ├── libraries │ ├── Flutter_Plugins.xml │ ├── Flutter_for_Android.xml │ └── Dart_SDK.xml ├── vcs.xml ├── runConfigurations │ └── example_lib_main_dart.xml └── modules.xml ├── scripts ├── publish.sh ├── android-wait-for-emulator.sh └── test.sh ├── tool └── env.dart ├── .github ├── autolabeler.yml ├── no-response.yml ├── ISSUE_TEMPLATE │ └── FEATURE_REQUEST.md ├── FUNDING.yml └── PULL_REQUEST_TEMPLATE.md └── flutter_inappwebview_android.iml /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.1.1/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/vcs-1/gc.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/src/ios/main.dart: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gradle/4.4.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gradle/5.1.1/fileChanges/last-build.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/.idea/.name: -------------------------------------------------------------------------------- 1 | flutter_inappbrowser -------------------------------------------------------------------------------- /example/android/settings_aar.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/.last_build_id: -------------------------------------------------------------------------------- 1 | f2dc815feb3d720ac2860b728da31698 -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_inappwebview' 2 | -------------------------------------------------------------------------------- /lib/src/web_storage/ios/main.dart: -------------------------------------------------------------------------------- 1 | export 'web_storage_manager.dart'; 2 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/ca-crt.srl: -------------------------------------------------------------------------------- 1 | B83E5BFA72399E6B 2 | -------------------------------------------------------------------------------- /lib/src/chrome_safari_browser/ios/main.dart: -------------------------------------------------------------------------------- 1 | export 'safari_options.dart'; 2 | -------------------------------------------------------------------------------- /lib/src/in_app_browser/ios/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_browser_options.dart'; 2 | -------------------------------------------------------------------------------- /lib/src/web_storage/android/main.dart: -------------------------------------------------------------------------------- 1 | export 'web_storage_manager.dart'; 2 | -------------------------------------------------------------------------------- /lib/src/in_app_browser/android/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_browser_options.dart'; 2 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/integration_test/.env.dart: -------------------------------------------------------------------------------- 1 | final environment = {"NODE_SERVER_IP":"192.168.1.129"}; -------------------------------------------------------------------------------- /example/test_assets/css/blue-body.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(0, 0, 255); 3 | } -------------------------------------------------------------------------------- /lib/src/chrome_safari_browser/android/main.dart: -------------------------------------------------------------------------------- 1 | export 'chrome_custom_tabs_options.dart'; 2 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/cache.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 01 15:11:27 CEST 2019 2 | gradle.version=5.1.1 3 | -------------------------------------------------------------------------------- /example/assets/js/main.js: -------------------------------------------------------------------------------- 1 | function add(a, b) { 2 | return a + b; 3 | } 4 | console.log(add(10, 20)); -------------------------------------------------------------------------------- /lib/src/web_message/main.dart: -------------------------------------------------------------------------------- 1 | export 'web_message_channel.dart'; 2 | export 'web_message_listener.dart'; -------------------------------------------------------------------------------- /lib/src/android/main.dart: -------------------------------------------------------------------------------- 1 | export 'service_worker_controller.dart'; 2 | export 'webview_feature.dart'; 3 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/public/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: yellow; 3 | color: #333; 4 | } -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/public/js/main.js: -------------------------------------------------------------------------------- 1 | document.querySelector("#test").innerHTML = "this is a test"; -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/assets/favicon.ico -------------------------------------------------------------------------------- /lib/src/in_app_webview/ios/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_webview_options.dart'; 2 | export 'in_app_webview_controller.dart'; 3 | -------------------------------------------------------------------------------- /lib/src/pull_to_refresh/main.dart: -------------------------------------------------------------------------------- 1 | export 'pull_to_refresh_controller.dart'; 2 | export 'pull_to_refresh_options.dart'; 3 | -------------------------------------------------------------------------------- /lib/src/in_app_webview/android/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_webview_options.dart'; 2 | export 'in_app_webview_controller.dart'; 3 | -------------------------------------------------------------------------------- /example/assets/sample_audio.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/assets/sample_audio.ogg -------------------------------------------------------------------------------- /example/assets/sample_video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/assets/sample_video.mp4 -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /example/test_assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/favicon.ico -------------------------------------------------------------------------------- /example/test_assets/certificate.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/certificate.pfx -------------------------------------------------------------------------------- /example/test_assets/sample_audio.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/sample_audio.ogg -------------------------------------------------------------------------------- /example/test_assets/sample_video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/sample_video.mp4 -------------------------------------------------------------------------------- /.gradle/4.4.1/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/.gradle/4.4.1/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /.gradle/5.1.1/fileHashes/fileHashes.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/.gradle/5.1.1/fileHashes/fileHashes.lock -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/.idea/caches/gradle_models.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/android/.idea/caches/gradle_models.ser -------------------------------------------------------------------------------- /example/assets/images/flutter-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/assets/images/flutter-logo.jpg -------------------------------------------------------------------------------- /example/assets/images/flutter-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/assets/images/flutter-logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .vscode/ 5 | .packages 6 | .pub/ 7 | pubspec.lock 8 | 9 | build/ 10 | 11 | .idea/workspace.xml -------------------------------------------------------------------------------- /.gradle/4.4.1/taskHistory/taskHistory.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/.gradle/4.4.1/taskHistory/taskHistory.lock -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /android/.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/android/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /example/test_assets/images/flutter-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/images/flutter-logo.jpg -------------------------------------------------------------------------------- /example/test_assets/images/flutter-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/test_assets/images/flutter-logo.png -------------------------------------------------------------------------------- /lib/src/web_storage/main.dart: -------------------------------------------------------------------------------- 1 | export 'web_storage.dart'; 2 | export 'web_storage_manager.dart'; 3 | export 'android/main.dart'; 4 | export 'ios/main.dart'; 5 | -------------------------------------------------------------------------------- /.gradle/buildOutputCleanup/buildOutputCleanup.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/.gradle/buildOutputCleanup/buildOutputCleanup.lock -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/src/in_app_browser/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_browser.dart'; 2 | export 'in_app_browser_options.dart'; 3 | export 'android/main.dart'; 4 | export 'ios/main.dart'; 5 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/certificate.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/nodejs_server_test_auth_basic_and_ssl/certificate.pfx -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/src/chrome_safari_browser/main.dart: -------------------------------------------------------------------------------- 1 | export 'chrome_safari_browser.dart'; 2 | export 'chrome_safari_browser_options.dart'; 3 | export 'android/main.dart'; 4 | export 'ios/main.dart'; 5 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/assets/flutter_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/nodejs_server_test_auth_basic_and_ssl/assets/flutter_logo.png -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /lib/src/in_app_webview/_static_channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | 3 | const IN_APP_WEBVIEW_STATIC_CHANNEL = 4 | const MethodChannel('com.pichillilorenzo/flutter_inappwebview_static'); 5 | -------------------------------------------------------------------------------- /android/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/src/web_storage/_static_channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | 3 | const WEB_STORAGE_STATIC_CHANNEL = const MethodChannel( 4 | 'com.pichillilorenzo/flutter_inappwebview_webstoragemanager'); 5 | -------------------------------------------------------------------------------- /android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angebagui/flutter_inappwebview/master/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 3 | #include "Generated.xcconfig" 4 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_inappwebview_example 2 | 3 | Demonstrates how to use the flutter_inappwebview plugin. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 3 | #include "Generated.xcconfig" 4 | FLUTTER_BUILD_MODE=debug -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/pichillilorenzo/flutterwebviewexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutterwebviewexample; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | 7 | } -------------------------------------------------------------------------------- /android/src/main/res/layout/chrome_custom_tabs_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/floating_action_mode_shape.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Sep 26 11:13:08 CEST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /scripts/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly SCRIPT_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | readonly PROJECT_DIR="$(dirname $SCRIPT_PATH)" 5 | 6 | cd $PROJECT_DIR/lib 7 | dartfmt -w . 8 | 9 | cd $PROJECT_DIR 10 | flutter analyze 11 | flutter pub publish --dry-run 12 | flutter pub publish -------------------------------------------------------------------------------- /android/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/WebMessageChannelJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebMessageChannelJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 10/03/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let WEB_MESSAGE_CHANNELS_VARIABLE_NAME = "window.\(JAVASCRIPT_BRIDGE_NAME)._webMessageChannels" 11 | -------------------------------------------------------------------------------- /ios/Classes/WKProcessPoolManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKProcessPoolManager.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/11/2019. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | class WKProcessPoolManager { 12 | static let sharedProcessPool = WKProcessPool() 13 | } 14 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: d927c9331005f81157fa39dff7b5dab415ad330b 8 | channel: master 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewFileProvider.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview; 2 | 3 | import androidx.core.content.FileProvider; 4 | 5 | public class InAppWebViewFileProvider extends FileProvider { 6 | 7 | // This class intentionally left blank. 8 | 9 | } 10 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_for_Android.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /lib/src/in_app_webview/main.dart: -------------------------------------------------------------------------------- 1 | export 'webview.dart'; 2 | export 'in_app_webview.dart'; 3 | export 'in_app_webview_controller.dart'; 4 | export 'in_app_webview_options.dart'; 5 | export 'headless_in_app_webview.dart'; 6 | export '../pull_to_refresh/pull_to_refresh_controller.dart'; 7 | export 'android/main.dart'; 8 | export 'ios/main.dart'; 9 | -------------------------------------------------------------------------------- /ios/Classes/PullToRefresh/PullToRefreshDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PullToRefreshDelegate.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 04/03/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol PullToRefreshDelegate { 11 | func enablePullToRefresh() 12 | func disablePullToRefresh() 13 | } 14 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Options.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview; 2 | 3 | import java.util.Map; 4 | 5 | public interface Options { 6 | public Options parse(Map options); 7 | public Map toMap(); 8 | public Map getRealOptions(T obj); 9 | } 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations/example_lib_main_dart.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_browser/ActivityResultListener.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.in_app_browser; 2 | 3 | import android.content.Intent; 4 | 5 | public interface ActivityResultListener { 6 | /** @return true if the result has been handled. */ 7 | boolean onActivityResult(int requestCode, int resultCode, Intent data); 8 | } 9 | -------------------------------------------------------------------------------- /ios/Classes/ContextMenuOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContextMenuOptions.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 30/05/2020. 6 | // 7 | 8 | import Foundation 9 | 10 | class ContextMenuOptions: Options { 11 | 12 | var hideDefaultSystemContextMenuItems = false; 13 | 14 | override init(){ 15 | super.init() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tool/env.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | 5 | Future main() async { 6 | final config = { 7 | 'NODE_SERVER_IP': Platform.environment['NODE_SERVER_IP'], 8 | }; 9 | 10 | final filename = 'example/integration_test/.env.dart'; 11 | await File(filename) 12 | .writeAsString('final environment = ${json.encode(config)};'); 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | 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. -------------------------------------------------------------------------------- /lib/src/x509_certificate/main.dart: -------------------------------------------------------------------------------- 1 | // from https://github.com/filom/ASN1Decoder 2 | 3 | export 'asn1_decoder.dart'; 4 | export 'asn1_distinguished_names.dart'; 5 | export 'asn1_identifier.dart'; 6 | export 'asn1_object.dart'; 7 | export 'oid.dart'; 8 | export 'key_usage.dart'; 9 | export 'x509_certificate.dart'; 10 | export 'x509_extension.dart'; 11 | export 'x509_public_key.dart'; 12 | export 'asn1_der_encoder.dart'; 13 | -------------------------------------------------------------------------------- /.github/autolabeler.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-auto-labeler - https://github.com/probot/autolabeler 2 | 3 | # label: file | path 4 | android: ["/android", "*.kt", "*.java", "*gradle*", "AndroidManifest.xml"] 5 | iOS: ["/ios", "*.swift", "*.h", "*.m", "*.xcodeproj", "*.xcworkspace", "*.plist", "*.storyboard", "*.xcconfig", Podfile*"] 6 | flutter/dart: ["/lib", "*.dart"] 7 | documentation: ["*.md"] 8 | legal: ["LICENSE*", "NOTICES*"] 9 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Go Back 4 | Go Forward 5 | Reload 6 | Share 7 | Close 8 | Search 9 | 10 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node_auth_basic", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "basic-auth": "latest", 13 | "cors": "^2.8.5", 14 | "express": "latest", 15 | "https": "latest" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/ServerTrustChallenge.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | public class ServerTrustChallenge extends URLAuthenticationChallenge { 4 | public ServerTrustChallenge(URLProtectionSpace protectionSpace) { 5 | super(protectionSpace); 6 | } 7 | 8 | @Override 9 | public String toString() { 10 | return "ServerTrustChallenge{} " + super.toString(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ios/Classes/FlutterMethodCallDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlutterMethodCallDelegate.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/12/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | public class FlutterMethodCallDelegate: NSObject { 11 | public override init() { 12 | super.init() 13 | } 14 | 15 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/Classes/Types/WebViewTransport.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewTransport.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class WebViewTransport: NSObject { 11 | var webView: InAppWebView 12 | var request: URLRequest 13 | 14 | init(webView: InAppWebView, request: URLRequest) { 15 | self.webView = webView 16 | self.request = request 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/Classes/Types/WKSecurityOrigin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKSecurityOrigin.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | @available(iOS 9.0, *) 12 | extension WKSecurityOrigin { 13 | public func toMap () -> [String:Any?] { 14 | return [ 15 | "host": host, 16 | "port": port, 17 | "protocol": self.protocol 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ios/Classes/Types/WKNavigationResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKNavigationResponse.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | extension WKNavigationResponse { 12 | public func toMap () -> [String:Any?] { 13 | return [ 14 | "response": response.toMap(), 15 | "isForMainFrame": isForMainFrame, 16 | "canShowMIMEType": canShowMIMEType, 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/test_driver/integration_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | import 'package:flutter_driver/flutter_driver.dart'; 5 | 6 | Future main() async { 7 | final FlutterDriver driver = await FlutterDriver.connect(); 8 | final String data = 9 | await driver.requestData(null, timeout: const Duration(minutes: 1)); 10 | await driver.close(); 11 | final Map result = jsonDecode(data); 12 | exit(result['result'] == 'true' ? 0 : 1); 13 | } 14 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 5 5 | # Label requiring a response 6 | responseRequiredLabel: answered 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because it was marked as "answered", and there wasn't any recent activity on this issue. 10 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /ios/Classes/InAppBrowser/InAppBrowserDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InAppBrowserDelegate.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 14/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public protocol InAppBrowserDelegate { 11 | func didChangeTitle(title: String?) 12 | func didStartNavigation(url: URL?) 13 | func didUpdateVisitedHistory(url: URL?) 14 | func didFinishNavigation(url: URL?) 15 | func didFailNavigation(url: URL?, error: Error) 16 | func didChangeProgress(progress: Double) 17 | } 18 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /android/src/main/res/layout/floating_action_mode_item.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Classes/Types/SecCertificate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecCertificate.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension SecCertificate { 11 | var data: Data { 12 | let serverCertificateCFData = SecCertificateCopyData(self) 13 | let data = CFDataGetBytePtr(serverCertificateCFData) 14 | let size = CFDataGetLength(serverCertificateCFData) 15 | let certificateData = NSData(bytes: data, length: size) 16 | return Data(certificateData) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/WindowIdJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WindowIdJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let WINDOW_ID_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_WINDOW_ID_JS_PLUGIN_SCRIPT" 11 | 12 | let WINDOW_ID_VARIABLE_JS_SOURCE = "window._\(JAVASCRIPT_BRIDGE_NAME)_windowId" 13 | 14 | let WINDOW_ID_INITIALIZE_JS_SOURCE = """ 15 | (function() { 16 | \(WINDOW_ID_VARIABLE_JS_SOURCE) = \(PluginScriptsUtil.VAR_PLACEHOLDER_VALUE); 17 | return \(WINDOW_ID_VARIABLE_JS_SOURCE); 18 | })() 19 | """ 20 | -------------------------------------------------------------------------------- /ios/Classes/Types/ClientCertChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClientCertChallenge.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | class ClientCertChallenge: NSObject { 11 | var protectionSpace: URLProtectionSpace! 12 | 13 | public init(fromChallenge: URLAuthenticationChallenge) { 14 | protectionSpace = fromChallenge.protectionSpace 15 | } 16 | 17 | public func toMap () -> [String:Any?] { 18 | return [ 19 | "protectionSpace": protectionSpace.toMap(), 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ios/Classes/Types/ServerTrustChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServerTrustChallenge.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | class ServerTrustChallenge: NSObject { 11 | var protectionSpace: URLProtectionSpace! 12 | 13 | public init(fromChallenge: URLAuthenticationChallenge) { 14 | protectionSpace = fromChallenge.protectionSpace 15 | } 16 | 17 | public func toMap () -> [String:Any?] { 18 | return [ 19 | "protectionSpace": protectionSpace.toMap() 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/public/test-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Flutter InAppWebView 8 | 9 | 10 | 11 |

TEST

12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /ios/Classes/InAppBrowser/InAppBrowserNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InAppBrowserNavigationController.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 14/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class InAppBrowserNavigationController: UINavigationController { 11 | var tmpWindow: UIWindow? 12 | 13 | deinit { 14 | print("InAppBrowserNavigationController - dealloc") 15 | tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0) 16 | tmpWindow = nil 17 | UIApplication.shared.delegate?.window??.makeKeyAndVisible() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:4.0.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_console_message_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnConsoleMessageTest 8 | 9 | 10 |

InAppWebViewOnConsoleMessageTest

11 | 14 | 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | ## Environment 8 | 9 | **Flutter version:** 10 | **Plugin version:** 11 | **Android version:** 12 | **iOS version:** 13 | **Xcode version:** 14 | **Device information:** 15 | 16 | ## Description 17 | 18 | **What you'd like to happen:** 19 | 20 | **Alternatives you've considered:** 21 | 22 | **Images:** 23 | -------------------------------------------------------------------------------- /example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/Applications/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/macbookpro/MobileApps/flutter_inappwebview/example" 5 | export "FLUTTER_TARGET=lib/main.dart" 6 | export "FLUTTER_BUILD_DIR=build" 7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios" 8 | export "FLUTTER_BUILD_NAME=1.0.0" 9 | export "FLUTTER_BUILD_NUMBER=1" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=false" 12 | export "TREE_SHAKE_ICONS=false" 13 | export "PACKAGE_CONFIG=.packages" 14 | -------------------------------------------------------------------------------- /android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /ios/Classes/Types/WebMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebMessage.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 10/03/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class WebMessage : NSObject { 11 | var data: String? 12 | var ports: [WebMessagePort]? 13 | 14 | public init(data: String?, ports: [WebMessagePort]?) { 15 | super.init() 16 | self.data = data 17 | self.ports = ports 18 | } 19 | 20 | public func dispose() { 21 | ports?.removeAll() 22 | } 23 | 24 | deinit { 25 | print("WebMessage - dealloc") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/chrome_custom_tabs/KeepAliveService.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Binder; 6 | import android.os.IBinder; 7 | 8 | /** 9 | * Empty service used by the custom tab to bind to, raising the application's importance. 10 | */ 11 | public class KeepAliveService extends Service { 12 | private static final Binder sBinder = new Binder(); 13 | 14 | @Override 15 | public IBinder onBind(Intent intent) { 16 | return sBinder; 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Classes/Types/WKNavigationAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKNavigationAction.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | extension WKNavigationAction { 12 | public func toMap () -> [String:Any?] { 13 | return [ 14 | "request": request.toMap(), 15 | "isForMainFrame": targetFrame?.isMainFrame ?? false, 16 | "iosWKNavigationType": navigationType.rawValue, 17 | "iosSourceFrame": sourceFrame.toMap(), 18 | "iosTargetFrame": targetFrame?.toMap() 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/pichillilorenzo/flutterwebviewexample/EmbedderV1Activity.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutterwebviewexample; 2 | 3 | import android.os.Bundle; 4 | import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin; 5 | 6 | @SuppressWarnings("deprecation") 7 | public class EmbedderV1Activity extends io.flutter.app.FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | InAppWebViewFlutterPlugin.registerWith( 12 | registrarFor("com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin")); 13 | } 14 | } -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # WebView 2 | -keepattributes *JavascriptInterface* 3 | -keepclassmembers class * { 4 | @android.webkit.JavascriptInterface ; 5 | } 6 | -keepclassmembers class * extends android.webkit.WebViewClient { 7 | public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); 8 | public boolean *(android.webkit.WebView, java.lang.String); 9 | public void *(android.webkit.webView, jav.lang.String); 10 | } 11 | -keepclassmembers class flutter_inappwebview$JavaScriptBridgeInterface { 12 | ; 13 | ; 14 | public *; 15 | private *; 16 | } 17 | -keep class flutter_inappwebview.** { *; } -------------------------------------------------------------------------------- /ios/Classes/LeakAvoider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LeakAvoider.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/12/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | public class LeakAvoider: NSObject { 11 | weak var delegate : FlutterMethodCallDelegate? 12 | 13 | init(delegate: FlutterMethodCallDelegate) { 14 | super.init() 15 | self.delegate = delegate 16 | } 17 | 18 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 19 | self.delegate?.handle(call, result: result) 20 | } 21 | 22 | deinit { 23 | print("LeakAvoider - dealloc") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ios/Classes/Types/URLAuthenticationChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLAuthenticationChallenge.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension URLAuthenticationChallenge { 11 | public func toMap () -> [String:Any?] { 12 | return [ 13 | "protectionSpace": protectionSpace.toMap(), 14 | "previousFailureCount": previousFailureCount, 15 | "iosFailureResponse": failureResponse?.toMap(), 16 | "iosError": error?.localizedDescription, 17 | "proposedCredential": proposedCredential?.toMap(), 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_browser/InAppBrowserDelegate.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.in_app_browser; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.List; 6 | 7 | public interface InAppBrowserDelegate { 8 | Activity getActivity(); 9 | List getActivityResultListeners(); 10 | void didChangeTitle(String title); 11 | void didStartNavigation(String url); 12 | void didUpdateVisitedHistory(String url); 13 | void didFinishNavigation(String url); 14 | void didFailNavigation(String url, int errorCode, String description); 15 | void didChangeProgress(int progress); 16 | } 17 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/chrome_custom_tabs/ServiceConnectionCallback.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs; 2 | 3 | import androidx.browser.customtabs.CustomTabsClient; 4 | 5 | /** 6 | * Callback for events when connecting and disconnecting from Custom Tabs Service. 7 | */ 8 | public interface ServiceConnectionCallback { 9 | /** 10 | * Called when the service is connected. 11 | * @param client a CustomTabsClient 12 | */ 13 | void onServiceConnected(CustomTabsClient client); 14 | 15 | /** 16 | * Called when the service is disconnected. 17 | */ 18 | void onServiceDisconnected(); 19 | } -------------------------------------------------------------------------------- /ios/Classes/Types/WKWindowFeatures.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKWindowFeatures.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | extension WKWindowFeatures { 12 | public func toMap () -> [String:Any?] { 13 | return [ 14 | "allowsResizing": allowsResizing, 15 | "height": height, 16 | "menuBarVisibility": menuBarVisibility, 17 | "statusBarVisibility": statusBarVisibility, 18 | "toolbarsVisibility": toolbarsVisibility, 19 | "width": width, 20 | "x": x, 21 | "y": y 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_create_window_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnCreateWindowTest 8 | 9 | 10 |

InAppWebViewOnCreateWindowTest

11 | target blank 12 | 15 | 16 | -------------------------------------------------------------------------------- /lib/src/main.dart: -------------------------------------------------------------------------------- 1 | export 'in_app_webview/main.dart'; 2 | export 'in_app_browser/main.dart'; 3 | export 'chrome_safari_browser/main.dart'; 4 | export 'android/main.dart'; 5 | export 'ios/main.dart'; 6 | export 'x509_certificate/main.dart'; 7 | export 'web_storage/main.dart'; 8 | export 'types.dart'; 9 | export 'in_app_webview/headless_in_app_webview.dart'; 10 | export 'in_app_webview/in_app_webview.dart'; 11 | export 'in_app_browser/in_app_browser.dart'; 12 | export 'cookie_manager.dart'; 13 | export 'in_app_localhost_server.dart'; 14 | export 'content_blocker.dart'; 15 | export 'http_auth_credentials_database.dart'; 16 | export 'context_menu.dart'; 17 | export 'pull_to_refresh/main.dart'; 18 | export 'web_message/main.dart'; 19 | -------------------------------------------------------------------------------- /scripts/android-wait-for-emulator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set +e 4 | 5 | bootanim="" 6 | failcounter=0 7 | timeout_in_sec=360 8 | 9 | until [[ "$bootanim" =~ "stopped" ]]; do 10 | bootanim=`adb -e shell getprop init.svc.bootanim 2>&1 &` 11 | if [[ "$bootanim" =~ "device not found" || "$bootanim" =~ "device offline" 12 | || "$bootanim" =~ "running" ]]; then 13 | let "failcounter += 1" 14 | echo "Waiting for emulator to start: $failcounter of $timeout_in_sec : status: $bootanim" 15 | if [[ $failcounter -gt timeout_in_sec ]]; then 16 | echo "Timeout ($timeout_in_sec seconds) reached; failed to start emulator" 17 | exit 1 18 | fi 19 | fi 20 | sleep 1 21 | done 22 | 23 | echo "Emulator is ready" -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/URLCredentialContract.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.credential_database; 2 | 3 | import android.provider.BaseColumns; 4 | 5 | public class URLCredentialContract { 6 | private URLCredentialContract() {} 7 | 8 | /* Inner class that defines the table contents */ 9 | public static class FeedEntry implements BaseColumns { 10 | public static final String TABLE_NAME = "credential"; 11 | public static final String COLUMN_NAME_USERNAME = "username"; 12 | public static final String COLUMN_NAME_PASSWORD = "password"; 13 | public static final String COLUMN_NAME_PROTECTION_SPACE_ID = "protection_space_id"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/PrintJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PrintJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let PRINT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_PRINT_JS_PLUGIN_SCRIPT" 11 | 12 | let PRINT_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: PRINT_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: PRINT_JS_SOURCE, 15 | injectionTime: .atDocumentStart, 16 | forMainFrameOnly: false, 17 | requiredInAllContentWorlds: true, 18 | messageHandlerNames: []) 19 | 20 | let PRINT_JS_SOURCE = """ 21 | window.print = function() { 22 | window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onPrint", window.location.href); 23 | } 24 | """ 25 | -------------------------------------------------------------------------------- /android/src/main/res/layout/floating_action_mode.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /ios/Classes/Types/URLResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLResponse.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension URLResponse { 11 | public func toMap () -> [String:Any?] { 12 | let httpResponse: HTTPURLResponse? = self as? HTTPURLResponse 13 | return [ 14 | "expectedContentLength": expectedContentLength, 15 | "mimeType": mimeType, 16 | "suggestedFilename": suggestedFilename, 17 | "textEncodingName": textEncodingName, 18 | "url": url?.absoluteString, 19 | "headers": httpResponse?.allHeaderFields, 20 | "statusCode": httpResponse?.statusCode 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 19 | 20 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/credential_database/URLProtectionSpaceContract.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.credential_database; 2 | 3 | import android.provider.BaseColumns; 4 | 5 | public class URLProtectionSpaceContract { 6 | private URLProtectionSpaceContract() {} 7 | 8 | /* Inner class that defines the table contents */ 9 | public static class FeedEntry implements BaseColumns { 10 | public static final String TABLE_NAME = "protection_space"; 11 | public static final String COLUMN_NAME_HOST = "host"; 12 | public static final String COLUMN_NAME_PROTOCOL = "protocol"; 13 | public static final String COLUMN_NAME_REALM = "realm"; 14 | public static final String COLUMN_NAME_PORT = "port"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/Shared.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 7 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; 8 | import io.flutter.plugin.common.BinaryMessenger; 9 | import io.flutter.plugin.common.PluginRegistry; 10 | 11 | public class Shared { 12 | public static Context applicationContext; 13 | public static PluginRegistry.Registrar registrar; 14 | public static BinaryMessenger messenger; 15 | public static FlutterPlugin.FlutterAssets flutterAssets; 16 | public static ActivityPluginBinding activityPluginBinding; 17 | public static Activity activity; 18 | } 19 | -------------------------------------------------------------------------------- /ios/Classes/Types/URLCredential.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLCredential.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension URLCredential { 11 | public func toMap () -> [String:Any?] { 12 | var x509Certificates: [Data] = [] 13 | // certificates could be nil!!! 14 | if certificates != nil { 15 | for certificate in certificates { 16 | x509Certificates.append((certificate as! SecCertificate).data) 17 | } 18 | } 19 | return [ 20 | "password": password, 21 | "username": user, 22 | "iosCertificates": x509Certificates, 23 | "iosPersistence": persistence.rawValue 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.paypal.me/LorenzoPichilli'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client1.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 4096 3 | days = 9999 4 | distinguished_name = req_distinguished_name 5 | attributes = req_attributes 6 | prompt = no 7 | x509_extensions = v3_ca 8 | 9 | [ req_distinguished_name ] 10 | C = US 11 | ST = MA 12 | L = Boston 13 | O = Example Co 14 | OU = techops 15 | CN = client1 16 | emailAddress = certs@example.com 17 | 18 | [ req_attributes ] 19 | challengePassword = password 20 | 21 | [ v3_ca ] 22 | authorityInfoAccess = @issuer_info 23 | 24 | [ issuer_info ] 25 | OCSP;URI.0 = http://ocsp.example.com/ 26 | caIssuers;URI.0 = http://example.com/ca.cert 27 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client2.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 4096 3 | days = 9999 4 | distinguished_name = req_distinguished_name 5 | attributes = req_attributes 6 | prompt = no 7 | x509_extensions = v3_ca 8 | 9 | [ req_distinguished_name ] 10 | C = US 11 | ST = MA 12 | L = Boston 13 | O = Example Co 14 | OU = techops 15 | CN = client2 16 | emailAddress = certs@example.com 17 | 18 | [ req_attributes ] 19 | challengePassword = password 20 | 21 | [ v3_ca ] 22 | authorityInfoAccess = @issuer_info 23 | 24 | [ issuer_info ] 25 | OCSP;URI.0 = http://ocsp.example.com/ 26 | caIssuers;URI.0 = http://example.com/ca.cert 27 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/server.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 4096 3 | days = 9999 4 | distinguished_name = req_distinguished_name 5 | attributes = req_attributes 6 | prompt = no 7 | x509_extensions = v3_ca 8 | 9 | [ req_distinguished_name ] 10 | C = US 11 | ST = MA 12 | L = Boston 13 | O = Example Co 14 | OU = techops 15 | CN = localhost 16 | emailAddress = certs@example.com 17 | 18 | [ req_attributes ] 19 | challengePassword = password 20 | 21 | [ v3_ca ] 22 | authorityInfoAccess = @issuer_info 23 | 24 | [ issuer_info ] 25 | OCSP;URI.0 = http://ocsp.example.com/ 26 | caIssuers;URI.0 = http://example.com/ca.cert 27 | -------------------------------------------------------------------------------- /ios/Classes/Types/WKFrameInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKFrameInfo.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | extension WKFrameInfo { 12 | 13 | public func toMap () -> [String:Any?] { 14 | var securityOrigin: [String:Any?]? = nil 15 | if #available(iOS 9.0, *) { 16 | securityOrigin = self.securityOrigin.toMap() 17 | } 18 | // fix: self.request throws EXC_BREAKPOINT when coming from WKNavigationAction.sourceFrame 19 | let request: URLRequest? = self.value(forKey: "request") as? URLRequest 20 | return [ 21 | "isMainFrame": isMainFrame, 22 | "request": request?.toMap(), 23 | "securityOrigin": securityOrigin 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ios/Classes/Types/SslCertificate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SslCertificate.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class SslCertificate: NSObject { 11 | var x509Certificate: Data 12 | var issuedBy: Any? 13 | var issuedTo: Any? 14 | var validNotAfterDate: Any? 15 | var validNotBeforeDate: Any? 16 | 17 | public init(x509Certificate: Data) { 18 | self.x509Certificate = x509Certificate 19 | } 20 | 21 | public func toMap () -> [String:Any?] { 22 | return [ 23 | "x509Certificate": x509Certificate, 24 | "issuedBy": issuedBy, 25 | "issuedTo": issuedTo, 26 | "validNotAfterDate": validNotAfterDate, 27 | "validNotBeforeDate": validNotBeforeDate 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/UserScriptInjectionTime.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | public enum UserScriptInjectionTime { 4 | AT_DOCUMENT_START (0), 5 | AT_DOCUMENT_END (1); 6 | 7 | private final int value; 8 | 9 | private UserScriptInjectionTime(int value) { 10 | this.value = value; 11 | } 12 | 13 | public boolean equalsValue(int otherValue) { 14 | return value == otherValue; 15 | } 16 | 17 | public static UserScriptInjectionTime fromValue(int value) { 18 | for( UserScriptInjectionTime type : UserScriptInjectionTime.values()) { 19 | if(value == type.toValue()) 20 | return type; 21 | } 22 | throw new IllegalArgumentException("No enum constant: " + value); 23 | } 24 | 25 | public int toValue() { 26 | return this.value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | //import flutter_downloader 4 | 5 | @UIApplicationMain 6 | 7 | @objc class AppDelegate: FlutterAppDelegate { 8 | 9 | override func application( 10 | _ application: UIApplication, 11 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 12 | ) -> Bool { 13 | GeneratedPluginRegistrant.register(with: self) 14 | //FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins) 15 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 16 | } 17 | } 18 | 19 | //private func registerPlugins(registry: FlutterPluginRegistry) { 20 | // if (!registry.hasPlugin("FlutterDownloaderPlugin")) { 21 | // FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!) 22 | // } 23 | //} 24 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/OnWindowFocusEventJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnWindowFocusEventJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT" 11 | 12 | let ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: ON_WINDOW_FOCUS_EVENT_JS_SOURCE, 14 | source: ON_WINDOW_FOCUS_EVENT_JS_SOURCE, 15 | injectionTime: .atDocumentStart, 16 | forMainFrameOnly: true, 17 | requiredInAllContentWorlds: false, 18 | messageHandlerNames: []) 19 | 20 | let ON_WINDOW_FOCUS_EVENT_JS_SOURCE = """ 21 | (function(){ 22 | window.addEventListener('focus', function(e) { 23 | window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onWindowFocus'); 24 | }); 25 | })(); 26 | """ 27 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/OnWindowBlurEventJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OnWindowBlurEventJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT" 11 | 12 | let ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: ON_WINDOW_BLUR_EVENT_JS_SOURCE, 15 | injectionTime: .atDocumentStart, 16 | forMainFrameOnly: true, 17 | requiredInAllContentWorlds: false, 18 | messageHandlerNames: []) 19 | 20 | let ON_WINDOW_BLUR_EVENT_JS_SOURCE = """ 21 | (function(){ 22 | window.addEventListener('blur', function(e) { 23 | window.\(JAVASCRIPT_BRIDGE_NAME).callHandler('onWindowBlur'); 24 | }); 25 | })(); 26 | """ 27 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/ca.cnf: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default 3 | 4 | [ CA_default ] 5 | serial = ca-serial 6 | crl = ca-crl.pem 7 | database = ca-database.txt 8 | name_opt = CA_default 9 | cert_opt = CA_default 10 | default_crl_days = 9999 11 | default_md = md5 12 | 13 | [ req ] 14 | default_bits = 4096 15 | days = 9999 16 | distinguished_name = req_distinguished_name 17 | attributes = req_attributes 18 | prompt = no 19 | output_password = password 20 | 21 | [ req_distinguished_name ] 22 | C = US 23 | ST = MA 24 | L = Boston 25 | O = Example Co 26 | OU = techops 27 | CN = ca 28 | emailAddress = certs@example.com 29 | 30 | [ req_attributes ] 31 | challengePassword = test 32 | -------------------------------------------------------------------------------- /example/ios/Flutter/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: This podspec is NOT to be published. It is only used as a local source! 3 | # This is a generated file; do not edit or check into version control. 4 | # 5 | 6 | Pod::Spec.new do |s| 7 | s.name = 'Flutter' 8 | s.version = '1.0.0' 9 | s.summary = 'High-performance, high-fidelity mobile apps.' 10 | s.homepage = 'https://flutter.io' 11 | s.license = { :type => 'MIT' } 12 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 13 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 14 | s.ios.deployment_target = '8.0' 15 | # Framework linking is handled by Flutter tooling, not CocoaPods. 16 | # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. 17 | s.vendored_frameworks = 'path/to/nothing' 18 | end 19 | -------------------------------------------------------------------------------- /lib/src/x509_certificate/asn1_der_encoder.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | import 'asn1_identifier.dart'; 3 | 4 | class ASN1DEREncoder { 5 | static Uint8List encodeSequence({required Uint8List content}) { 6 | var encoded = Uint8List.fromList([]); 7 | encoded.add(ASN1Identifier.constructedTag | 8 | ASN1IdentifierTagNumber.SEQUENCE.toValue()); 9 | encoded.addAll(contentLength(size: content.length)); 10 | encoded.addAll(content); 11 | return Uint8List.fromList(encoded); 12 | } 13 | 14 | static Uint8List contentLength({required int size}) { 15 | if (size >= 128) { 16 | var lenBytes = Uint8List(size); 17 | while (lenBytes.first == 0) { 18 | lenBytes.removeAt(0); 19 | } 20 | int len = 0x80 | lenBytes.length; 21 | return Uint8List(len)..addAll(lenBytes); 22 | } else { 23 | return Uint8List(size); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/PreferredContentModeOptionType.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | public enum PreferredContentModeOptionType { 4 | RECOMMENDED (0), 5 | MOBILE (1), 6 | DESKTOP (2); 7 | 8 | private final int value; 9 | 10 | private PreferredContentModeOptionType(int value) { 11 | this.value = value; 12 | } 13 | 14 | public boolean equalsValue(int otherValue) { 15 | return value == otherValue; 16 | } 17 | 18 | public static PreferredContentModeOptionType fromValue(int value) { 19 | for( PreferredContentModeOptionType type : PreferredContentModeOptionType.values()) { 20 | if(value == type.toValue()) 21 | return type; 22 | } 23 | throw new IllegalArgumentException("No enum constant: " + value); 24 | } 25 | 26 | public int toValue() { 27 | return this.value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_js_dialog_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnJsDialogTest 8 | 9 | 10 |

InAppWebViewOnJsDialogTest

11 | 18 | 19 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/NavigationActionPolicy.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | public enum NavigationActionPolicy { 4 | CANCEL(0), 5 | ALLOW(1); 6 | 7 | private final int value; 8 | 9 | private NavigationActionPolicy(int value) { 10 | this.value = value; 11 | } 12 | 13 | public boolean equalsValue(int otherValue) { 14 | return value == otherValue; 15 | } 16 | 17 | public static NavigationActionPolicy fromValue(int value) { 18 | for( NavigationActionPolicy type : NavigationActionPolicy.values()) { 19 | if(value == type.value) 20 | return type; 21 | } 22 | throw new IllegalArgumentException("No enum constant: " + value); 23 | } 24 | 25 | public int rawValue() { 26 | return this.value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.valueOf(this.value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_javascript_handler_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewJavaScriptHandlerTest 8 | 9 | 10 |

InAppWebViewJavaScriptHandlerTest

11 | 20 | 21 | -------------------------------------------------------------------------------- /lib/flutter_inappwebview.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | library flutter_inappwebview; 23 | 24 | export 'src/main.dart'; 25 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | readonly SCRIPT_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | readonly PROJECT_DIR="$(dirname $SCRIPT_PATH)" 5 | 6 | function error() { 7 | echo "$@" 1>&2 8 | } 9 | 10 | # on macOS local IP can be found using $(ipconfig getifaddr en0) 11 | # on linux local IP can be found using $(ifconfig en0 | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}') or $(ip route get 1 | awk '{print $NF;exit}') 12 | export NODE_SERVER_IP=$1 13 | FAILED=0 14 | 15 | dart $PROJECT_DIR/tool/env.dart 16 | 17 | cd $PROJECT_DIR/nodejs_server_test_auth_basic_and_ssl 18 | node index.js & 19 | 20 | flutter clean 21 | cd $PROJECT_DIR/example 22 | flutter clean 23 | flutter driver --driver=test_driver/integration_test.dart --target=integration_test/webview_flutter_test.dart 24 | 25 | if [ $? -eq 0 ]; then 26 | echo "Integration tests passed successfully." 27 | else 28 | error "Some integration tests failed." 29 | FAILED=1 30 | fi 31 | 32 | kill $(jobs -p) 33 | 34 | exit $FAILED -------------------------------------------------------------------------------- /ios/Classes/PullToRefresh/PullToRefreshOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PullToRefreshOptions.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 03/03/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class PullToRefreshOptions : Options { 11 | 12 | var enabled = true 13 | var color: String? 14 | var backgroundColor: String? 15 | var attributedTitle: [String: Any?]? 16 | 17 | override init(){ 18 | super.init() 19 | } 20 | 21 | override func parse(options: [String: Any?]) -> PullToRefreshOptions { 22 | let _ = super.parse(options: options) 23 | if let attributedTitle = options["attributedTitle"] as? [String: Any?] { 24 | self.attributedTitle = attributedTitle 25 | } 26 | return self 27 | } 28 | 29 | override func getRealOptions(obj: PullToRefreshControl?) -> [String: Any?] { 30 | let realOptions: [String: Any?] = toMap() 31 | return realOptions 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/content_blocker/ContentBlockerActionType.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.content_blocker; 2 | 3 | public enum ContentBlockerActionType { 4 | BLOCK ("block"), 5 | CSS_DISPLAY_NONE ("css-display-none"), 6 | MAKE_HTTPS ("make-https"); 7 | 8 | private final String value; 9 | 10 | private ContentBlockerActionType(String value) { 11 | this.value = value; 12 | } 13 | 14 | public boolean equalsValue(String otherValue) { 15 | return value.equals(otherValue); 16 | } 17 | 18 | public static ContentBlockerActionType fromValue(String value) { 19 | for( ContentBlockerActionType type : ContentBlockerActionType.values()) { 20 | if(value.equals(type.value)) 21 | return type; 22 | } 23 | throw new IllegalArgumentException("No enum constant: " + value); 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return this.value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/CallAsyncJavaScriptBelowIOS14WrapperJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CallAsyncJavaScriptBelowIOS14WrapperJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let CALL_ASYNC_JAVASCRIPT_BELOW_IOS_14_WRAPPER_JS = """ 11 | (function(obj) { 12 | (async function(\(PluginScriptsUtil.VAR_FUNCTION_ARGUMENT_NAMES) { 13 | \(PluginScriptsUtil.VAR_FUNCTION_BODY) 14 | })(\(PluginScriptsUtil.VAR_FUNCTION_ARGUMENT_VALUES)).then(function(value) { 15 | window.webkit.messageHandlers['onCallAsyncJavaScriptResultBelowIOS14Received'].postMessage({'value': value, 'error': null, 'resultUuid': '\(PluginScriptsUtil.VAR_RESULT_UUID)'}); 16 | }).catch(function(error) { 17 | window.webkit.messageHandlers['onCallAsyncJavaScriptResultBelowIOS14Received'].postMessage({'value': null, 'error': error + '', 'resultUuid': '\(PluginScriptsUtil.VAR_RESULT_UUID)'}); 18 | }); 19 | return null; 20 | })(\(PluginScriptsUtil.VAR_FUNCTION_ARGUMENTS_OBJ)); 21 | """ 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Connection with issue(s) 2 | 3 | Resolve issue #??? 4 | 5 | 6 | 7 | Connected to #??? 8 | 9 | 10 | 11 | ## Testing and Review Notes 12 | 13 | 14 | 15 | 16 | ## Screenshots or Videos 17 | 18 | 19 | 20 | ## To Do 21 | 22 | 23 | - [ ] double check the original issue to confirm it is fully satisfied 24 | - [ ] add testing notes and screenshots in PR description to help guide reviewers 25 | - [ ] request the "UX" team perform a design review (if/when applicable) 26 | -------------------------------------------------------------------------------- /ios/Classes/InAppWebViewFlutterPlugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface InAppWebViewFlutterPlugin : NSObject 21 | + (void)registerWithRegistrar:(nonnull NSObject *)registrar; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_navigation_state_change_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnNavigationStateChangeTest 8 | 9 | 10 | 11 |

InAppWebViewOnNavigationStateChangeTest

12 | 25 | 26 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_load_resource_custom_scheme_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnLoadResourceCustomSchemeTest 8 | 9 | 10 |
11 |
12 |

InAppWebViewOnLoadResourceCustomSchemeTest

13 | flutter logo 14 |
15 |
16 | 17 | 23 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/PrintJS.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; 4 | import com.pichillilorenzo.flutter_inappwebview.types.UserScriptInjectionTime; 5 | 6 | public class PrintJS { 7 | public static final String PRINT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_PRINT_JS_PLUGIN_SCRIPT"; 8 | public static final PluginScript PRINT_JS_PLUGIN_SCRIPT = new PluginScript( 9 | PrintJS.PRINT_JS_PLUGIN_SCRIPT_GROUP_NAME, 10 | PrintJS.PRINT_JS_SOURCE, 11 | UserScriptInjectionTime.AT_DOCUMENT_START, 12 | null, 13 | false 14 | ); 15 | 16 | public static final String PRINT_JS_SOURCE = "window.print = function() {" + 17 | " if (window.top == null || window.top === window) {" + 18 | " window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onPrint', window.location.href);" + 19 | " } else {" + 20 | " window.top.print();" + 21 | " }" + 22 | "};"; 23 | } 24 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/FlutterWebViewFactory.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.in_app_webview; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import java.util.HashMap; 7 | 8 | import io.flutter.plugin.common.BinaryMessenger; 9 | import io.flutter.plugin.common.StandardMessageCodec; 10 | import io.flutter.plugin.platform.PlatformView; 11 | import io.flutter.plugin.platform.PlatformViewFactory; 12 | 13 | public class FlutterWebViewFactory extends PlatformViewFactory { 14 | private final View containerView; 15 | private final BinaryMessenger messenger; 16 | 17 | public FlutterWebViewFactory(BinaryMessenger messenger, View containerView) { 18 | super(StandardMessageCodec.INSTANCE); 19 | this.containerView = containerView; 20 | this.messenger = messenger; 21 | } 22 | 23 | @Override 24 | public PlatformView create(Context context, int id, Object args) { 25 | HashMap params = (HashMap) args; 26 | return new FlutterWebView(messenger, context, id, params, containerView); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/OnWindowBlurEventJS.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; 4 | import com.pichillilorenzo.flutter_inappwebview.types.UserScriptInjectionTime; 5 | 6 | public class OnWindowBlurEventJS { 7 | public static final String ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT"; 8 | public static final PluginScript ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT = new PluginScript( 9 | OnWindowBlurEventJS.ON_WINDOW_BLUR_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME, 10 | OnWindowBlurEventJS.ON_WINDOW_BLUR_EVENT_JS_SOURCE, 11 | UserScriptInjectionTime.AT_DOCUMENT_START, 12 | null, 13 | false 14 | ); 15 | 16 | public static final String ON_WINDOW_BLUR_EVENT_JS_SOURCE = "(function(){" + 17 | " window.addEventListener('blur', function(e) {" + 18 | " window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onWindowBlur');" + 19 | " });" + 20 | "})();"; 21 | } 22 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/OnWindowFocusEventJS.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; 4 | import com.pichillilorenzo.flutter_inappwebview.types.UserScriptInjectionTime; 5 | 6 | public class OnWindowFocusEventJS { 7 | public static final String ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT"; 8 | public static final PluginScript ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT = new PluginScript( 9 | OnWindowFocusEventJS.ON_WINDOW_FOCUS_EVENT_JS_PLUGIN_SCRIPT_GROUP_NAME, 10 | OnWindowFocusEventJS.ON_WINDOW_FOCUS_EVENT_JS_SOURCE, 11 | UserScriptInjectionTime.AT_DOCUMENT_START, 12 | null, 13 | false 14 | ); 15 | 16 | public static final String ON_WINDOW_FOCUS_EVENT_JS_SOURCE = "(function(){" + 17 | " window.addEventListener('focus', function(e) {" + 18 | " window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onWindowFocus');" + 19 | " });" + 20 | "})();"; 21 | } 22 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ios/Classes/InAppWebView/FlutterWebViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FlutterWebViewFactory.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo on 13/11/18. 6 | // 7 | 8 | import Flutter 9 | import Foundation 10 | 11 | public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory { 12 | private var registrar: FlutterPluginRegistrar? 13 | 14 | init(registrar: FlutterPluginRegistrar?) { 15 | super.init() 16 | self.registrar = registrar 17 | } 18 | 19 | public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { 20 | return FlutterStandardMessageCodec.sharedInstance() 21 | } 22 | 23 | public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { 24 | let arguments = args as? NSDictionary 25 | let webviewController = FlutterWebViewController(registrar: registrar!, 26 | withFrame: frame, 27 | viewIdentifier: viewId, 28 | arguments: arguments!) 29 | return webviewController 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/PluginScriptsUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PluginScripts.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class PluginScriptsUtil { 11 | public static let VAR_PLACEHOLDER_VALUE = "$IN_APP_WEBVIEW_PLACEHOLDER_VALUE" 12 | public static let VAR_FUNCTION_ARGUMENT_NAMES = "$IN_APP_WEBVIEW_FUNCTION_ARGUMENT_NAMES" 13 | public static let VAR_FUNCTION_ARGUMENT_VALUES = "$IN_APP_WEBVIEW_FUNCTION_ARGUMENT_VALUES" 14 | public static let VAR_FUNCTION_ARGUMENTS_OBJ = "$IN_APP_WEBVIEW_FUNCTION_ARGUMENTS_OBJ" 15 | public static let VAR_FUNCTION_BODY = "$IN_APP_WEBVIEW_FUNCTION_BODY" 16 | public static let VAR_RESULT_UUID = "$IN_APP_WEBVIEW_RESULT_UUID" 17 | 18 | public static let GET_SELECTED_TEXT_JS_SOURCE = """ 19 | (function(){ 20 | var txt; 21 | if (window.getSelection) { 22 | txt = window.getSelection().toString(); 23 | } else if (window.document.getSelection) { 24 | txt = window.document.getSelection().toString(); 25 | } else if (window.document.selection) { 26 | txt = window.document.selection.createRange().text; 27 | } 28 | return txt; 29 | })(); 30 | """ 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/content_blocker/ContentBlockerTriggerResourceType.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.content_blocker; 2 | 3 | public enum ContentBlockerTriggerResourceType { 4 | DOCUMENT ("document"), 5 | IMAGE ("image"), 6 | STYLE_SHEET ("style-sheet"), 7 | SCRIPT ("script"), 8 | FONT ("font"), 9 | SVG_DOCUMENT ("svg-document"), 10 | MEDIA ("media"), 11 | POPUP ("popup"), 12 | RAW ("raw"); 13 | 14 | private final String value; 15 | 16 | private ContentBlockerTriggerResourceType(String value) { 17 | this.value = value; 18 | } 19 | 20 | public boolean equalsValue(String otherValue) { 21 | return value.equals(otherValue); 22 | } 23 | 24 | public static ContentBlockerTriggerResourceType fromValue(String value) { 25 | for( ContentBlockerTriggerResourceType type : ContentBlockerTriggerResourceType.values()) { 26 | if(value.equals(type.value)) 27 | return type; 28 | } 29 | throw new IllegalArgumentException("No enum constant: " + value); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return this.value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ios/flutter_inappwebview.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutterplugintest.podspec' to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_inappwebview' 7 | s.version = '0.0.1' 8 | s.summary = 'A new Flutter plugin.' 9 | s.description = <<-DESC 10 | A new Flutter plugin. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.resources = 'Storyboards/**/*.storyboard' 18 | s.public_header_files = 'Classes/**/*.h' 19 | s.dependency 'Flutter' 20 | 21 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. 22 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } 23 | s.swift_version = '5.0' 24 | 25 | s.dependency 'OrderedSet', '~>5.0' 26 | 27 | s.default_subspec = 'Core' 28 | 29 | s.subspec 'Core' do |core| 30 | core.platform = :ios, '8.0' 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /ios/Classes/HttpAuthenticationChallenge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HttpAuthenticationChallenge.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | class HttpAuthenticationChallenge: NSObject { 11 | var protectionSpace: URLProtectionSpace! 12 | var previousFailureCount: Int = 0 13 | var failureResponse: URLResponse? 14 | var error: Error? 15 | var proposedCredential: URLCredential? 16 | 17 | public init(fromChallenge: URLAuthenticationChallenge) { 18 | protectionSpace = fromChallenge.protectionSpace 19 | previousFailureCount = fromChallenge.previousFailureCount 20 | failureResponse = fromChallenge.failureResponse 21 | error = fromChallenge.error 22 | proposedCredential = fromChallenge.proposedCredential 23 | } 24 | 25 | public func toMap () -> [String:Any?] { 26 | return [ 27 | "protectionSpace": protectionSpace.toMap(), 28 | "previousFailureCount": previousFailureCount, 29 | "iosFailureResponse": failureResponse?.toMap(), 30 | "iosError": error?.localizedDescription, 31 | "proposedCredential": proposedCredential?.toMap() 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/WebViewFeatureManager.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview; 2 | 3 | import androidx.webkit.WebViewFeature; 4 | 5 | import io.flutter.plugin.common.BinaryMessenger; 6 | import io.flutter.plugin.common.MethodCall; 7 | import io.flutter.plugin.common.MethodChannel; 8 | 9 | public class WebViewFeatureManager implements MethodChannel.MethodCallHandler { 10 | 11 | static final String LOG_TAG = "WebViewFeatureManager"; 12 | 13 | public static MethodChannel channel; 14 | 15 | public WebViewFeatureManager(BinaryMessenger messenger) { 16 | channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_android_webviewfeature"); 17 | channel.setMethodCallHandler(this); 18 | } 19 | 20 | @Override 21 | public void onMethodCall(MethodCall call, MethodChannel.Result result) { 22 | switch (call.method) { 23 | case "isFeatureSupported": 24 | String feature = (String) call.argument("feature"); 25 | result.success(WebViewFeature.isFeatureSupported(feature)); 26 | break; 27 | default: 28 | result.notImplemented(); 29 | } 30 | } 31 | 32 | public void dispose() { 33 | channel.setMethodCallHandler(null); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/OriginalViewPortMetaTagContentJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OriginalViewPortMetaTagContentJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT" 11 | 12 | let ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_SOURCE, 15 | injectionTime: .atDocumentEnd, 16 | forMainFrameOnly: true, 17 | requiredInAllContentWorlds: false, 18 | messageHandlerNames: []) 19 | 20 | let ORIGINAL_VIEWPORT_METATAG_CONTENT_JS_SOURCE = """ 21 | window.\(JAVASCRIPT_BRIDGE_NAME)._originalViewPortMetaTagContent = ""; 22 | (function() { 23 | var metaTagNodes = document.head.getElementsByTagName('meta'); 24 | for (var i = 0; i < metaTagNodes.length; i++) { 25 | var metaTagNode = metaTagNodes[i]; 26 | if (metaTagNode.name === "viewport") { 27 | window.\(JAVASCRIPT_BRIDGE_NAME)._originalViewPortMetaTagContent = metaTagNode.content; 28 | } 29 | } 30 | })(); 31 | """ 32 | -------------------------------------------------------------------------------- /ios/Classes/Types/HitTestResult.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HitTestResult.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum HitTestResultType: Int { 11 | case unknownType = 0 12 | case phoneType = 2 13 | case geoType = 3 14 | case emailType = 4 15 | case imageType = 5 16 | case srcAnchorType = 7 17 | case srcImageAnchorType = 8 18 | case editTextType = 9 19 | } 20 | 21 | public class HitTestResult: NSObject { 22 | var type: HitTestResultType 23 | var extra: String? 24 | 25 | public init(type: HitTestResultType, extra: String?) { 26 | self.type = type 27 | self.extra = extra 28 | } 29 | 30 | public static func fromMap(map: [String:Any?]?) -> HitTestResult? { 31 | guard let map = map else { 32 | return nil 33 | } 34 | let type = HitTestResultType.init(rawValue: map["type"] as? Int ?? HitTestResultType.unknownType.rawValue) ?? HitTestResultType.unknownType 35 | return HitTestResult(type: type, extra: map["extra"] as? String) 36 | } 37 | 38 | public func toMap () -> [String:Any?] { 39 | return [ 40 | "type": type.rawValue, 41 | "extra": extra, 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/EnableViewportScaleJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnableViewportScaleJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let ENABLE_VIEWPORT_SCALE_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ENABLE_VIEWPORT_SCALE_JS_PLUGIN_SCRIPT" 11 | 12 | let ENABLE_VIEWPORT_SCALE_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: ENABLE_VIEWPORT_SCALE_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: ENABLE_VIEWPORT_SCALE_JS_SOURCE, 15 | injectionTime: .atDocumentEnd, 16 | forMainFrameOnly: true, 17 | requiredInAllContentWorlds: false, 18 | messageHandlerNames: []) 19 | 20 | let ENABLE_VIEWPORT_SCALE_JS_SOURCE = """ 21 | (function() { 22 | var meta = document.createElement('meta'); 23 | meta.setAttribute('name', 'viewport'); 24 | meta.setAttribute('content', 'width=device-width'); 25 | document.getElementsByTagName('head')[0].appendChild(meta); 26 | })() 27 | """ 28 | 29 | let NOT_ENABLE_VIEWPORT_SCALE_JS_SOURCE = """ 30 | (function() { 31 | var meta = document.createElement('meta'); 32 | meta.setAttribute('name', 'viewport'); 33 | meta.setAttribute('content', window.\(JAVASCRIPT_BRIDGE_NAME)._originalViewPortMetaTagContent); 34 | document.getElementsByTagName('head')[0].appendChild(meta); 35 | })() 36 | """ 37 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/SupportZoomJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SupportZoomJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let NOT_SUPPORT_ZOOM_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_NOT_SUPPORT_ZOOM_JS_PLUGIN_SCRIPT" 11 | 12 | let NOT_SUPPORT_ZOOM_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: NOT_SUPPORT_ZOOM_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: NOT_SUPPORT_ZOOM_JS_SOURCE, 15 | injectionTime: .atDocumentEnd, 16 | forMainFrameOnly: true, 17 | requiredInAllContentWorlds: false, 18 | messageHandlerNames: []) 19 | 20 | let NOT_SUPPORT_ZOOM_JS_SOURCE = """ 21 | (function() { 22 | var meta = document.createElement('meta'); 23 | meta.setAttribute('name', 'viewport'); 24 | meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'); 25 | document.getElementsByTagName('head')[0].appendChild(meta); 26 | })() 27 | """ 28 | 29 | let SUPPORT_ZOOM_JS_SOURCE = """ 30 | (function() { 31 | var meta = document.createElement('meta'); 32 | meta.setAttribute('name', 'viewport'); 33 | meta.setAttribute('content', window.\(JAVASCRIPT_BRIDGE_NAME)._originalViewPortMetaTagContent); 34 | document.getElementsByTagName('head')[0].appendChild(meta); 35 | })() 36 | """ 37 | 38 | -------------------------------------------------------------------------------- /ios/Classes/Options.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Options.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo on 26/09/18. 6 | // 7 | 8 | import Foundation 9 | 10 | @objcMembers 11 | public class Options: NSObject { 12 | 13 | override init(){ 14 | super.init() 15 | } 16 | 17 | func parse(options: [String: Any?]) -> Options { 18 | for (key, value) in options { 19 | if value != nil, !(value is NSNull), self.responds(to: Selector(key)) { 20 | self.setValue(value, forKey: key) 21 | } 22 | } 23 | return self 24 | } 25 | 26 | func toMap() -> [String: Any?] { 27 | var options: [String: Any?] = [:] 28 | var counts = UInt32(); 29 | let properties = class_copyPropertyList(object_getClass(self), &counts); 30 | for i in 0.. [String: Any?] { 43 | let realOptions: [String: Any?] = toMap() 44 | return realOptions 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/web_storage/web_storage_manager.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/services.dart'; 4 | 5 | import '_static_channel.dart'; 6 | import 'android/web_storage_manager.dart'; 7 | import 'ios/web_storage_manager.dart'; 8 | 9 | ///Class that implements a singleton object (shared instance) which manages the web storage used by WebView instances. 10 | ///On Android, it is implemented using [WebStorage](https://developer.android.com/reference/android/webkit/WebStorage.html). 11 | ///On iOS, it is implemented using [WKWebsiteDataStore.default()](https://developer.apple.com/documentation/webkit/wkwebsitedatastore). 12 | /// 13 | ///**NOTE for iOS**: available from iOS 9.0+. 14 | class WebStorageManager { 15 | static WebStorageManager? _instance; 16 | static const MethodChannel _staticChannel = WEB_STORAGE_STATIC_CHANNEL; 17 | 18 | AndroidWebStorageManager android = AndroidWebStorageManager(); 19 | IOSWebStorageManager ios = IOSWebStorageManager(); 20 | 21 | ///Gets the WebStorage manager shared instance. 22 | static WebStorageManager instance() { 23 | return (_instance != null) ? _instance! : _init(); 24 | } 25 | 26 | static WebStorageManager _init() { 27 | _staticChannel.setMethodCallHandler(_handleMethod); 28 | _instance = new WebStorageManager(); 29 | return _instance!; 30 | } 31 | 32 | static Future _handleMethod(MethodCall call) async {} 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/ContextMenuOptions.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.in_app_webview; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.Options; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class ContextMenuOptions implements Options { 9 | public static final String LOG_TAG = "ContextMenuOptions"; 10 | 11 | public Boolean hideDefaultSystemContextMenuItems = false; 12 | 13 | public ContextMenuOptions parse(Map options) { 14 | for (Map.Entry pair : options.entrySet()) { 15 | String key = pair.getKey(); 16 | Object value = pair.getValue(); 17 | if (value == null) { 18 | continue; 19 | } 20 | 21 | switch (key) { 22 | case "hideDefaultSystemContextMenuItems": 23 | hideDefaultSystemContextMenuItems = (Boolean) value; 24 | break; 25 | } 26 | } 27 | 28 | return this; 29 | } 30 | 31 | public Map toMap() { 32 | Map options = new HashMap<>(); 33 | options.put("hideDefaultSystemContextMenuItems", hideDefaultSystemContextMenuItems); 34 | return options; 35 | } 36 | 37 | @Override 38 | public Map getRealOptions(Object obj) { 39 | Map realOptions = toMap(); 40 | return realOptions; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /android/src/main/res/layout/activity_web_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 21 | 22 | 23 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/chrome_custom_tabs/ServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs; 2 | 3 | import android.content.ComponentName; 4 | import androidx.browser.customtabs.CustomTabsClient; 5 | import androidx.browser.customtabs.CustomTabsServiceConnection; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | /** 10 | * Implementation for the CustomTabsServiceConnection that avoids leaking the 11 | * ServiceConnectionCallback 12 | */ 13 | public class ServiceConnection extends CustomTabsServiceConnection { 14 | // A weak reference to the ServiceConnectionCallback to avoid leaking it. 15 | private WeakReference mConnectionCallback; 16 | 17 | public ServiceConnection(ServiceConnectionCallback connectionCallback) { 18 | mConnectionCallback = new WeakReference<>(connectionCallback); 19 | } 20 | 21 | @Override 22 | public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { 23 | ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); 24 | if (connectionCallback != null) connectionCallback.onServiceConnected(client); 25 | } 26 | 27 | @Override 28 | public void onServiceDisconnected(ComponentName name) { 29 | ServiceConnectionCallback connectionCallback = mConnectionCallback.get(); 30 | if (connectionCallback != null) connectionCallback.onServiceDisconnected(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ios/Classes/Types/WKContentWorld.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKContentWorld.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | import WebKit 10 | 11 | @available(iOS 14.0, *) 12 | extension WKContentWorld { 13 | // Workaround to create stored properties in an extension: 14 | // https://valv0.medium.com/computed-properties-and-extensions-a-pure-swift-approach-64733768112c 15 | 16 | private static var _windowId = [String: Int64?]() 17 | 18 | var windowId: Int64? { 19 | get { 20 | let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) 21 | return WKContentWorld._windowId[tmpAddress] ?? nil 22 | } 23 | set(newValue) { 24 | let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self)) 25 | WKContentWorld._windowId[tmpAddress] = newValue 26 | } 27 | } 28 | 29 | public static func fromMap(map: [String:Any?]?, windowId: Int64?) -> WKContentWorld? { 30 | guard let map = map else { 31 | return nil 32 | } 33 | var name = map["name"] as! String 34 | name = windowId != nil && name != "page" ? 35 | WKUserContentController.WINDOW_ID_PREFIX + String(windowId!) + "-" + name : 36 | name 37 | let contentWorld = Util.getContentWorld(name: name) 38 | contentWorld.windowId = name != "page" ? windowId : nil 39 | return contentWorld 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/URLAuthenticationChallenge.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class URLAuthenticationChallenge { 7 | private URLProtectionSpace protectionSpace; 8 | 9 | public URLAuthenticationChallenge(URLProtectionSpace protectionSpace) { 10 | this.protectionSpace = protectionSpace; 11 | } 12 | 13 | public Map toMap() { 14 | Map challengeMap = new HashMap<>(); 15 | challengeMap.put("protectionSpace", protectionSpace.toMap()); 16 | return challengeMap; 17 | } 18 | 19 | public URLProtectionSpace getProtectionSpace() { 20 | return protectionSpace; 21 | } 22 | 23 | public void setProtectionSpace(URLProtectionSpace protectionSpace) { 24 | this.protectionSpace = protectionSpace; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | if (this == o) return true; 30 | if (o == null || getClass() != o.getClass()) return false; 31 | 32 | URLAuthenticationChallenge challenge = (URLAuthenticationChallenge) o; 33 | 34 | return protectionSpace.equals(challenge.protectionSpace); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return protectionSpace.hashCode(); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "URLAuthenticationChallenge{" + 45 | "protectionSpace=" + protectionSpace + 46 | '}'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/JavaScriptBridgeJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // javaScriptBridgeJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let JAVASCRIPT_BRIDGE_NAME = "flutter_inappwebview" 11 | let JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT" 12 | 13 | let JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT = PluginScript( 14 | groupName: JAVASCRIPT_BRIDGE_JS_PLUGIN_SCRIPT_GROUP_NAME, 15 | source: JAVASCRIPT_BRIDGE_JS_SOURCE, 16 | injectionTime: .atDocumentStart, 17 | forMainFrameOnly: false, 18 | requiredInAllContentWorlds: true, 19 | messageHandlerNames: ["callHandler"]) 20 | 21 | let JAVASCRIPT_BRIDGE_JS_SOURCE = """ 22 | window.\(JAVASCRIPT_BRIDGE_NAME) = {}; 23 | \(WEB_MESSAGE_CHANNELS_VARIABLE_NAME) = {}; 24 | window.\(JAVASCRIPT_BRIDGE_NAME).callHandler = function() { 25 | var _windowId = \(WINDOW_ID_VARIABLE_JS_SOURCE); 26 | var _callHandlerID = setTimeout(function(){}); 27 | window.webkit.messageHandlers['callHandler'].postMessage( {'handlerName': arguments[0], '_callHandlerID': _callHandlerID, 'args': JSON.stringify(Array.prototype.slice.call(arguments, 1)), '_windowId': _windowId} ); 28 | return new Promise(function(resolve, reject) { 29 | window.\(JAVASCRIPT_BRIDGE_NAME)[_callHandlerID] = resolve; 30 | }); 31 | }; 32 | \(WEB_MESSAGE_LISTENER_JS_SOURCE) 33 | """ 34 | 35 | let PLATFORM_READY_JS_SOURCE = "window.dispatchEvent(new Event('flutterInAppWebViewPlatformReady'));"; 36 | -------------------------------------------------------------------------------- /lib/src/platform_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | 3 | class PlatformUtil { 4 | static PlatformUtil? _instance; 5 | static const MethodChannel _channel = const MethodChannel( 6 | 'com.pichillilorenzo/flutter_inappwebview_platformutil'); 7 | 8 | static PlatformUtil instance() { 9 | return (_instance != null) ? _instance! : _init(); 10 | } 11 | 12 | static PlatformUtil _init() { 13 | _channel.setMethodCallHandler(_handleMethod); 14 | _instance = PlatformUtil(); 15 | return _instance!; 16 | } 17 | 18 | static Future _handleMethod(MethodCall call) async {} 19 | 20 | String? _cachedSystemVersion; 21 | Future getSystemVersion() async { 22 | if (_cachedSystemVersion != null) { 23 | return _cachedSystemVersion!; 24 | } 25 | Map args = {}; 26 | _cachedSystemVersion = 27 | await _channel.invokeMethod('getSystemVersion', args); 28 | return _cachedSystemVersion!; 29 | } 30 | 31 | Future formatDate( 32 | {required DateTime date, 33 | required String format, 34 | String locale = "en_US", 35 | String timezone = "UTC"}) async { 36 | Map args = {}; 37 | args.putIfAbsent('date', () => date.millisecondsSinceEpoch); 38 | args.putIfAbsent('format', () => format); 39 | args.putIfAbsent('locale', () => locale); 40 | args.putIfAbsent('timezone', () => timezone); 41 | return await _channel.invokeMethod('formatDate', args); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ios/Classes/InAppWebViewFlutterPlugin.m: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | Unless required by applicable law or agreed to in writing, 11 | software distributed under the License is distributed on an 12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | KIND, either express or implied. See the License for the 14 | specific language governing permissions and limitations 15 | under the License. 16 | */ 17 | 18 | #import "InAppWebViewFlutterPlugin.h" 19 | #if __has_include() 20 | #import 21 | #else 22 | // Support project import fallback if the generated compatibility header 23 | // is not copied when this plugin is created as a library. 24 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 25 | #import "flutter_inappwebview-Swift.h" 26 | #endif 27 | 28 | @implementation InAppWebViewFlutterPlugin : NSObject 29 | + (void)registerWithRegistrar:(NSObject*)registrar { 30 | [SwiftFlutterPlugin registerWithRegistrar:registrar]; 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.pichillilorenzo.flutter_inappwebview' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.6.3' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 30 26 | 27 | defaultConfig { 28 | minSdkVersion 17 29 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 30 | 31 | vectorDrawables.useSupportLibrary = true 32 | consumerProguardFiles 'proguard-rules.pro' 33 | } 34 | lintOptions { 35 | disable 'InvalidPackage' 36 | } 37 | buildTypes { 38 | debug { 39 | minifyEnabled false 40 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 41 | } 42 | release { 43 | minifyEnabled true 44 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 45 | } 46 | } 47 | dependencies { 48 | implementation 'androidx.webkit:webkit:1.4.0' 49 | implementation 'androidx.browser:browser:1.3.0' 50 | implementation 'androidx.appcompat:appcompat:1.3.0-beta01' 51 | implementation 'com.squareup.okhttp3:mockwebserver:3.14.7' 52 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/OnLoadResourceJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // resourceObserverJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT" 11 | let FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE = "window.\(JAVASCRIPT_BRIDGE_NAME)._useOnLoadResource" 12 | 13 | let ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT = PluginScript( 14 | groupName: ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT_GROUP_NAME, 15 | source: ON_LOAD_RESOURCE_JS_SOURCE, 16 | injectionTime: .atDocumentStart, 17 | forMainFrameOnly: false, 18 | requiredInAllContentWorlds: false, 19 | messageHandlerNames: []) 20 | 21 | let ON_LOAD_RESOURCE_JS_SOURCE = """ 22 | \(FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE) = true; 23 | (function() { 24 | var observer = new PerformanceObserver(function(list) { 25 | list.getEntries().forEach(function(entry) { 26 | if (\(FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE) == null || \(FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE) == true) { 27 | var resource = { 28 | "url": entry.name, 29 | "initiatorType": entry.initiatorType, 30 | "startTime": entry.startTime, 31 | "duration": entry.duration 32 | }; 33 | window.\(JAVASCRIPT_BRIDGE_NAME).callHandler("onLoadResource", resource); 34 | } 35 | }); 36 | }); 37 | observer.observe({entryTypes: ['resource']}); 38 | })(); 39 | """ 40 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_on_load_resource_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewOnLoadResourceTest 8 | 9 | 10 | 11 | 12 |
13 |
14 |

InAppWebViewOnLoadResourceTest

15 | flutter logo 16 |

17 | placeholder 100x50 18 |

19 |
20 |
21 | 33 | 34 | -------------------------------------------------------------------------------- /lib/src/pull_to_refresh/pull_to_refresh_options.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import '../util.dart'; 3 | import '../types.dart'; 4 | 5 | class PullToRefreshOptions { 6 | ///Sets whether the pull-to-refresh feature is enabled or not. 7 | bool enabled; 8 | 9 | ///The color of the refresh control. 10 | Color? color; 11 | 12 | ///The background color of the refresh control. 13 | Color? backgroundColor; 14 | 15 | ///The distance to trigger a sync in dips. 16 | /// 17 | ///**NOTE**: Available only on Android. 18 | int? distanceToTriggerSync; 19 | 20 | ///The distance in pixels that the refresh indicator can be pulled beyond its resting position. 21 | /// 22 | ///**NOTE**: Available only on Android. 23 | int? slingshotDistance; 24 | 25 | ///The title text to display in the refresh control. 26 | /// 27 | ///**NOTE**: Available only on iOS. 28 | IOSNSAttributedString? attributedTitle; 29 | 30 | PullToRefreshOptions( 31 | {this.enabled = true, 32 | this.color, 33 | this.backgroundColor, 34 | this.distanceToTriggerSync, 35 | this.slingshotDistance, 36 | this.attributedTitle}); 37 | 38 | Map toMap() { 39 | return { 40 | "enabled": enabled, 41 | "color": color?.toHex(), 42 | "backgroundColor": backgroundColor?.toHex(), 43 | "distanceToTriggerSync": distanceToTriggerSync, 44 | "slingshotDistance": slingshotDistance, 45 | "attributedTitle": attributedTitle?.toMap() ?? {} 46 | }; 47 | } 48 | 49 | Map toJson() { 50 | return this.toMap(); 51 | } 52 | 53 | @override 54 | String toString() { 55 | return toMap().toString(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/ContentWorld.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import java.util.Map; 7 | 8 | public class ContentWorld { 9 | @NonNull 10 | private String name; 11 | 12 | public static final ContentWorld PAGE = new ContentWorld("page"); 13 | public static final ContentWorld DEFAULT_CLIENT = new ContentWorld("defaultClient"); 14 | 15 | private ContentWorld(@NonNull String name) { 16 | this.name = name; 17 | } 18 | 19 | public static ContentWorld world(@NonNull String name) { 20 | return new ContentWorld(name); 21 | } 22 | 23 | @Nullable 24 | public static ContentWorld fromMap(@Nullable Map map) { 25 | if (map == null) { 26 | return null; 27 | } 28 | String name = (String) map.get("name"); 29 | assert name != null; 30 | return new ContentWorld(name); 31 | } 32 | 33 | @NonNull 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(@NonNull String name) { 39 | this.name = name; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (o == null || getClass() != o.getClass()) return false; 46 | 47 | ContentWorld that = (ContentWorld) o; 48 | 49 | return name.equals(that.name); 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | return name.hashCode(); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "ContentWorld{" + 60 | "name='" + name + '\'' + 61 | '}'; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/PluginScript.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | public class PluginScript extends UserScript { 7 | private boolean requiredInAllContentWorlds; 8 | 9 | public PluginScript(@Nullable String groupName, @NonNull String source, @NonNull UserScriptInjectionTime injectionTime, @Nullable ContentWorld contentWorld, boolean requiredInAllContentWorlds) { 10 | super(groupName, source, injectionTime, contentWorld); 11 | this.requiredInAllContentWorlds = requiredInAllContentWorlds; 12 | } 13 | 14 | public boolean isRequiredInAllContentWorlds() { 15 | return requiredInAllContentWorlds; 16 | } 17 | 18 | public void setRequiredInAllContentWorlds(boolean requiredInAllContentWorlds) { 19 | this.requiredInAllContentWorlds = requiredInAllContentWorlds; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) return true; 25 | if (o == null || getClass() != o.getClass()) return false; 26 | if (!super.equals(o)) return false; 27 | 28 | PluginScript that = (PluginScript) o; 29 | 30 | return requiredInAllContentWorlds == that.requiredInAllContentWorlds; 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | int result = super.hashCode(); 36 | result = 31 * result + (requiredInAllContentWorlds ? 1 : 0); 37 | return result; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "PluginScript{" + 43 | "requiredInContentWorld=" + requiredInAllContentWorlds + 44 | "} " + super.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/chrome_custom_tabs/ActionBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.chrome_custom_tabs; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | 8 | import com.pichillilorenzo.flutter_inappwebview.Shared; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import io.flutter.plugin.common.MethodChannel; 14 | 15 | public class ActionBroadcastReceiver extends BroadcastReceiver { 16 | protected static final String LOG_TAG = "ActionBroadcastReceiver"; 17 | public static final String KEY_ACTION_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_ID"; 18 | public static final String KEY_ACTION_VIEW_ID = "com.pichillilorenzo.flutter_inappwebview.ChromeCustomTabs.ACTION_VIEW_ID"; 19 | public static final String KEY_URL_TITLE = "android.intent.extra.SUBJECT"; 20 | 21 | @Override 22 | public void onReceive(Context context, Intent intent) { 23 | String url = intent.getDataString(); 24 | if (url != null) { 25 | Bundle b = intent.getExtras(); 26 | String viewId = b.getString(KEY_ACTION_VIEW_ID); 27 | int id = b.getInt(KEY_ACTION_ID); 28 | String title = b.getString(KEY_URL_TITLE); 29 | 30 | MethodChannel channel = new MethodChannel(Shared.messenger, "com.pichillilorenzo/flutter_chromesafaribrowser_" + viewId); 31 | Map obj = new HashMap<>(); 32 | obj.put("url", url); 33 | obj.put("title", title); 34 | obj.put("id", id); 35 | channel.invokeMethod("onChromeSafariBrowserMenuItemActionPerform", obj); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /flutter_inappwebview_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lib/src/chrome_safari_browser/chrome_safari_browser_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | 3 | import 'android/chrome_custom_tabs_options.dart'; 4 | import 'ios/safari_options.dart'; 5 | 6 | class ChromeSafariBrowserOptions { 7 | Map toMap() { 8 | return {}; 9 | } 10 | 11 | static ChromeSafariBrowserOptions fromMap(Map map) { 12 | return new ChromeSafariBrowserOptions(); 13 | } 14 | 15 | ChromeSafariBrowserOptions copy() { 16 | return ChromeSafariBrowserOptions.fromMap(this.toMap()); 17 | } 18 | 19 | Map toJson() { 20 | return this.toMap(); 21 | } 22 | 23 | @override 24 | String toString() { 25 | return toMap().toString(); 26 | } 27 | } 28 | 29 | ///Class that represents the options that can be used for an [ChromeSafariBrowser] window. 30 | class ChromeSafariBrowserClassOptions { 31 | ///Android-specific options. 32 | AndroidChromeCustomTabsOptions? android; 33 | 34 | ///iOS-specific options. 35 | IOSSafariOptions? ios; 36 | 37 | ChromeSafariBrowserClassOptions({this.android, this.ios}) { 38 | this.android = this.android ?? AndroidChromeCustomTabsOptions(); 39 | this.ios = this.ios ?? IOSSafariOptions(); 40 | } 41 | 42 | Map toMap() { 43 | Map options = {}; 44 | if (defaultTargetPlatform == TargetPlatform.android) 45 | options.addAll(this.android?.toMap() ?? {}); 46 | else if (defaultTargetPlatform == TargetPlatform.iOS) 47 | options.addAll(this.ios?.toMap() ?? {}); 48 | 49 | return options; 50 | } 51 | 52 | Map toJson() { 53 | return this.toMap(); 54 | } 55 | 56 | @override 57 | String toString() { 58 | return toMap().toString(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/types/SslErrorExt.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.types; 2 | 3 | import android.net.http.SslCertificate; 4 | import android.net.http.SslError; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public class SslErrorExt extends SslError { 12 | 13 | private SslErrorExt(int error, SslCertificate certificate, String url) { 14 | super(error, certificate, url); 15 | } 16 | 17 | @Nullable 18 | static public Map toMap(SslError sslError) { 19 | if (sslError == null) { 20 | return null; 21 | } 22 | 23 | int primaryError = sslError.getPrimaryError(); 24 | 25 | String message; 26 | switch (primaryError) { 27 | case SslError.SSL_DATE_INVALID: 28 | message = "The date of the certificate is invalid"; 29 | break; 30 | case SslError.SSL_EXPIRED: 31 | message = "The certificate has expired"; 32 | break; 33 | case SslError.SSL_IDMISMATCH: 34 | message = "Hostname mismatch"; 35 | break; 36 | case SslError.SSL_INVALID: 37 | message = "A generic error occurred"; 38 | break; 39 | case SslError.SSL_NOTYETVALID: 40 | message = "The certificate is not yet valid"; 41 | break; 42 | case SslError.SSL_UNTRUSTED: 43 | message = "The certificate authority is not trusted"; 44 | break; 45 | default: 46 | message = null; 47 | break; 48 | } 49 | 50 | Map urlProtectionSpaceMap = new HashMap<>(); 51 | urlProtectionSpaceMap.put("androidError", primaryError); 52 | urlProtectionSpaceMap.put("message", message); 53 | return urlProtectionSpaceMap; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/content_blocker/ContentBlocker.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.content_blocker; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | public class ContentBlocker { 6 | @NonNull 7 | private ContentBlockerTrigger trigger; 8 | @NonNull 9 | private ContentBlockerAction action; 10 | 11 | public ContentBlocker (@NonNull ContentBlockerTrigger trigger, @NonNull ContentBlockerAction action) { 12 | this.trigger = trigger; 13 | this.action = action; 14 | } 15 | 16 | @NonNull 17 | public ContentBlockerTrigger getTrigger() { 18 | return trigger; 19 | } 20 | 21 | public void setTrigger(@NonNull ContentBlockerTrigger trigger) { 22 | this.trigger = trigger; 23 | } 24 | 25 | @NonNull 26 | public ContentBlockerAction getAction() { 27 | return action; 28 | } 29 | 30 | public void setAction(@NonNull ContentBlockerAction action) { 31 | this.action = action; 32 | } 33 | 34 | @Override 35 | public boolean equals(Object o) { 36 | if (this == o) return true; 37 | if (o == null || getClass() != o.getClass()) return false; 38 | 39 | ContentBlocker that = (ContentBlocker) o; 40 | 41 | if (!trigger.equals(that.trigger)) return false; 42 | return action.equals(that.action); 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | int result = trigger.hashCode(); 48 | result = 31 * result + action.hashCode(); 49 | return result; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "ContentBlocker{" + 55 | "trigger=" + trigger + 56 | ", action=" + action + 57 | '}'; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ios/Classes/Types/SslError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SslError.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 15/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | public class SslError: NSObject { 11 | var errorType: SecTrustResultType? 12 | var message: String? 13 | 14 | public init(errorType: SecTrustResultType?) { 15 | self.errorType = errorType 16 | 17 | var sslErrorMessage: String? = nil 18 | switch errorType { 19 | case .deny: 20 | sslErrorMessage = "Indicates a user-configured deny; do not proceed." 21 | break 22 | case .fatalTrustFailure: 23 | sslErrorMessage = "Indicates a trust failure which cannot be overridden by the user." 24 | break 25 | case .invalid: 26 | sslErrorMessage = "Indicates an invalid setting or result." 27 | break 28 | case .otherError: 29 | sslErrorMessage = "Indicates a failure other than that of trust evaluation." 30 | break 31 | case .recoverableTrustFailure: 32 | sslErrorMessage = "Indicates a trust policy failure which can be overridden by the user." 33 | break 34 | case .unspecified: 35 | sslErrorMessage = "Indicates the evaluation succeeded and the certificate is implicitly trusted, but user intent was not explicitly specified." 36 | break 37 | default: 38 | sslErrorMessage = nil 39 | } 40 | 41 | self.message = sslErrorMessage 42 | } 43 | 44 | public func toMap () -> [String:Any?] { 45 | return [ 46 | "iosError": errorType?.rawValue, 47 | "message": message 48 | ] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /android/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 21 | 22 | 28 | 29 | 35 | 36 | 42 | 43 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ios/Classes/SafariViewController/SafariBrowserOptions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SafariBrowserOptions.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo on 26/09/18. 6 | // 7 | 8 | import Foundation 9 | 10 | @available(iOS 9.0, *) 11 | @objcMembers 12 | public class SafariBrowserOptions: Options { 13 | 14 | var entersReaderIfAvailable = false 15 | var barCollapsingEnabled = false 16 | var dismissButtonStyle = 0 //done 17 | var preferredBarTintColor: String? 18 | var preferredControlTintColor: String? 19 | var presentationStyle = 0 //fullscreen 20 | var transitionStyle = 0 //crossDissolve 21 | 22 | override init(){ 23 | super.init() 24 | } 25 | 26 | override func getRealOptions(obj: SafariViewController?) -> [String: Any?] { 27 | var realOptions: [String: Any?] = toMap() 28 | if let safariViewController = obj { 29 | if #available(iOS 11.0, *) { 30 | realOptions["entersReaderIfAvailable"] = safariViewController.configuration.entersReaderIfAvailable 31 | realOptions["barCollapsingEnabled"] = safariViewController.configuration.barCollapsingEnabled 32 | realOptions["dismissButtonStyle"] = safariViewController.dismissButtonStyle.rawValue 33 | } 34 | if #available(iOS 10.0, *) { 35 | realOptions["preferredBarTintColor"] = safariViewController.preferredBarTintColor?.hexString 36 | realOptions["preferredControlTintColor"] = safariViewController.preferredControlTintColor?.hexString 37 | } 38 | realOptions["presentationStyle"] = safariViewController.modalPresentationStyle.rawValue 39 | realOptions["transitionStyle"] = safariViewController.modalTransitionStyle.rawValue 40 | } 41 | return realOptions 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /lib/src/in_app_browser/android/in_app_browser_options.dart: -------------------------------------------------------------------------------- 1 | import '../../in_app_webview/android/in_app_webview_options.dart'; 2 | 3 | import '../in_app_browser_options.dart'; 4 | import '../in_app_browser.dart'; 5 | 6 | ///This class represents all the Android-only [InAppBrowser] options available. 7 | class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions { 8 | ///Set to `true` if you want the title should be displayed. The default value is `false`. 9 | bool hideTitleBar; 10 | 11 | ///Set the action bar's title. 12 | String? toolbarTopFixedTitle; 13 | 14 | ///Set to `false` to not close the InAppBrowser when the user click on the back button and the WebView cannot go back to the history. The default value is `true`. 15 | bool closeOnCannotGoBack; 16 | 17 | AndroidInAppBrowserOptions( 18 | {this.hideTitleBar = false, 19 | this.toolbarTopFixedTitle, 20 | this.closeOnCannotGoBack = true}); 21 | 22 | @override 23 | Map toMap() { 24 | return { 25 | "hideTitleBar": hideTitleBar, 26 | "toolbarTopFixedTitle": toolbarTopFixedTitle, 27 | "closeOnCannotGoBack": closeOnCannotGoBack, 28 | }; 29 | } 30 | 31 | static AndroidInAppBrowserOptions fromMap(Map map) { 32 | AndroidInAppBrowserOptions options = AndroidInAppBrowserOptions(); 33 | options.hideTitleBar = map["hideTitleBar"]; 34 | options.toolbarTopFixedTitle = map["toolbarTopFixedTitle"]; 35 | options.closeOnCannotGoBack = map["closeOnCannotGoBack"]; 36 | return options; 37 | } 38 | 39 | @override 40 | Map toJson() { 41 | return this.toMap(); 42 | } 43 | 44 | @override 45 | String toString() { 46 | return toMap().toString(); 47 | } 48 | 49 | @override 50 | AndroidInAppBrowserOptions copy() { 51 | return AndroidInAppBrowserOptions.fromMap(this.toMap()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client1-csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIE5TCCAs0CAQAwgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEPMA0GA1UE 3 | BwwGQm9zdG9uMRMwEQYDVQQKDApFeGFtcGxlIENvMRAwDgYDVQQLDAd0ZWNob3Bz 4 | MRAwDgYDVQQDDAdjbGllbnQxMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxl 5 | LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPWhU8of86y3Lols 6 | 0cU40+cbCcAhOEsdDiouVKX9cpnYoP5IIsTOiQHjAcMYekTMNXxLcGGa8FWO1bDW 7 | 6WjvzNi0s2xqYMThP5h7m5XK4PR6NjLnE8I0kyfYjvx4vN/AXNWJXgNDJ+dkm3O0 8 | ceXzMzswuLqrhEv7UpkJm37znimOBtP7JSFmoz5mT+/s3Aojzop1Le1VSPVANIbu 9 | PgdsIdoNMR8oJrKai0PourJKuvOV5qiNm0123+lq9x4R+zoY2AIB34o9RJfcuUZs 10 | +IqDt+SyL3MHwuP8OMmYyU6yerfWLZ2Ywsg01uDGQMaHfPH1S8d8Hiq4Vwfi9RWE 11 | kvifb4eQDBzVN3x1Hn/1cEghaLneDiRRwRiFZFs/WKvafxMOY4M30gpuSStHzIt/ 12 | wE+N8vC8KNW2TyyPAkCq6L8BjOlJ7EX0eilbSroMz/SeTO8+t4+N9vJ5/4e4dSSQ 13 | zo3Sdw3K8sdK7zoBToWGW26yCSEvnSBjNyWvNKLWsHM1wKxbN85sDYdeyn7pvjHe 14 | K1g0eQF/WGbEyHCTws3tDCo/wfpbZNtkW1w8zlBAmpbZdNZDs4769pZ/tb9wctUk 15 | TasbXlXedMmmw2eOZ3d/hj0REFpbl/34ClQSTnlVQJKv/7CwqzJWDUd5uWzaHPtr 16 | hzUOJDKoDBEvfL+yAEJNMM8maGcpAgMBAAGgGTAXBgkqhkiG9w0BCQcxCgwIcGFz 17 | c3dvcmQwDQYJKoZIhvcNAQELBQADggIBAJal3mvhA+zM72cXUY1IYIVVS9QuSzqC 18 | GkUT8O174bD1acc7KEm0uGS628sR0mFCKArfH9YTjUOX1+jORPBhVCXeg9xp/PPg 19 | 9mjTHyKPJu2vnq6GaS1WXqEOQJkppV5fBqciIDRQOu1goR2I21qjEUnVnb82jRXv 20 | DpZ9YkgyMdf2Li9taj2snJSfXBwjhNH78lXmRz/HYTQSHyih4dfpdLpeIK8g+0uR 21 | 8bkJzga5hc2dDEyQQ+xQ+jVBdiAT6R/zV/V7ghJDHeJ4HuLuIVh9zIbAz0jPvG7u 22 | pumHW3Lbr5ISwxmhOp1RczxWeRktP+8aVP0Uk5D/5EGxs8F+lbU4lh0RTm0ae6W1 23 | UMExBn056C46ypvp7H0vLiijyhyVjo8kfz8HA392TlCOYxaJB2EaUoJA3yu5lb8w 24 | nSQrlGCtA8ba9ceMFhjzIxE6I7qf93GZlK9m7HcqEdFNkm/byo2gQ5/SMSpOiL4C 25 | IuK9p/bTBwpJL88ibAOq/V8IZBPRcyWnJcL7KzQKQGOVpl2egrf4Iqn5/FZwXpmL 26 | zIVDHSRP1NwTqkAX1JxoHn7bjDDkhtB6V4qy2/uqscTBPA2m/Z+rJofusjsHblrN 27 | nrQnzcwsiVU/gPgNUPTZi2wmxAkc7zFvnR3F1NCjLEr3G5rmF+M9aT3/5w0U3zOW 28 | JN5HS6NqtcFI 29 | -----END CERTIFICATE REQUEST----- 30 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client2-csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIE5TCCAs0CAQAwgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEPMA0GA1UE 3 | BwwGQm9zdG9uMRMwEQYDVQQKDApFeGFtcGxlIENvMRAwDgYDVQQLDAd0ZWNob3Bz 4 | MRAwDgYDVQQDDAdjbGllbnQyMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxl 5 | LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO2ARFzN+hQgmnEj 6 | OXHcOVjCPH6g/UNXwUNjtEUBg+EDTGliOC8If6ObFjW4tfIjwgGdhKt++92LRxDe 7 | BauM8al7QK8yZhw7I7waqm0C4tIw4MdAlcRxZ0gEG7l5i9jU55yPpUcxZ1VE0VuH 8 | ADgAosZtjltsBv03tq2Cf11jTEcaly4ze/8vDaAyl+M4u9FrflPnYoPmCiMBTz1j 9 | 1mdVtGsg2nGk+MA5RX9bMwWZq5bT9j2RG7PDMoc139SieQx4/5aVqIH628K7X0xE 10 | /YydLh7vARM15Fn8tJy4yj/fgkU+3AWN8nWoOwceLNEB/yorBs1tjjSWEt3NIP7d 11 | kcyHYmZ7XyUMSzlfdSVY+OoM1z63MoSCTwZJzZ5fI4ca+NtoxYny4unyM1q7QKwA 12 | CisynJvGD5aI5bRgpjujlpw5IEuGqBZRjkLB0heOrPUlGEKkvaH2r9w/rGo8w4Is 13 | ebz3OHBeVpB2AqbifMa+3cwZ9/IpRWUKUdnoqye5ySx1RHWmz3fjwerTDPzHWxJ8 14 | YH8HORvuwUm+j/hXFvB3D8S754X+OEA8bgu/7dfIE1C330WDvVAP6EngCZKAI8W2 15 | 6u2SYXKPviqXciap5B4K4QHyUsiVruBIvymwTnz1+sharbRBOll7ZZKbBK1UNaCn 16 | XO0Vt7NM5EbNEhjBlrArPGxIT0bFAgMBAAGgGTAXBgkqhkiG9w0BCQcxCgwIcGFz 17 | c3dvcmQwDQYJKoZIhvcNAQELBQADggIBAGDn6DOovGaSpbe2PGetJrvQht2T6de8 18 | cbnGCusQSjdqssUtjnKqV8hE4K8RsbrwWK6Gz6VR3s+ayVvm6JMNSf129UJEoOO5 19 | f1KKWOB1ZuvIaxxdpWWSEyT2NWsnxPb4PVgRv+SjAkFlpfQdPqG+BDyd7PbjffTi 20 | Yut3+AejTU6pkD9A82SyVUYP0hcSdnusclxeecBpvuBC1r1+ZmWMhgVHN9C13Bin 21 | KPanEcwSP9GER9E5z38+mM6outSBTQ48+sSrfYXJgJe1kJ5U5swkTv0msoysOG7y 22 | A9mn+upeL2+BI/9IkLswJygfDOUEQDdiafT9PAhJczKm6uLzNFSi5d+W+2VGMBoM 23 | K3Ur5tg1Hom/yvkPBLteldNPySswJ0QTHtuhyyKsIx7pzy68YJtCIdaFCoOPMiEy 24 | ME95l2Tp/G8g9GQbRNnRtBaNAirrzRTEpOxfIX0JZk/vouz7vDvnXLBZOwzaAWM3 25 | 0/f5uQD4YrY5qQ2Xl+Wq5ZySYi6afxhh0w9X72W3AKOgXuVKN0VUFOW0ani+tKuw 26 | PLPwMRx12vgPUhNGfosTzTSOnTyI5yBqG4BtSHnR5k1DYLwTjdlGCr8jcA3u8sLP 27 | sJX0u9+/JSaemlb2E6/T4pHwIot+l52DBnbe66ekwVoDf47smefapiYE7Gb7KRxA 28 | 0j8l/ryckQZk 29 | -----END CERTIFICATE REQUEST----- 30 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/server-csr.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIE5zCCAs8CAQAwgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEPMA0GA1UE 3 | BwwGQm9zdG9uMRMwEQYDVQQKDApFeGFtcGxlIENvMRAwDgYDVQQLDAd0ZWNob3Bz 4 | MRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWNlcnRzQGV4YW1w 5 | bGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6+4m+blS6NcS 6 | ZcftDArQhd7ekeeZzfiedonAXybjJ+GkqtigKW2hUtHldWRswx56braUAJYUsj2I 7 | Xh9y9/vWCGUGF9ZsiPTI28bZgbfwvyGaO0K4mLPGdvOvtXgbbw3uC6hU+sbiFF88 8 | BgZdwnsjoP7wPHqyzJ8PQ7BM7jdflLFn1uULS+9fe/7gPRSXxvS26WC1IYK8gVqQ 9 | JBXH2tO3ZSh8LygePjKUWQF4xsN8mttRYlahdhNIMb1ZgBnG4rFq8JOc5fUbrYIz 10 | s+LLMRm8zn3GIZgp4BiK900RJGxDXtVnx6ce4fdj+4OsL8NW3JzBNB66unsQ1gkz 11 | WZbAbaXN7HeUpnktuGfA+TdWrzMd8XXaMDHXj9Uh8NtjToBJ5hHkStSkHRxBnlyo 12 | MvWXGubn+EfUC5nVBGnG/Yfb9caKlpgIHh164ScGKlFlV4W8VpoA1W0BwE/R/E/I 13 | lo5wiX5DP2uxh8bC7J1UK7guDnGDZASWsqNxtCBuCmEx9L6ePlnQbuc/AA+QLdyS 14 | z4wb0IGefS+et0BOJFj2/u28/A5N21swarTCxPm0rczXZfRhooM8/X6Z3Pw6E5ze 15 | D1S/49V8qLwqwcwkJhnIJoqSj/cWNGVXRY2Tqu5536NvK3e5BvOPeULf0IKYDhUs 16 | LxwgpQ07gntS7UHBSejmmmjs92IiQiECAwEAAaAZMBcGCSqGSIb3DQEJBzEKDAhw 17 | YXNzd29yZDANBgkqhkiG9w0BAQsFAAOCAgEANu/fvD8Bq5ISbTQX42hTyHfe3caL 18 | G7BDJdwTaBhzHcJFL0xbHDpDKvEhWgjzfP253x4EEx2tLHOCntj7CNBCYBq/oyWs 19 | 60ef7RH6/Lg+zo3wPO8iSV4hvjJrddwb7nlmZOFK0rGnpdTEQyvr+885/pyeP6a9 20 | iMtZZL3/QIz2RN79nuOhh3J5G9SsrQhxw7Dk7zXIaSXdC/+f+lJnJZav6Q+9w8WD 21 | a5sgx8jMTjL9TjA9jCh02P04MM4MD4YjwY9K13I9qWs3bhR4n43omlDFbMMQ/Es6 22 | t+8hN1yxsokSi0iZhCCCeUZxfbCyN5z23DmHYcbkTwhKbqW4QJnJ3Xw9eYmPNC9Q 23 | FxxZmj6A7N2+V07jXQjyhdNWCeTLoPEyoAAwtNi8SASG6olvgIygX0rhRwU8HvZt 24 | u9gKh5vTg4Si4rNZ6DatHY/qlJUcaaqLpG2nI8bctkefH65if8k1iKhfPTxawtHk 25 | ytrsyU+oQ2d6maBcEqfY6ui2j5O3U4yUVM+8RjppM/qrzqg9c3++tRfRMg0ZArQu 26 | lXjA5KnQuNAeSDJmDpfOVoHAXM/uPte8pP9ZVO7MLBqhjkdXfF0fJxV6qX0/l0nt 27 | gurXEbIv19qz91QkzI2MeM59c+IYTkxYZmkbFqf4rB2OJT5yUcsJ88R7zipc8zFa 28 | CR1YgTG5mrlPW2c= 29 | -----END CERTIFICATE REQUEST----- 30 | -------------------------------------------------------------------------------- /ios/Classes/PluginScriptsJS/ConsoleLogJS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConsoleLogJS.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 16/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | let CONSOLE_LOG_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_CONSOLE_LOG_JS_PLUGIN_SCRIPT" 11 | 12 | let CONSOLE_LOG_JS_PLUGIN_SCRIPT = PluginScript( 13 | groupName: CONSOLE_LOG_JS_PLUGIN_SCRIPT_GROUP_NAME, 14 | source: CONSOLE_LOG_JS_SOURCE, 15 | injectionTime: .atDocumentStart, 16 | forMainFrameOnly: false, 17 | requiredInAllContentWorlds: true, 18 | messageHandlerNames: ["consoleLog", "consoleDebug", "consoleError", "consoleInfo", "consoleWarn"]) 19 | 20 | // the message needs to be concatenated with '' in order to have the same behavior like on Android 21 | let CONSOLE_LOG_JS_SOURCE = """ 22 | (function(console) { 23 | 24 | var oldLogs = { 25 | 'consoleLog': console.log, 26 | 'consoleDebug': console.debug, 27 | 'consoleError': console.error, 28 | 'consoleInfo': console.info, 29 | 'consoleWarn': console.warn 30 | }; 31 | 32 | for (var k in oldLogs) { 33 | (function(oldLog) { 34 | console[oldLog.replace('console', '').toLowerCase()] = function() { 35 | var message = ''; 36 | for (var i in arguments) { 37 | if (message == '') { 38 | message += arguments[i]; 39 | } 40 | else { 41 | message += ' ' + arguments[i]; 42 | } 43 | } 44 | 45 | var _windowId = \(WINDOW_ID_VARIABLE_JS_SOURCE); 46 | window.webkit.messageHandlers[oldLog].postMessage({'message': message, '_windowId': _windowId}); 47 | oldLogs[oldLog].apply(null, arguments); 48 | } 49 | })(k); 50 | } 51 | })(window.console); 52 | """ 53 | -------------------------------------------------------------------------------- /example/test_assets/in_app_webview_initial_file_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | InAppWebViewInitialFileTest 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |

InAppWebViewInitialFileTest

18 | 23 |
24 |
25 | 26 |
27 |

InAppWebViewInitialFileTest

28 | flutter logo 29 |

30 | placeholder 100x50 31 |

32 | flutter_inappwebview 33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /lib/t_rex_runner/t-rex.css: -------------------------------------------------------------------------------- 1 | #main-frame-error { 2 | box-sizing: border-box; 3 | padding: 0 10%; 4 | font-size: 1em; 5 | line-height: 1.55; 6 | margin: 0 auto; 7 | max-width: 600px; 8 | padding-top: 100px; 9 | width: 100%; 10 | } 11 | #main-content { 12 | font-size: 1em; 13 | line-height: 1.55; 14 | margin: 0 auto; 15 | max-width: 600px; 16 | padding-top: 100px; 17 | width: 100%; 18 | } 19 | #t-rex-icon { 20 | font-size: 1em; 21 | line-height: 1.55; 22 | background-repeat: no-repeat; 23 | background-size: 100%; 24 | height: 72px; 25 | margin: 0 0 40px; 26 | width: 72px; 27 | display: inline-block; 28 | content: -webkit-image-set( 29 | url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAGxJREFUeF7tyMEJwkAQRuFf5ipMKxYQiJ3Z2nSwrWwBA0+DQZcdxEOueaePp9+dQZFB7GpUcURSVU66yVNFj6LFICatThZB6r/ko/pbRpUgilY0Cbw5sNmb9txGXUKyuH7eV25x39DtJXUNPQGJtWFV+BT/QAAAAABJRU5ErkJggg==) 30 | 1x, 31 | url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQBAMAAAAVaP+LAAAAGFBMVEUAAABTU1NNTU1TU1NPT09SUlJSUlJTU1O8B7DEAAAAB3RSTlMAoArVKvVgBuEdKgAAAJ1JREFUeF7t1TEOwyAMQNG0Q6/UE+RMXD9d/tC6womIFSL9P+MnAYOXeTIzMzMzMzMzaz8J9Ri6HoITmuHXhISE8nEh9yxDh55aCEUoTGbbQwjqHwIkRAEiIaG0+0AA9VBMaE89Rogeoww936MQrWdBr4GN/z0IAdQ6nQ/FIpRXDwHcA+JIJcQowQAlFUA0MfQpXLlVQfkzR4igS6ENjknm/wiaGhsAAAAASUVORK5CYII=) 32 | 2x 33 | ); 34 | position: relative; 35 | visibility: hidden; 36 | } 37 | #offline-resources { 38 | display: none; 39 | } 40 | #main-frame-error > .runner-container { 41 | height: 150px; 42 | max-width: 600px; 43 | overflow: hidden; 44 | position: absolute; 45 | top: 35px; 46 | width: 44px; 47 | } 48 | #main-frame-error > .controller { 49 | background: rgba(247, 247, 247, 0.1); 50 | height: 100vh; 51 | left: 0; 52 | position: absolute; 53 | top: 0; 54 | width: 100vw; 55 | z-index: 9; 56 | } 57 | #main-frame-error .hidden { 58 | display: none; 59 | } 60 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/RequestPermissionHandler.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview; 2 | 3 | import android.app.Activity; 4 | import android.content.pm.PackageManager; 5 | import android.util.Log; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.core.app.ActivityCompat; 9 | import androidx.core.content.ContextCompat; 10 | 11 | import java.util.Arrays; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | public abstract class RequestPermissionHandler implements ActivityCompat.OnRequestPermissionsResultCallback { 17 | 18 | private static Map> actionDictionary = new HashMap<>(); 19 | 20 | public static void checkAndRun(Activity activity, String permission, int requestCode, Runnable runnable) { 21 | 22 | int permissionCheck = ContextCompat.checkSelfPermission(activity.getApplicationContext(), permission); 23 | 24 | if (permissionCheck != PackageManager.PERMISSION_GRANTED) { 25 | if (actionDictionary.containsKey(requestCode)) 26 | actionDictionary.get(requestCode).add(runnable); 27 | else 28 | actionDictionary.put(requestCode, Arrays.asList(runnable)); 29 | ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode); 30 | } 31 | else 32 | runnable.run(); 33 | } 34 | 35 | @Override 36 | public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { 37 | if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { 38 | List callbacks = actionDictionary.get(requestCode); 39 | for (Runnable runnable : callbacks) { 40 | runnable.run(); 41 | callbacks.remove(runnable); 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/x509_certificate/x509_public_key.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'asn1_decoder.dart'; 4 | import 'asn1_der_encoder.dart'; 5 | import 'asn1_object.dart'; 6 | import 'oid.dart'; 7 | 8 | class X509PublicKey { 9 | ASN1Object? pkBlock; 10 | 11 | X509PublicKey({this.pkBlock}); 12 | 13 | String? get algOid => pkBlock?.subAtIndex(0)?.subAtIndex(0)?.value; 14 | 15 | String? get algName => OID.fromValue(algOid)?.name(); 16 | 17 | String? get algParams => pkBlock?.subAtIndex(0)?.subAtIndex(1)?.value; 18 | 19 | Uint8List? get derEncodedKey { 20 | var value = pkBlock?.encoded; 21 | if (value != null) { 22 | return ASN1DEREncoder.encodeSequence(content: value); 23 | } 24 | return null; 25 | } 26 | 27 | Uint8List? get encoded { 28 | var oid = OID.fromValue(algOid); 29 | var keyData = pkBlock?.subAtIndex(1)?.value ?? null; 30 | 31 | if (oid != null && algOid != null && keyData != null) { 32 | if (oid == OID.ecPublicKey) { 33 | return Uint8List.fromList(keyData); 34 | } else if (oid == OID.rsaEncryption) { 35 | List? publicKeyAsn1Objects; 36 | try { 37 | publicKeyAsn1Objects = 38 | ASN1DERDecoder.decode(data: keyData.toList(growable: true)); 39 | } catch (e) {} 40 | 41 | if (publicKeyAsn1Objects != null && publicKeyAsn1Objects.length > 0) { 42 | var publicKeyModulus = 43 | publicKeyAsn1Objects.first.subAtIndex(0)?.value; 44 | if (publicKeyModulus != null) { 45 | return Uint8List.fromList(publicKeyModulus); 46 | } 47 | } 48 | } 49 | } 50 | return null; 51 | } 52 | 53 | Map toMap() { 54 | return { 55 | "algOid": algOid, 56 | "algName": algName, 57 | "algParams": algParams, 58 | "encoded": encoded, 59 | }; 60 | } 61 | 62 | Map toJson() { 63 | return toMap(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/ConsoleLogJS.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; 4 | import com.pichillilorenzo.flutter_inappwebview.types.UserScriptInjectionTime; 5 | 6 | public class ConsoleLogJS { 7 | public static final String CONSOLE_LOG_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_CONSOLE_LOG_JS_PLUGIN_SCRIPT"; 8 | public static final PluginScript CONSOLE_LOG_JS_PLUGIN_SCRIPT = new PluginScript( 9 | ConsoleLogJS.CONSOLE_LOG_JS_PLUGIN_SCRIPT_GROUP_NAME, 10 | ConsoleLogJS.CONSOLE_LOG_JS_SOURCE, 11 | UserScriptInjectionTime.AT_DOCUMENT_START, 12 | null, 13 | true 14 | ); 15 | 16 | public static final String CONSOLE_LOG_JS_SOURCE = "(function(console) {" + 17 | " var oldLogs = {" + 18 | " 'log': console.log," + 19 | " 'debug': console.debug," + 20 | " 'error': console.error," + 21 | " 'info': console.info," + 22 | " 'warn': console.warn" + 23 | " };" + 24 | " for (var k in oldLogs) {" + 25 | " (function(oldLog) {" + 26 | " console[oldLog] = function() {" + 27 | " var message = '';" + 28 | " for (var i in arguments) {" + 29 | " if (message == '') {" + 30 | " message += arguments[i];" + 31 | " }" + 32 | " else {" + 33 | " message += ' ' + arguments[i];" + 34 | " }" + 35 | " }" + 36 | " oldLogs[oldLog].call(console, message);" + 37 | " }" + 38 | " })(k);" + 39 | " }" + 40 | "})(window.console);"; 41 | } 42 | -------------------------------------------------------------------------------- /example/assets/page-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Flutter InAppBrowser 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

Flutter InAppBrowser

17 | 22 |
23 |
24 | 25 |
26 |

Page 1

27 |

Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.

28 |

29 | Learn more 30 |

31 |
32 | 33 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /example/assets/page-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Flutter InAppBrowser 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

Flutter InAppBrowser

17 | 22 |
23 |
24 | 25 |
26 |

Page 2

27 |

Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.

28 |

29 | Learn more 30 |

31 |
32 | 33 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /example/test_assets/page-1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Flutter InAppBrowser 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

Flutter InAppBrowser

17 | 22 |
23 |
24 | 25 |
26 |

Page 1

27 |

Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.

28 |

29 | Learn more 30 |

31 |
32 | 33 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /example/test_assets/page-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Flutter InAppBrowser 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

Flutter InAppBrowser

17 | 22 |
23 |
24 | 25 |
26 |

Page 2

27 |

Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.

28 |

29 | Learn more 30 |

31 |
32 | 33 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /example/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Globals 3 | */ 4 | 5 | /* Links */ 6 | a, 7 | a:focus, 8 | a:hover { 9 | color: #fff; 10 | } 11 | 12 | /* Custom default button */ 13 | .btn-secondary, 14 | .btn-secondary:hover, 15 | .btn-secondary:focus { 16 | color: #333; 17 | text-shadow: none; /* Prevent inheritance from `body` */ 18 | background-color: #fff; 19 | border: .05rem solid #fff; 20 | } 21 | 22 | 23 | /* 24 | * Base structure 25 | */ 26 | 27 | html, 28 | body { 29 | height: 100%; 30 | background-color: #333; 31 | } 32 | 33 | body { 34 | display: -ms-flexbox; 35 | display: flex; 36 | color: #fff; 37 | text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5); 38 | box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5); 39 | } 40 | 41 | .cover-container { 42 | max-width: 42em; 43 | } 44 | 45 | 46 | /* 47 | * Header 48 | */ 49 | .masthead { 50 | margin-bottom: 2rem; 51 | } 52 | 53 | .masthead-brand { 54 | margin-bottom: 0; 55 | } 56 | 57 | .nav-masthead .nav-link { 58 | padding: .25rem 0; 59 | font-weight: 700; 60 | color: rgba(255, 255, 255, .5); 61 | background-color: transparent; 62 | border-bottom: .25rem solid transparent; 63 | } 64 | 65 | .nav-masthead .nav-link:hover, 66 | .nav-masthead .nav-link:focus { 67 | border-bottom-color: rgba(255, 255, 255, .25); 68 | } 69 | 70 | .nav-masthead .nav-link + .nav-link { 71 | margin-left: 1rem; 72 | } 73 | 74 | .nav-masthead .active { 75 | color: #fff; 76 | border-bottom-color: #fff; 77 | } 78 | 79 | @media (min-width: 48em) { 80 | .masthead-brand { 81 | float: left; 82 | } 83 | .nav-masthead { 84 | float: right; 85 | } 86 | } 87 | 88 | 89 | /* 90 | * Cover 91 | */ 92 | .cover { 93 | padding: 0 1.5rem; 94 | } 95 | .cover .btn-lg { 96 | padding: .75rem 1.25rem; 97 | font-weight: 700; 98 | } 99 | 100 | 101 | /* 102 | * Footer 103 | */ 104 | .mastfoot { 105 | color: rgba(255, 255, 255, .5); 106 | } -------------------------------------------------------------------------------- /example/test_assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Globals 3 | */ 4 | 5 | /* Links */ 6 | a, 7 | a:focus, 8 | a:hover { 9 | color: #fff; 10 | } 11 | 12 | /* Custom default button */ 13 | .btn-secondary, 14 | .btn-secondary:hover, 15 | .btn-secondary:focus { 16 | color: #333; 17 | text-shadow: none; /* Prevent inheritance from `body` */ 18 | background-color: #fff; 19 | border: .05rem solid #fff; 20 | } 21 | 22 | 23 | /* 24 | * Base structure 25 | */ 26 | 27 | html, 28 | body { 29 | height: 100%; 30 | background-color: #333; 31 | } 32 | 33 | body { 34 | display: -ms-flexbox; 35 | display: flex; 36 | color: #fff; 37 | text-shadow: 0 .05rem .1rem rgba(0, 0, 0, .5); 38 | box-shadow: inset 0 0 5rem rgba(0, 0, 0, .5); 39 | } 40 | 41 | .cover-container { 42 | max-width: 42em; 43 | } 44 | 45 | 46 | /* 47 | * Header 48 | */ 49 | .masthead { 50 | margin-bottom: 2rem; 51 | } 52 | 53 | .masthead-brand { 54 | margin-bottom: 0; 55 | } 56 | 57 | .nav-masthead .nav-link { 58 | padding: .25rem 0; 59 | font-weight: 700; 60 | color: rgba(255, 255, 255, .5); 61 | background-color: transparent; 62 | border-bottom: .25rem solid transparent; 63 | } 64 | 65 | .nav-masthead .nav-link:hover, 66 | .nav-masthead .nav-link:focus { 67 | border-bottom-color: rgba(255, 255, 255, .25); 68 | } 69 | 70 | .nav-masthead .nav-link + .nav-link { 71 | margin-left: 1rem; 72 | } 73 | 74 | .nav-masthead .active { 75 | color: #fff; 76 | border-bottom-color: #fff; 77 | } 78 | 79 | @media (min-width: 48em) { 80 | .masthead-brand { 81 | float: left; 82 | } 83 | .nav-masthead { 84 | float: right; 85 | } 86 | } 87 | 88 | 89 | /* 90 | * Cover 91 | */ 92 | .cover { 93 | padding: 0 1.5rem; 94 | } 95 | .cover .btn-lg { 96 | padding: .75rem 1.25rem; 97 | font-weight: 700; 98 | } 99 | 100 | 101 | /* 102 | * Footer 103 | */ 104 | .mastfoot { 105 | color: rgba(255, 255, 255, .5); 106 | } -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ios/Classes/Types/UIColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 19/02/21. 6 | // 7 | 8 | import Foundation 9 | 10 | extension UIColor { 11 | convenience init(hexString: String) { 12 | let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) 13 | var int = UInt64() 14 | Scanner(string: hex).scanHexInt64(&int) 15 | let a, r, g, b: UInt64 16 | switch hex.count { 17 | case 3: // RGB (12-bit) 18 | (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) 19 | case 6: // RGB (24-bit) 20 | (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) 21 | case 8: // ARGB (32-bit) 22 | (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) 23 | default: 24 | (a, r, g, b) = (255, 0, 0, 0) 25 | } 26 | self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255) 27 | } 28 | 29 | var hexString: String? { 30 | var red: CGFloat = 0 31 | var green: CGFloat = 0 32 | var blue: CGFloat = 0 33 | var alpha: CGFloat = 0 34 | 35 | let multiplier = CGFloat(255.999999) 36 | 37 | guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else { 38 | return nil 39 | } 40 | 41 | if alpha == 1.0 { 42 | return String( 43 | format: "#%02lX%02lX%02lX", 44 | Int(red * multiplier), 45 | Int(green * multiplier), 46 | Int(blue * multiplier) 47 | ) 48 | } 49 | else { 50 | return String( 51 | format: "#%02lX%02lX%02lX%02lX", 52 | Int(red * multiplier), 53 | Int(green * multiplier), 54 | Int(blue * multiplier), 55 | Int(alpha * multiplier) 56 | ) 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/x509_certificate/key_usage.dart: -------------------------------------------------------------------------------- 1 | class KeyUsage { 2 | final int _value; 3 | 4 | const KeyUsage._internal(this._value); 5 | 6 | static final Set values = [ 7 | KeyUsage.digitalSignature, 8 | KeyUsage.nonRepudiation, 9 | KeyUsage.keyEncipherment, 10 | KeyUsage.dataEncipherment, 11 | KeyUsage.keyAgreement, 12 | KeyUsage.keyCertSign, 13 | KeyUsage.cRLSign, 14 | KeyUsage.encipherOnly, 15 | KeyUsage.decipherOnly, 16 | ].toSet(); 17 | 18 | static KeyUsage? fromIndex(int? value) { 19 | if (value != null) { 20 | try { 21 | return KeyUsage.values 22 | .firstWhere((element) => element.toValue() == value); 23 | } catch (e) { 24 | return null; 25 | } 26 | } 27 | return null; 28 | } 29 | 30 | int toValue() => _value; 31 | 32 | String name() => _KeyUsageMapName.containsKey(this._value) 33 | ? _KeyUsageMapName[this._value]! 34 | : ""; 35 | 36 | @override 37 | String toString() => "($_value, ${name()})"; 38 | 39 | static const digitalSignature = const KeyUsage._internal(0); 40 | static const nonRepudiation = const KeyUsage._internal(1); 41 | static const keyEncipherment = const KeyUsage._internal(2); 42 | static const dataEncipherment = const KeyUsage._internal(3); 43 | static const keyAgreement = const KeyUsage._internal(4); 44 | static const keyCertSign = const KeyUsage._internal(5); 45 | static const cRLSign = const KeyUsage._internal(6); 46 | static const encipherOnly = const KeyUsage._internal(7); 47 | static const decipherOnly = const KeyUsage._internal(8); 48 | 49 | bool operator ==(value) => value == _value; 50 | 51 | @override 52 | int get hashCode => _value.hashCode; 53 | 54 | static const Map _KeyUsageMapName = { 55 | 0: "digitalSignature", 56 | 1: "nonRepudiation", 57 | 2: "keyEncipherment", 58 | 3: "dataEncipherment", 59 | 4: "keyAgreement", 60 | 5: "keyCertSign", 61 | 6: "cRLSign", 62 | 7: "encipherOnly", 63 | 8: "decipherOnly", 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /android/src/main/java/com/pichillilorenzo/flutter_inappwebview/plugin_scripts_js/OnLoadResourceJS.java: -------------------------------------------------------------------------------- 1 | package com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js; 2 | 3 | import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; 4 | import com.pichillilorenzo.flutter_inappwebview.types.UserScriptInjectionTime; 5 | 6 | public class OnLoadResourceJS { 7 | public static final String ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT_GROUP_NAME = "IN_APP_WEBVIEW_ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT"; 8 | public static final String FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE = JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + "._useOnLoadResource"; 9 | public static final PluginScript ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT = new PluginScript( 10 | OnLoadResourceJS.ON_LOAD_RESOURCE_JS_PLUGIN_SCRIPT_GROUP_NAME, 11 | OnLoadResourceJS.ON_LOAD_RESOURCE_JS_SOURCE, 12 | UserScriptInjectionTime.AT_DOCUMENT_START, 13 | null, 14 | false 15 | ); 16 | 17 | public static final String ON_LOAD_RESOURCE_JS_SOURCE = "window." + FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE + " = true;" + 18 | "(function() {" + 19 | " var observer = new PerformanceObserver(function(list) {" + 20 | " list.getEntries().forEach(function(entry) {" + 21 | " if (" + FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE + " == null || " + FLAG_VARIABLE_FOR_ON_LOAD_RESOURCE_JS_SOURCE + " == true) {" + 22 | " var resource = {" + 23 | " 'url': entry.name," + 24 | " 'initiatorType': entry.initiatorType," + 25 | " 'startTime': entry.startTime," + 26 | " 'duration': entry.duration" + 27 | " };" + 28 | " window." + JavaScriptBridgeJS.JAVASCRIPT_BRIDGE_NAME + ".callHandler('onLoadResource', resource);" + 29 | " }" + 30 | " });" + 31 | " });" + 32 | " observer.observe({entryTypes: ['resource']});" + 33 | "})();"; 34 | } 35 | -------------------------------------------------------------------------------- /ios/Classes/CustomeSchemeHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomeSchemeHandler.swift 3 | // flutter_inappwebview 4 | // 5 | // Created by Lorenzo Pichilli on 25/10/2019. 6 | // 7 | 8 | import Flutter 9 | import Foundation 10 | import WebKit 11 | 12 | @available(iOS 11.0, *) 13 | class CustomeSchemeHandler : NSObject, WKURLSchemeHandler { 14 | var schemeHandlers: [Int:WKURLSchemeTask] = [:] 15 | 16 | func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { 17 | schemeHandlers[urlSchemeTask.hash] = urlSchemeTask 18 | let inAppWebView = webView as! InAppWebView 19 | if let url = urlSchemeTask.request.url { 20 | inAppWebView.onLoadResourceCustomScheme(url: url.absoluteString, result: {(result) -> Void in 21 | if result is FlutterError { 22 | print((result as! FlutterError).message ?? "") 23 | } 24 | else if (result as? NSObject) == FlutterMethodNotImplemented {} 25 | else { 26 | let json: [String: Any] 27 | if let r = result { 28 | json = r as! [String: Any] 29 | let urlResponse = URLResponse(url: url, mimeType: (json["contentType"] as! String), expectedContentLength: -1, textEncodingName: (json["contentEncoding"] as! String)) 30 | let data = json["data"] as! FlutterStandardTypedData 31 | if (self.schemeHandlers[urlSchemeTask.hash] != nil) { 32 | urlSchemeTask.didReceive(urlResponse) 33 | urlSchemeTask.didReceive(data.data) 34 | urlSchemeTask.didFinish() 35 | self.schemeHandlers.removeValue(forKey: urlSchemeTask.hash) 36 | } 37 | } 38 | } 39 | }) 40 | } 41 | } 42 | 43 | func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) { 44 | schemeHandlers.removeValue(forKey: urlSchemeTask.hash) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/ca-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | lrzYwz1UU//M2zwtN5nHjE+bnks= 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client1-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFijCCA3KgAwIBAgIJALg+W/pyOZ5qMA0GCSqGSIb3DQEBBQUAMIGBMQswCQYD 3 | VQQGEwJVUzELMAkGA1UECAwCTUExDzANBgNVBAcMBkJvc3RvbjETMBEGA1UECgwK 4 | RXhhbXBsZSBDbzEQMA4GA1UECwwHdGVjaG9wczELMAkGA1UEAwwCY2ExIDAeBgkq 5 | hkiG9w0BCQEWEWNlcnRzQGV4YW1wbGUuY29tMB4XDTE5MTAzMDIzMzcwOVoXDTIy 6 | MDcyNTIzMzcwOVowgYYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEPMA0GA1UE 7 | BwwGQm9zdG9uMRMwEQYDVQQKDApFeGFtcGxlIENvMRAwDgYDVQQLDAd0ZWNob3Bz 8 | MRAwDgYDVQQDDAdjbGllbnQxMSAwHgYJKoZIhvcNAQkBFhFjZXJ0c0BleGFtcGxl 9 | LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPWhU8of86y3Lols 10 | 0cU40+cbCcAhOEsdDiouVKX9cpnYoP5IIsTOiQHjAcMYekTMNXxLcGGa8FWO1bDW 11 | 6WjvzNi0s2xqYMThP5h7m5XK4PR6NjLnE8I0kyfYjvx4vN/AXNWJXgNDJ+dkm3O0 12 | ceXzMzswuLqrhEv7UpkJm37znimOBtP7JSFmoz5mT+/s3Aojzop1Le1VSPVANIbu 13 | PgdsIdoNMR8oJrKai0PourJKuvOV5qiNm0123+lq9x4R+zoY2AIB34o9RJfcuUZs 14 | +IqDt+SyL3MHwuP8OMmYyU6yerfWLZ2Ywsg01uDGQMaHfPH1S8d8Hiq4Vwfi9RWE 15 | kvifb4eQDBzVN3x1Hn/1cEghaLneDiRRwRiFZFs/WKvafxMOY4M30gpuSStHzIt/ 16 | wE+N8vC8KNW2TyyPAkCq6L8BjOlJ7EX0eilbSroMz/SeTO8+t4+N9vJ5/4e4dSSQ 17 | zo3Sdw3K8sdK7zoBToWGW26yCSEvnSBjNyWvNKLWsHM1wKxbN85sDYdeyn7pvjHe 18 | K1g0eQF/WGbEyHCTws3tDCo/wfpbZNtkW1w8zlBAmpbZdNZDs4769pZ/tb9wctUk 19 | TasbXlXedMmmw2eOZ3d/hj0REFpbl/34ClQSTnlVQJKv/7CwqzJWDUd5uWzaHPtr 20 | hzUOJDKoDBEvfL+yAEJNMM8maGcpAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGhm 21 | 496UQQKPqXUXl52lPUhchjCxecfukVrLf2GR3H8r9W6s46pu60MGZBip7TQowXGN 22 | v4uZKABxOkI7VoRUhndsO8KiR39DlmE/SocSrEyfe6cblMaMr7c6oTojcYiXHLbi 23 | Wy52O5TX1iqMBNyrvPAfDjOubkaUF0iuyh1Vzn5OuHvWfmC5uOONHIUCukeyg+hg 24 | wxYH5vYduhYiqmdAPNHrqrGRqOfbwG6KTMaqH6xihupJsgcxwVpzbdWWxPU37tZE 25 | sI1RVS26Z6XuA2j1uQ4BzRUbGlXqvESYV9jSkKYvNfMqVDL+g2h9xumlPtTIiP6b 26 | GZIN4zel7WhaOdftnz5w4AdaPt3sYXxTda95973TNe072tgR/lJsvobW1szSo0k8 27 | m2AbWeepzeKftYanCydRz5MnlOX8mf3HaL0QqreQwxaiF40mOUVcMPJfY2pK25qU 28 | pVK9E3oA1ufc7+8Hnx4KsE9DO/1VyCrpBq0LwUKjmhYTLChsuH0Gpj+/pqioWNKB 29 | c6Mt+APzGG8jqWrwMlsixK2U6G22zASpFBWuFhQIShkL819zgpRB67XPQUgKkbQT 30 | 4wF9cR4xwHvz8NsFHyXGFkI3U9yGGOVXWMOQ+ZhLyWGkwg096mVro/AtGveAs0sr 31 | QWfJbuZM/gWlaojLGqtatDEc+tfRZ7g+nxU+PhQq 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/client2-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /nodejs_server_test_auth_basic_and_ssl/server-crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFjDCCA3SgAwIBAgIJALg+W/pyOZ5pMA0GCSqGSIb3DQEBBQUAMIGBMQswCQYD 3 | VQQGEwJVUzELMAkGA1UECAwCTUExDzANBgNVBAcMBkJvc3RvbjETMBEGA1UECgwK 4 | RXhhbXBsZSBDbzEQMA4GA1UECwwHdGVjaG9wczELMAkGA1UEAwwCY2ExIDAeBgkq 5 | hkiG9w0BCQEWEWNlcnRzQGV4YW1wbGUuY29tMB4XDTE5MTAzMDIzMzQxOVoXDTIy 6 | MDcyNTIzMzQxOVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJNQTEPMA0GA1UE 7 | BwwGQm9zdG9uMRMwEQYDVQQKDApFeGFtcGxlIENvMRAwDgYDVQQLDAd0ZWNob3Bz 8 | MRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWNlcnRzQGV4YW1w 9 | bGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6+4m+blS6NcS 10 | ZcftDArQhd7ekeeZzfiedonAXybjJ+GkqtigKW2hUtHldWRswx56braUAJYUsj2I 11 | Xh9y9/vWCGUGF9ZsiPTI28bZgbfwvyGaO0K4mLPGdvOvtXgbbw3uC6hU+sbiFF88 12 | BgZdwnsjoP7wPHqyzJ8PQ7BM7jdflLFn1uULS+9fe/7gPRSXxvS26WC1IYK8gVqQ 13 | JBXH2tO3ZSh8LygePjKUWQF4xsN8mttRYlahdhNIMb1ZgBnG4rFq8JOc5fUbrYIz 14 | s+LLMRm8zn3GIZgp4BiK900RJGxDXtVnx6ce4fdj+4OsL8NW3JzBNB66unsQ1gkz 15 | WZbAbaXN7HeUpnktuGfA+TdWrzMd8XXaMDHXj9Uh8NtjToBJ5hHkStSkHRxBnlyo 16 | MvWXGubn+EfUC5nVBGnG/Yfb9caKlpgIHh164ScGKlFlV4W8VpoA1W0BwE/R/E/I 17 | lo5wiX5DP2uxh8bC7J1UK7guDnGDZASWsqNxtCBuCmEx9L6ePlnQbuc/AA+QLdyS 18 | z4wb0IGefS+et0BOJFj2/u28/A5N21swarTCxPm0rczXZfRhooM8/X6Z3Pw6E5ze 19 | D1S/49V8qLwqwcwkJhnIJoqSj/cWNGVXRY2Tqu5536NvK3e5BvOPeULf0IKYDhUs 20 | LxwgpQ07gntS7UHBSejmmmjs92IiQiECAwEAATANBgkqhkiG9w0BAQUFAAOCAgEA 21 | JxbqWQynzigBoaR7DP6AtXzYC2RcVBQuwyBSy348ruiIeQy3Niwt5cuhFA/LVyZP 22 | QI6KQTj2Qd0elAkeSp55nG/ZWmcszAF8aWrFRNUc0U85eUcZSyKP1eRblFgf2sMg 23 | HrJY0w0Ust43jk+tWNCftSHL6+uxaKc0z18vFmpHIBtpecCHYaA2mEUTTS19mzSu 24 | K816jEqDvwxUWRbC8aTLOKDS3w1OLBtwVQ8bBvKCbJv7I3AmWtGkmDdetBwEe9u4 25 | lpC/7Rmm57/UG5P8Vy7lVGyOnxQaTE1FxxNWwq02Iy4gc1UAovYYBtgsg+XfnpL6 26 | TUo/9gtjl5K6OMxS/8JJjCi7U8RqiZICGTvjUvl0ahUtjs9CHtruWPbQ7tpA+IWQ 27 | k9U708R3TAILHtq1Po1cWTtezYqUokLVwQlvwWJOezuPWnz0v5VKuLX64Ot0HAjI 28 | rB/VggCRRFbxseM22q3xYKGpERhvAnSjD6bAYP11MlCj/4FBflHDWgDjTvmwRW05 29 | GW7rsTT+4omu/yQGRXSqFpaD1pYuoi1j0Lhtk/LCwQLE9bxPBUf0t8Ut+q5s0s0X 30 | yXB1git1Aq09HZ1yJRfL//g/PWOu5lFhc8Xe4grrB3peRl2yHNiBNXQ1m1DmxCpL 31 | oeM+rfdX4oDVWH5oFmyFGAUOdsZ1JgvaasFq2JRKryA= 32 | -----END CERTIFICATE----- 33 | --------------------------------------------------------------------------------