fix #679, updated X509Certificate classes, removed androidOnRequestFocus event

because it is never called
This commit is contained in:
Lorenzo Pichilli 2021-02-12 17:14:13 +01:00
parent e9f5cabd2b
commit de9d081af2
37 changed files with 862 additions and 1030 deletions

View File

@ -1,772 +0,0 @@
<component name="libraryTable">
<library name="Dart Packages" type="DartPackagesLibraryType">
<properties>
<option name="packageNameToDirsMap">
<entry key="_fe_analyzer_shared">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-12.0.0/lib" />
</list>
</value>
</entry>
<entry key="analyzer">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-0.40.6/lib" />
</list>
</value>
</entry>
<entry key="archive">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/archive-3.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/archive-2.0.13/lib" />
</list>
</value>
</entry>
<entry key="args">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/args-1.6.0/lib" />
</list>
</value>
</entry>
<entry key="async">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="boolean_selector">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="characters">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0-nullsafety.5/lib" />
</list>
</value>
</entry>
<entry key="charcode">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="cli_util">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/cli_util-0.2.0/lib" />
</list>
</value>
</entry>
<entry key="clock">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="collection">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0-nullsafety.5/lib" />
</list>
</value>
</entry>
<entry key="convert">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/convert-2.1.1/lib" />
</list>
</value>
</entry>
<entry key="coverage">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/coverage-0.14.2/lib" />
</list>
</value>
</entry>
<entry key="crypto">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/crypto-2.1.5/lib" />
</list>
</value>
</entry>
<entry key="cupertino_icons">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/cupertino_icons-1.0.2/lib" />
</list>
</value>
</entry>
<entry key="device_info">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/lib" />
</list>
</value>
</entry>
<entry key="device_info_platform_interface">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/device_info_platform_interface-2.0.0-nullsafety.2/lib" />
</list>
</value>
</entry>
<entry key="fake_async">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="ffi">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/ffi-0.1.3/lib" />
</list>
</value>
</entry>
<entry key="file">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/file-6.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/file-6.0.0-nullsafety.4/lib" />
</list>
</value>
</entry>
<entry key="flutter">
<value>
<list>
<option value="$USER_HOME$/flutter/packages/flutter/lib" />
</list>
</value>
</entry>
<entry key="flutter_downloader">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/lib" />
</list>
</value>
</entry>
<entry key="flutter_driver">
<value>
<list>
<option value="$USER_HOME$/flutter/packages/flutter_driver/lib" />
</list>
</value>
</entry>
<entry key="flutter_test">
<value>
<list>
<option value="$USER_HOME$/flutter/packages/flutter_test/lib" />
</list>
</value>
</entry>
<entry key="fuchsia_remote_debug_protocol">
<value>
<list>
<option value="$USER_HOME$/flutter/packages/fuchsia_remote_debug_protocol/lib" />
</list>
</value>
</entry>
<entry key="glob">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/glob-1.2.0/lib" />
</list>
</value>
</entry>
<entry key="http_multi_server">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/http_multi_server-2.2.0/lib" />
</list>
</value>
</entry>
<entry key="http_parser">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4/lib" />
</list>
</value>
</entry>
<entry key="integration_test">
<value>
<list>
<option value="$USER_HOME$/flutter/packages/integration_test/lib" />
</list>
</value>
</entry>
<entry key="intl">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/intl-0.17.0/lib" />
</list>
</value>
</entry>
<entry key="io">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/io-0.3.4/lib" />
</list>
</value>
</entry>
<entry key="js">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="json_rpc_2">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/json_rpc_2-2.2.2/lib" />
</list>
</value>
</entry>
<entry key="logging">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/logging-0.11.4/lib" />
</list>
</value>
</entry>
<entry key="matcher">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="meta">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0-nullsafety.6/lib" />
</list>
</value>
</entry>
<entry key="mime">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mime-1.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mime-0.9.7/lib" />
</list>
</value>
</entry>
<entry key="mockito">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mockito-4.1.1/lib" />
</list>
</value>
</entry>
<entry key="node_interop">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_interop-1.2.1/lib" />
</list>
</value>
</entry>
<entry key="node_io">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_io-1.1.1/lib" />
</list>
</value>
</entry>
<entry key="node_preamble">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_preamble-1.4.13/lib" />
</list>
</value>
</entry>
<entry key="package_config">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/package_config-1.9.3/lib" />
</list>
</value>
</entry>
<entry key="path">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="path_provider">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/lib" />
</list>
</value>
</entry>
<entry key="path_provider_linux">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/lib" />
</list>
</value>
</entry>
<entry key="path_provider_macos">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/lib" />
</list>
</value>
</entry>
<entry key="path_provider_platform_interface">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_platform_interface-1.0.4/lib" />
</list>
</value>
</entry>
<entry key="path_provider_windows">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/lib" />
</list>
</value>
</entry>
<entry key="pedantic">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="permission_handler">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/lib" />
</list>
</value>
</entry>
<entry key="permission_handler_platform_interface">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler_platform_interface-2.0.2/lib" />
</list>
</value>
</entry>
<entry key="platform">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0-nullsafety.4/lib" />
</list>
</value>
</entry>
<entry key="plugin_platform_interface">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/plugin_platform_interface-1.1.0-nullsafety.1/lib" />
</list>
</value>
</entry>
<entry key="pool">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pool-1.5.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="process">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/process-4.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/process-4.0.0-nullsafety.4/lib" />
</list>
</value>
</entry>
<entry key="pub_semver">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.4.4/lib" />
</list>
</value>
</entry>
<entry key="shelf">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf-0.7.5/lib" />
</list>
</value>
</entry>
<entry key="shelf_packages_handler">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_packages_handler-2.0.0/lib" />
</list>
</value>
</entry>
<entry key="shelf_static">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_static-0.2.9+1/lib" />
</list>
</value>
</entry>
<entry key="shelf_web_socket">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.3/lib" />
</list>
</value>
</entry>
<entry key="sky_engine">
<value>
<list>
<option value="$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib" />
</list>
</value>
</entry>
<entry key="source_map_stack_trace">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-2.1.0-nullsafety.4/lib" />
</list>
</value>
</entry>
<entry key="source_maps">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.10-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="source_span">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0-nullsafety.4/lib" />
</list>
</value>
</entry>
<entry key="stack_trace">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0-nullsafety.6/lib" />
</list>
</value>
</entry>
<entry key="stream_channel">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="string_scanner">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="sync_http">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.2.0/lib" />
</list>
</value>
</entry>
<entry key="term_glyph">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="test">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test-1.16.0-nullsafety.9/lib" />
</list>
</value>
</entry>
<entry key="test_api">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19-nullsafety.6/lib" />
</list>
</value>
</entry>
<entry key="test_core">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_core-0.3.12-nullsafety.9/lib" />
</list>
</value>
</entry>
<entry key="typed_data">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0-nullsafety.5/lib" />
</list>
</value>
</entry>
<entry key="url_launcher">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/lib" />
</list>
</value>
</entry>
<entry key="url_launcher_linux">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/lib" />
</list>
</value>
</entry>
<entry key="url_launcher_macos">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/lib" />
</list>
</value>
</entry>
<entry key="url_launcher_platform_interface">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_platform_interface-2.0.0-nullsafety.1/lib" />
</list>
</value>
</entry>
<entry key="url_launcher_windows">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/lib" />
</list>
</value>
</entry>
<entry key="uuid">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/uuid-3.0.0-nullsafety.0/lib" />
</list>
</value>
</entry>
<entry key="vector_math">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0-nullsafety.5/lib" />
</list>
</value>
</entry>
<entry key="vm_service">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-6.0.1-nullsafety.1/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-5.5.0/lib" />
</list>
</value>
</entry>
<entry key="watcher">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/watcher-0.9.7+15/lib" />
</list>
</value>
</entry>
<entry key="web_socket_channel">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.2.0/lib" />
</list>
</value>
</entry>
<entry key="webdriver">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webdriver-3.0.0/lib" />
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webdriver-2.1.2/lib" />
</list>
</value>
</entry>
<entry key="webkit_inspection_protocol">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webkit_inspection_protocol-0.7.4/lib" />
</list>
</value>
</entry>
<entry key="win32">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/win32-1.7.4+1/lib" />
</list>
</value>
</entry>
<entry key="xdg_directories">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/xdg_directories-0.1.2/lib" />
</list>
</value>
</entry>
<entry key="yaml">
<value>
<list>
<option value="$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/yaml-2.2.1/lib" />
</list>
</value>
</entry>
</option>
</properties>
<CLASSES>
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-12.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-0.40.6/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/archive-2.0.13/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/archive-3.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/args-1.6.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0-nullsafety.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/characters-1.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/charcode-1.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/cli_util-0.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/clock-1.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0-nullsafety.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/collection-1.15.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/convert-2.1.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/coverage-0.14.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/crypto-2.1.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/crypto-3.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/cupertino_icons-1.0.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/device_info_platform_interface-2.0.0-nullsafety.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/fake_async-1.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/ffi-0.1.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/file-6.0.0-nullsafety.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/file-6.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/glob-1.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/http_multi_server-2.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/http_parser-3.1.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/intl-0.17.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/io-0.3.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/json_rpc_2-2.2.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/logging-0.11.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.10/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0-nullsafety.6/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/meta-1.3.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mime-0.9.7/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mime-1.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/mockito-4.1.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_interop-1.2.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_io-1.1.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/node_preamble-1.4.13/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/package_config-1.9.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path-1.8.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_platform_interface-1.0.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pedantic-1.10.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler_platform_interface-2.0.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0-nullsafety.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/platform-3.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/plugin_platform_interface-1.1.0-nullsafety.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pool-1.5.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/process-4.0.0-nullsafety.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/process-4.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.4.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf-0.7.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_packages_handler-2.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_static-0.2.9+1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-2.1.0-nullsafety.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.10-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0-nullsafety.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0-nullsafety.6/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/sync_http-0.3.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test-1.16.0-nullsafety.9/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19-nullsafety.6/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/test_core-0.3.12-nullsafety.9/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0-nullsafety.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/typed_data-1.3.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_platform_interface-2.0.0-nullsafety.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/uuid-3.0.0-nullsafety.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0-nullsafety.5/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vector_math-2.1.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-5.5.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/vm_service-6.0.1-nullsafety.1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/watcher-0.9.7+15/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.2.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webdriver-2.1.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webdriver-3.0.0/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/webkit_inspection_protocol-0.7.4/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/win32-1.7.4+1/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/xdg_directories-0.1.2/lib" />
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/yaml-2.2.1/lib" />
<root url="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib" />
<root url="file://$USER_HOME$/flutter/packages/flutter/lib" />
<root url="file://$USER_HOME$/flutter/packages/flutter_driver/lib" />
<root url="file://$USER_HOME$/flutter/packages/flutter_test/lib" />
<root url="file://$USER_HOME$/flutter/packages/fuchsia_remote_debug_protocol/lib" />
<root url="file://$USER_HOME$/flutter/packages/integration_test/lib" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,6 +1,9 @@
<component name="libraryTable">
<library name="Flutter Plugins">
<CLASSES />
<CLASSES>
<root url="file://$USER_HOME$/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2" />
<root url="file://$PROJECT_DIR$" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>

View File

@ -9,13 +9,14 @@
- Added `initialUserScripts` WebView option
- Added `addUserScript`, `addUserScripts`, `removeUserScript`, `removeUserScripts`, `removeAllUserScripts`, `callAsyncJavaScript` WebView methods
- Added `contentWorld` argument to `evaluateJavascript` WebView method
- Added `isDirectionalLockEnabled`, `mediaType`, `pageZoom`, `limitsNavigationsToAppBoundDomains`, `useOnNavigationResponse`, `applePayAPIEnabled` iOS-specific WebView options
- Added `isDirectionalLockEnabled`, `mediaType`, `pageZoom`, `limitsNavigationsToAppBoundDomains`, `useOnNavigationResponse`, `applePayAPIEnabled`, `allowingReadAccessTo` iOS-specific WebView options
- Added `handlesURLScheme`, `createPdf`, `createWebArchiveData` iOS-specific WebView methods
- Added `iosOnNavigationResponse` and `iosShouldAllowDeprecatedTLS` iOS-specific WebView events
- Added `iosAnimated` optional argument to `zoomBy` WebView method
- Added `screenshotConfiguration` optional argument to `takeScreenshot` WebView method
- Added `scriptHtmlTagAttributes` optional argument to `injectJavascriptFileFromUrl` WebView method
- Added `cssLinkHtmlTagAttributes` optional argument to `injectCSSFileFromUrl` WebView method
- Added `iosAllowingReadAccessTo` iOS-specific optional argument to `loadUrl` WebView method
- Added new iOS-specific attributes to `ShouldOverrideUrlLoadingRequest` and `CreateWindowRequest` classes
- Updated integration tests
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
@ -52,6 +53,8 @@
- Changed `zoomBy` WebView method signature
- Moved `saveWebArchive` WebView method from Android-specific to cross-platform
- Renamed `HttpAuthChallenge` to `URLAuthenticationChallenge`
- Deleted `androidOnRequestFocus` event because it is never called
- Updated `basicConstraints`, `subjectKeyIdentifier`, `authorityKeyIdentifier`, `certificatePolicies`, `cRLDistributionPoints`, `authorityInfoAccess` attributes type of `X509Certificate`
## 4.0.0+4

View File

@ -437,7 +437,7 @@ Screenshots:
* `isLoading`: Check if the WebView instance is in a loading state.
* `loadData({required String data, String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", String androidHistoryUrl = "about:blank"})`: Loads the given data into this WebView.
* `loadFile({required String assetFilePath, Map<String, String> headers = const {}})`: Loads the given `assetFilePath` with optional headers specified as a map from name to value.
* `loadUrl({required String url, Map<String, String> headers = const {}})`: Loads the given url with optional headers specified as a map from name to value.
* `loadUrl({required String url, Map<String, String> headers = const {}, String? iosAllowingReadAccessTo})`: Loads the given url with optional headers specified as a map from name to value.
* `pauseTimers`: On Android, it pauses all layout, parsing, and JavaScript timers for all WebViews. This is a global requests, not restricted to just this WebView. This can be useful if the application has been paused. On iOS, it is restricted to just this WebView.
* `postUrl({required String url, required Uint8List postData})`: Loads the given url with postData using `POST` method into this WebView.
* `printCurrentPage`: Prints the current page.
@ -636,6 +636,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
##### `InAppWebView` iOS-specific options
* `accessibilityIgnoresInvertColors`: A Boolean value indicating whether the view ignores an accessibility request to invert its colors. The default value is `false`.
* `allowingReadAccessTo`: Used in combination with `WebView.initialUrl` (with `file://` scheme), it represents the URL from which to read the web content. This URL must be a file-based URL (with `file://` scheme).
* `allowsAirPlayForMediaPlayback`: Set to `true` to allow AirPlay. The default value is `true`.
* `allowsBackForwardNavigationGestures`: Set to `true` to allow the horizontal swipe gestures trigger back-forward list navigations. The default value is `true`.
* `allowsInlineMediaPlayback`: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls.
@ -713,7 +714,6 @@ Event names that starts with `android` or `ios` are events platform-specific.
* `androidOnRenderProcessUnresponsive`: Event called when the renderer currently associated with the WebView becomes unresponsive as a result of a long running blocking task such as the execution of JavaScript (available only on Android).
* `androidOnFormResubmission`: As the host application if the browser should resend data as the requested page was a result of a POST. The default is to not resend the data (available only on Android).
* `androidOnScaleChanged`: Event fired when the scale applied to the WebView has changed (available only on Android).
* `androidOnRequestFocus`: Event fired when there is a request to display and focus for this WebView (available only on Android).
* `androidOnReceivedIcon`: Event fired when there is new favicon for the current page (available only on Android).
* `androidOnReceivedTouchIconUrl`: Event fired when there is an url for an apple-touch-icon (available only on Android).
* `androidOnJsBeforeUnload`: Event fired when the client should display a dialog to confirm navigation away from the current page. This is the result of the `onbeforeunload` javascript event (available only on Android).

View File

@ -666,21 +666,21 @@ final public class InAppWebView extends InputAwareWebView {
"})();";
static final String onWindowBlurEventJS = "(function(){" +
" window.addEventListener('blur', function(e) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('onWindowBlur');" +
" });" +
"})();";
" window.addEventListener('blur', function(e) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('onWindowBlur');" +
" });" +
"})();";
static final String callAsyncJavaScriptWrapperJS = "(function(obj) {" +
" (async function($FUNCTION_ARGUMENT_NAMES) {" +
" $FUNCTION_BODY" +
" })($FUNCTION_ARGUMENT_VALUES).then(function(value) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('callAsyncJavaScript', {'value': value, 'error': null, 'resultUuid': '$RESULT_UUID'});" +
" }).catch(function(error) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('callAsyncJavaScript', {'value': null, 'error': error, 'resultUuid': '$RESULT_UUID'});" +
" });" +
" return null;" +
"})($FUNCTION_ARGUMENTS_OBJ);";
" (async function($FUNCTION_ARGUMENT_NAMES) {" +
" $FUNCTION_BODY" +
" })($FUNCTION_ARGUMENT_VALUES).then(function(value) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('callAsyncJavaScript', {'value': value, 'error': null, 'resultUuid': '$RESULT_UUID'});" +
" }).catch(function(error) {" +
" window." + JavaScriptBridgeInterface.name + ".callHandler('callAsyncJavaScript', {'value': null, 'error': error, 'resultUuid': '$RESULT_UUID'});" +
" });" +
" return null;" +
"})($FUNCTION_ARGUMENTS_OBJ);";
public InAppWebView(Context context) {
super(context);
@ -1864,8 +1864,8 @@ final public class InAppWebView extends InputAwareWebView {
final ActionMode.Callback callback
) {
// fix Android 10 clipboard not working properly https://github.com/pichillilorenzo/flutter_inappwebview/issues/678
if (!options.useHybridComposition) {
onWindowFocusChanged(isFocused());
if (!options.useHybridComposition && containerView != null) {
onWindowFocusChanged(containerView.isFocused());
}
boolean hasBeenRemovedAndRebuilt = false;

View File

@ -569,7 +569,7 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
@Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, final Message resultMsg) {
@ -635,14 +635,6 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
super.onCloseWindow(window);
}
@Override
public void onRequestFocus(WebView view) {
final Map<String, Object> obj = new HashMap<>();
channel.invokeMethod("onRequestFocus", obj);
super.onCloseWindow(view);
}
@Override
public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
Map<String, Object> obj = new HashMap<>();

View File

@ -23,6 +23,7 @@ public class WebViewFeatureManager implements MethodChannel.MethodCallHandler {
case "isFeatureSupported":
String feature = (String) call.argument("feature");
result.success(WebViewFeature.isFeatureSupported(feature));
break;
default:
result.notImplemented();
}

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-11 17:35:59.644389","version":"1.26.0-18.0.pre.257"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-12 16:50:12.665299","version":"1.27.0-2.0.pre.43"}

View File

@ -10,6 +10,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path_provider/path_provider.dart';
import '.env.dart';
@ -119,6 +120,127 @@ void main() {
expect(content.contains('flutter_test_header'), isTrue);
});
group("iOS loadFileURL", () {
late Directory appSupportDir;
late File fileHtml;
late File fileJs;
setUpAll(() async {
appSupportDir = (await getApplicationSupportDirectory())!;
final Directory htmlFolder = Directory('${appSupportDir.path}/html/');
if(!await htmlFolder.exists()){
await htmlFolder.create(recursive: true);
}
final Directory jsFolder = Directory('${appSupportDir.path}/js/');
if(!await jsFolder.exists()){
await jsFolder.create(recursive: true);
}
var html = """
<!DOCTYPE html><html>
<head>
<title>file scheme</title>
</head>
<body>
<script src="../js/main.js"></script>
</body>
</html>
""";
fileHtml = File(htmlFolder.path + "index.html");
fileHtml.writeAsStringSync(html);
var js = """
console.log('message');
""";
fileJs = File(jsFolder.path + "main.js");
fileJs.writeAsStringSync(js);
});
testWidgets('initialUrl with file:// scheme and allowingReadAccessTo', (WidgetTester tester) async {
final Completer<ConsoleMessage?> consoleMessageShouldNotComplete = Completer<ConsoleMessage?>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrl: Uri.encodeFull('file://${fileHtml.path}'),
onConsoleMessage: (controller, consoleMessage) {
consoleMessageShouldNotComplete.complete(consoleMessage);
},
),
),
);
var result = await consoleMessageShouldNotComplete.future
.timeout(const Duration(seconds: 2), onTimeout: () => null);
expect(result, null);
final Completer<ConsoleMessage> consoleMessageCompleter = Completer<ConsoleMessage>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrl: Uri.encodeFull('file://${fileHtml.path}'),
initialOptions: InAppWebViewGroupOptions(
ios: IOSInAppWebViewOptions(
allowingReadAccessTo: Uri.encodeFull('file://${appSupportDir.path}/')
)
),
onConsoleMessage: (controller, consoleMessage) {
consoleMessageCompleter.complete(consoleMessage);
},
),
),
);
final ConsoleMessage consoleMessage = await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message');
});
testWidgets('loadUrl with file:// scheme and iosAllowingReadAccessTo argument', (WidgetTester tester) async {
final Completer<ConsoleMessage?> consoleMessageShouldNotComplete = Completer<ConsoleMessage?>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
onWebViewCreated: (controller) {
controller.loadUrl(url: Uri.encodeFull('file://${fileHtml.path}'));
},
onConsoleMessage: (controller, consoleMessage) {
consoleMessageShouldNotComplete.complete(consoleMessage);
},
),
),
);
var result = await consoleMessageShouldNotComplete.future
.timeout(const Duration(seconds: 2), onTimeout: () => null);
expect(result, null);
final Completer<ConsoleMessage> consoleMessageCompleter = Completer<ConsoleMessage>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
onWebViewCreated: (controller) {
controller.loadUrl(url: Uri.encodeFull('file://${fileHtml.path}'),
iosAllowingReadAccessTo: Uri.encodeFull('file://${appSupportDir.path}/'));
},
onConsoleMessage: (controller, consoleMessage) {
consoleMessageCompleter.complete(consoleMessage);
},
),
),
);
final ConsoleMessage consoleMessage = await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message');
});
}, skip: !Platform.isIOS);
testWidgets('JavaScript Handler', (WidgetTester tester) async {
final Completer controllerCompleter =
@ -1080,7 +1202,7 @@ void main() {
await pageLoads.stream.first;
final InAppWebViewController controller = await controllerCompleter.future;
await controller.evaluateJavascript(source: 'window.open("about:blank", "_blank")');
await controller.evaluateJavascript(source: 'window.open("about:blank", "_blank");');
await pageLoads.stream.first;
final String? currentUrl = await controller.getUrl();
expect(currentUrl, 'about:blank');

View File

@ -2,12 +2,12 @@
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "FLUTTER_TARGET=integration_test/webview_flutter_test.dart"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"

View File

@ -10,9 +10,13 @@ import Flutter
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
/*FlutterDownloaderPlugin.setPluginRegistrantCallback({(registry: FlutterPluginRegistry) in
})*/
//FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
//private func registerPlugins(registry: FlutterPluginRegistry) {
// if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
// FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
// }
//}

View File

@ -1,8 +1,11 @@
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:path_provider/path_provider.dart';
// import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
@ -95,9 +98,10 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: false,
mediaPlaybackRequiresUserGesture: false,
clearCache: true,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
useHybridComposition: false,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,

View File

@ -8,6 +8,7 @@ import 'package:flutter_inappwebview_example/chrome_safari_browser_example.scree
import 'package:flutter_inappwebview_example/headless_in_app_webview.screen.dart';
import 'package:flutter_inappwebview_example/in_app_webiew_example.screen.dart';
import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart';
import 'package:path_provider/path_provider.dart';
// import 'package:permission_handler/permission_handler.dart';
// InAppLocalhostServer localhostServer = new InAppLocalhostServer();

View File

@ -21,7 +21,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_downloader: ^1.5.2
path_provider: ^1.6.27
path_provider: ^2.0.0-nullsafety
permission_handler: ^5.0.1+1
url_launcher: ^6.0.0-nullsafety.4
# connectivity: ^0.4.5+6

View File

@ -80,6 +80,5 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>

View File

@ -166,7 +166,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
if webViewController.isHidden {
webViewController.view.isHidden = true
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: false, completion: {() -> Void in
webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
})
webViewController.presentingViewController?.dismiss(animated: false, completion: {() -> Void in
webViewController.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
@ -175,7 +175,7 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
}
else {
webViewController.tmpWindow!.rootViewController!.present(webViewController, animated: true, completion: {() -> Void in
webViewController.webView.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
})
}
}

View File

@ -71,12 +71,12 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
let preWebviewConfiguration = InAppWebView.preWKWebViewConfiguration(options: webViewOptions)
if let wId = windowId, let webViewTransport = InAppWebView.windowWebViews[wId] {
self.webView = webViewTransport.webView
self.webView.IABController = self
self.webView.contextMenu = contextMenu
self.webView.channel = channel!
webView = webViewTransport.webView
webView.IABController = self
webView.contextMenu = contextMenu
webView.channel = channel!
} else {
self.webView = InAppWebView(frame: .zero,
webView = InAppWebView(frame: .zero,
configuration: preWebviewConfiguration,
IABController: self,
contextMenu: contextMenu,
@ -86,8 +86,8 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
methodCallDelegate = InAppWebViewMethodHandler(webView: webView!)
channel!.setMethodCallHandler(LeakAvoider(delegate: methodCallDelegate!).handle)
self.webView.appendUserScripts(userScripts: initUserScripts)
self.containerWebView.addSubview(self.webView)
webView.appendUserScripts(userScripts: initUserScripts)
containerWebView.addSubview(webView)
prepareConstraints()
prepareWebView()
@ -111,7 +111,7 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
let configuration = self.webView!.configuration
configuration.userContentController.add(contentRuleList!)
self.initLoad(initURL: self.initURL, initData: self.initData, initMimeType: self.initMimeType, initEncoding: self.initEncoding, initBaseUrl: self.initBaseUrl, initHeaders: self.initHeaders)
self.initLoad()
self.onBrowserCreated()
}
@ -122,7 +122,7 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
}
}
initLoad(initURL: initURL, initData: initData, initMimeType: initMimeType, initEncoding: initEncoding, initBaseUrl: initBaseUrl, initHeaders: initHeaders)
initLoad()
}
onBrowserCreated()
@ -131,9 +131,16 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
super.viewWillAppear(animated)
}
public func initLoad(initURL: URL?, initData: String?, initMimeType: String?, initEncoding: String?, initBaseUrl: String?, initHeaders: [String: String]?) {
if self.initData == nil {
loadUrl(url: self.initURL!, headers: self.initHeaders)
public func initLoad() {
if initData == nil, let initURL = initURL {
var allowingReadAccessToURL: URL? = nil
if let allowingReadAccessTo = webView.options?.allowingReadAccessTo, initURL.scheme == "file" {
allowingReadAccessToURL = URL(string: allowingReadAccessTo)
if allowingReadAccessToURL?.scheme != "file" {
allowingReadAccessToURL = nil
}
}
loadUrl(url: initURL, headers: initHeaders, allowingReadAccessTo: allowingReadAccessToURL)
}
else {
webView.loadData(data: initData!, mimeType: initMimeType!, encoding: initEncoding!, baseUrl: initBaseUrl!)
@ -144,29 +151,29 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
super.viewDidLoad()
urlField.delegate = self
urlField.text = self.initURL?.absoluteString
urlField.text = initURL?.absoluteString
urlField.backgroundColor = .white
urlField.textColor = .black
urlField.layer.borderWidth = 1.0
urlField.layer.borderColor = UIColor.lightGray.cgColor
urlField.layer.cornerRadius = 4
closeButton.addTarget(self, action: #selector(self.close), for: .touchUpInside)
closeButton.addTarget(self, action: #selector(close), for: .touchUpInside)
forwardButton.target = self
forwardButton.action = #selector(self.goForward)
forwardButton.action = #selector(goForward)
forwardButton.target = self
forwardButton.action = #selector(self.goForward)
forwardButton.action = #selector(goForward)
backButton.target = self
backButton.action = #selector(self.goBack)
backButton.action = #selector(goBack)
reloadButton.target = self
reloadButton.action = #selector(self.reload)
reloadButton.action = #selector(reload)
shareButton.target = self
shareButton.action = #selector(self.share)
shareButton.action = #selector(share)
spinner.hidesWhenStopped = true
spinner.isHidden = false
@ -184,53 +191,53 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
}
public func prepareConstraints () {
containerWebView_BottomFullScreenConstraint = NSLayoutConstraint(item: self.containerWebView!, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
containerWebView_TopFullScreenConstraint = NSLayoutConstraint(item: self.containerWebView!, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
containerWebView_BottomFullScreenConstraint = NSLayoutConstraint(item: containerWebView!, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
containerWebView_TopFullScreenConstraint = NSLayoutConstraint(item: containerWebView!, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
webView.translatesAutoresizingMaskIntoConstraints = false
let height = NSLayoutConstraint(item: self.webView!, attribute: .height, relatedBy: .equal, toItem: containerWebView, attribute: .height, multiplier: 1, constant: 0)
let width = NSLayoutConstraint(item: self.webView!, attribute: .width, relatedBy: .equal, toItem: containerWebView, attribute: .width, multiplier: 1, constant: 0)
let leftConstraint = NSLayoutConstraint(item: self.webView!, attribute: .leftMargin, relatedBy: .equal, toItem: containerWebView, attribute: .leftMargin, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: self.webView!, attribute: .rightMargin, relatedBy: .equal, toItem: containerWebView, attribute: .rightMargin, multiplier: 1, constant: 0)
let bottomContraint = NSLayoutConstraint(item: self.webView!, attribute: .bottomMargin, relatedBy: .equal, toItem: containerWebView, attribute: .bottomMargin, multiplier: 1, constant: 0)
let height = NSLayoutConstraint(item: webView!, attribute: .height, relatedBy: .equal, toItem: containerWebView, attribute: .height, multiplier: 1, constant: 0)
let width = NSLayoutConstraint(item: webView!, attribute: .width, relatedBy: .equal, toItem: containerWebView, attribute: .width, multiplier: 1, constant: 0)
let leftConstraint = NSLayoutConstraint(item: webView!, attribute: .leftMargin, relatedBy: .equal, toItem: containerWebView, attribute: .leftMargin, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: webView!, attribute: .rightMargin, relatedBy: .equal, toItem: containerWebView, attribute: .rightMargin, multiplier: 1, constant: 0)
let bottomContraint = NSLayoutConstraint(item: webView!, attribute: .bottomMargin, relatedBy: .equal, toItem: containerWebView, attribute: .bottomMargin, multiplier: 1, constant: 0)
containerWebView.addConstraints([height, width, leftConstraint, rightConstraint, bottomContraint])
webView_BottomFullScreenConstraint = NSLayoutConstraint(item: webView!, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.containerWebView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
webView_TopFullScreenConstraint = NSLayoutConstraint(item: webView!, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.containerWebView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
webView_BottomFullScreenConstraint = NSLayoutConstraint(item: webView!, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: containerWebView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
webView_TopFullScreenConstraint = NSLayoutConstraint(item: webView!, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: containerWebView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
}
public func prepareWebView() {
self.webView.options = webViewOptions
self.webView.prepare()
webView.options = webViewOptions
webView.prepare()
if (browserOptions?.hideUrlBar)! {
self.urlField.isHidden = true
self.urlField.isEnabled = false
urlField.isHidden = true
urlField.isEnabled = false
}
if (browserOptions?.toolbarTop)! {
if browserOptions?.toolbarTopBackgroundColor != "" {
self.toolbarTop.backgroundColor = color(fromHexString: (browserOptions?.toolbarTopBackgroundColor)!)
toolbarTop.backgroundColor = color(fromHexString: (browserOptions?.toolbarTopBackgroundColor)!)
}
}
else {
self.toolbarTop.isHidden = true
self.toolbarTop_BottomToWebViewTopConstraint.isActive = false
self.containerWebView_TopFullScreenConstraint.isActive = true
self.webView_TopFullScreenConstraint.isActive = true
toolbarTop.isHidden = true
toolbarTop_BottomToWebViewTopConstraint.isActive = false
containerWebView_TopFullScreenConstraint.isActive = true
webView_TopFullScreenConstraint.isActive = true
}
if (browserOptions?.toolbarBottom)! {
if browserOptions?.toolbarBottomBackgroundColor != "" {
self.toolbarBottom.backgroundColor = color(fromHexString: (browserOptions?.toolbarBottomBackgroundColor)!)
toolbarBottom.backgroundColor = color(fromHexString: (browserOptions?.toolbarBottomBackgroundColor)!)
}
self.toolbarBottom.isTranslucent = (browserOptions?.toolbarBottomTranslucent)!
toolbarBottom.isTranslucent = (browserOptions?.toolbarBottomTranslucent)!
}
else {
self.toolbarBottom.isHidden = true
self.toolbarBottom_TopToWebViewBottomConstraint.isActive = false
self.containerWebView_BottomFullScreenConstraint.isActive = true
self.webView_BottomFullScreenConstraint.isActive = true
toolbarBottom.isHidden = true
toolbarBottom_TopToWebViewBottomConstraint.isActive = false
containerWebView_BottomFullScreenConstraint.isActive = true
webView_BottomFullScreenConstraint.isActive = true
}
if browserOptions?.closeButtonCaption != "" {
@ -242,12 +249,12 @@ public class InAppBrowserWebViewController: UIViewController, UIScrollViewDelega
}
public func prepareBeforeViewWillAppear() {
self.modalPresentationStyle = UIModalPresentationStyle(rawValue: (browserOptions?.presentationStyle)!)!
self.modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)!
modalPresentationStyle = UIModalPresentationStyle(rawValue: (browserOptions?.presentationStyle)!)!
modalTransitionStyle = UIModalTransitionStyle(rawValue: (browserOptions?.transitionStyle)!)!
}
public func loadUrl(url: URL, headers: [String: String]?) {
webView.loadUrl(url: url, headers: headers)
public func loadUrl(url: URL, headers: [String: String]?, allowingReadAccessTo: URL?) {
webView.loadUrl(url: url, headers: headers, allowingReadAccessTo: allowingReadAccessTo)
updateUrlTextField(url: (webView.currentURL?.absoluteString)!)
}

View File

@ -134,9 +134,9 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
}
public func load(initialUrl: String?, initialFile: String?, initialData: [String: String]?, initialHeaders: [String: String]?) {
if initialFile != nil {
if let initialFile = initialFile {
do {
try webView!.loadFile(url: initialFile!, headers: initialHeaders)
try webView?.loadFile(url: initialFile, headers: initialHeaders)
}
catch let error as NSError {
dump(error)
@ -144,15 +144,22 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
return
}
if initialData != nil {
let data = initialData!["data"]!
let mimeType = initialData!["mimeType"]!
let encoding = initialData!["encoding"]!
let baseUrl = initialData!["baseUrl"]!
webView!.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
if let initialData = initialData {
let data = initialData["data"]!
let mimeType = initialData["mimeType"]!
let encoding = initialData["encoding"]!
let baseUrl = initialData["baseUrl"]!
webView?.loadData(data: data, mimeType: mimeType, encoding: encoding, baseUrl: baseUrl)
}
else if let url = URL(string: initialUrl!) {
webView!.loadUrl(url: url, headers: initialHeaders)
else if let initialUrl = initialUrl, let url = URL(string: initialUrl) {
var allowingReadAccessToURL: URL? = nil
if let allowingReadAccessTo = webView?.options?.allowingReadAccessTo, url.scheme == "file" {
allowingReadAccessToURL = URL(string: allowingReadAccessTo)
if allowingReadAccessToURL?.scheme != "file" {
allowingReadAccessToURL = nil
}
}
webView?.loadUrl(url: url, headers: initialHeaders, allowingReadAccessTo: allowingReadAccessToURL)
}
}
}

View File

@ -1838,18 +1838,22 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
})
}
public func loadUrl(url: URL, headers: [String: String]?) {
var request = URLRequest(url: url)
currentURL = url
if headers != nil {
if let mutableRequest = (request as NSURLRequest).mutableCopy() as? NSMutableURLRequest {
for (key, value) in headers! {
mutableRequest.setValue(value, forHTTPHeaderField: key)
public func loadUrl(url: URL, headers: [String: String]?, allowingReadAccessTo: URL?) {
if #available(iOS 9.0, *), let allowingReadAccessTo = allowingReadAccessTo, url.scheme == "file", allowingReadAccessTo.scheme == "file" {
loadFileURL(url, allowingReadAccessTo: allowingReadAccessTo)
} else {
var request = URLRequest(url: url)
currentURL = url
if headers != nil {
if let mutableRequest = (request as NSURLRequest).mutableCopy() as? NSMutableURLRequest {
for (key, value) in headers! {
mutableRequest.setValue(value, forHTTPHeaderField: key)
}
request = mutableRequest as URLRequest
}
request = mutableRequest as URLRequest
}
load(request)
}
load(request)
}
public func postUrl(url: URL, postData: Data, completionHandler: @escaping () -> Void) {
@ -1887,7 +1891,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if assetURL == nil {
throw NSError(domain: url + " asset file cannot be found!", code: 0)
}
loadUrl(url: assetURL!, headers: headers)
loadUrl(url: assetURL!, headers: headers, allowingReadAccessTo: nil)
}
func setOptions(newOptions: InAppWebViewOptions, newOptionsMap: [String: Any]) {
@ -3167,7 +3171,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
if !handledByClient, InAppWebView.windowWebViews[windowId] != nil {
InAppWebView.windowWebViews.removeValue(forKey: windowId)
if let url = navigationAction.request.url {
self.loadUrl(url: url, headers: nil)
self.loadUrl(url: url, headers: nil, allowingReadAccessTo: nil)
}
}
}
@ -3435,9 +3439,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
let serverTrust = challenge.protectionSpace.serverTrust!
var secResult = SecTrustResultType.invalid
SecTrustEvaluate(serverTrust, &secResult);
let secTrustEvaluateStatus = SecTrustEvaluate(serverTrust, &secResult);
if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
if secTrustEvaluateStatus == errSecSuccess, let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
let serverCertificateCFData = SecCertificateCopyData(serverCertificate)
let data = CFDataGetBytePtr(serverCertificateCFData)
let size = CFDataGetLength(serverCertificateCFData)

View File

@ -67,6 +67,7 @@ public class InAppWebViewOptions: Options<InAppWebView> {
var limitsNavigationsToAppBoundDomains = false
var useOnNavigationResponse = false
var applePayAPIEnabled = false
var allowingReadAccessTo: String? = nil
override init(){
super.init()

View File

@ -32,7 +32,12 @@ class InAppWebViewMethodHandler: FlutterMethodCallDelegate {
case "loadUrl":
let url = arguments!["url"] as! String
let headers = arguments!["headers"] as! [String: String]
webView?.loadUrl(url: URL(string: url)!, headers: headers)
let allowingReadAccessTo = arguments!["iosAllowingReadAccessTo"] as? String
var allowingReadAccessToURL: URL? = nil
if let allowingReadAccessTo = allowingReadAccessTo {
allowingReadAccessToURL = URL(string: allowingReadAccessTo)
}
webView?.loadUrl(url: URL(string: url)!, headers: headers, allowingReadAccessTo: allowingReadAccessToURL)
result(true)
break
case "postUrl":

View File

@ -193,9 +193,9 @@ class ASN1DERDecoder {
}
/// Decode DER OID bytes to String with dot notation
static String decodeOid({required List<int> contentData}) {
static String? decodeOid({required List<int> contentData}) {
if (contentData.isEmpty) {
return "";
return null;
}
var oid = "";
@ -393,6 +393,16 @@ class ASN1DERDecoder {
return date;
}
static List<int> sequenceContent({required List<int> data}) {
var iterator = data.iterator;
iterator.moveNext();
try {
return loadSubContent(iterator: iterator);
} catch (e) {
return data;
}
}
}
BigInt? toIntValue(List<int> data) {

View File

@ -0,0 +1,27 @@
import 'dart:typed_data';
import 'asn1_identifier.dart';
class ASN1DEREncoder {
static Uint8List encodeSequence({required Uint8List content}) {
var encoded = Uint8List.fromList([]);
encoded.add(ASN1Identifier.constructedTag | ASN1IdentifierTagNumber.SEQUENCE.toValue());
encoded.addAll(contentLength(size: content.length));
encoded.addAll(content);
return Uint8List.fromList(encoded);
}
static Uint8List contentLength({required int size}) {
if (size >= 128) {
var lenBytes = Uint8List(size);
while (lenBytes.first == 0) {
lenBytes.removeAt(0);
}
int len = 0x80 | lenBytes.length;
return Uint8List(len)..addAll(lenBytes);
} else {
return Uint8List(size);
}
}
}

View File

@ -1,3 +1,5 @@
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class ASN1DistinguishedNames {
final String _oid;
final String _representation;
@ -67,4 +69,40 @@ class ASN1DistinguishedNames {
@override
int get hashCode => _oid.hashCode;
/// Format subject/issuer information in RFC1779
static String string({required ASN1Object block}) {
var result = "";
var oidNames = ASN1DistinguishedNames.values;
for (var oidName in oidNames) {
var oidBlock = block.findOid(oidValue: oidName.oid());
if (oidBlock == null) {
continue;
}
if (result.isNotEmpty) {
result += ", ";
}
result += oidName.representation();
result += "=";
String? value;
try {
value = oidBlock.parent?.sub?.last.value as String?;
} catch (e) {}
if (value != null) {
result += quote(value);
}
}
return result;
}
static String quote(String string) {
var specialChars = [",", "+", "=", "\n", "<", ">", "#", ";", "\\"];
for (var specialChar in specialChars) {
if (string.contains(specialChar)) {
return "\"" + string + "\"";
}
}
return string;
}
}

View File

@ -206,15 +206,16 @@ class ASN1IdentifierTagNumber {
class ASN1Identifier {
int rawValue;
static int constructedTag = 0x20;
ASN1Identifier(this.rawValue);
bool isPrimitive() {
return (rawValue & 0x20) == 0;
return (rawValue & ASN1Identifier.constructedTag) == 0;
}
bool isConstructed() {
return (rawValue & 0x20) != 0;
return (rawValue & ASN1Identifier.constructedTag) != 0;
}
ASN1IdentifierTagNumber tagNumber() {

View File

@ -9,7 +9,7 @@ class ASN1Object {
/// This property contains the DER encoded object
Uint8List? encoded;
/// This property contains the decoded Swift object whenever is possible
/// This property contains the decoded object whenever is possible
dynamic value;
ASN1Identifier? identifier;
@ -96,4 +96,22 @@ class ASN1Object {
}
return null;
}
String? get asString {
var string = value as String?;
if (string != null) {
return string;
}
if (sub != null && sub!.length > 0) {
for (var item in sub!) {
var itemAsString = item.asString;
if (itemAsString != null) {
return itemAsString;
}
}
}
return null;
}
}

View File

@ -1,3 +1,5 @@
// from https://github.com/filom/ASN1Decoder
export 'asn1_decoder.dart';
export 'asn1_distinguished_names.dart';
export 'asn1_identifier.dart';
@ -7,3 +9,4 @@ export 'key_usage.dart';
export 'x509_certificate.dart';
export 'x509_extension.dart';
export 'x509_public_key.dart';
export 'asn1_der_encoder.dart';

View File

@ -100,6 +100,11 @@ class OID {
OID.codeSigning,
OID.emailProtection,
OID.timeStamping,
OID.pkcsSha256,
OID.sha2Family,
OID.sha3_244,
OID.sha3_256,
OID.sha3_384,
].toSet();
static OID? fromValue(String? value) {
@ -174,10 +179,15 @@ class OID {
static const dateOfBirth = const OID._internal("1.3.6.1.5.5.7.9.1");
static const desCBC = const OID._internal("1.3.14.3.2.7");
static const sha1 = const OID._internal("1.3.14.3.2.26");
static const pkcsSha256 = const OID._internal("1.3.6.1.4.1.22554.1.2.1");
static const sha2Family = const OID._internal("1.3.6.1.4.1.22554.1.2");
static const sha3_244 = const OID._internal("2.16.840.1.101.3.4.2.7");
static const sha3_256 = const OID._internal("2.16.840.1.101.3.4.2.8");
static const sha3_384 = const OID._internal("2.16.840.1.101.3.4.2.9");
static const md5 = const OID._internal("0.2.262.1.10.1.3.2");
static const sha256 = const OID._internal("2.16.840.1.101.3.4.2.1");
static const sha384 = const OID._internal("2.16.840.1.101.3.4.2.2");
static const sha512 = const OID._internal("2.16.840.1.101.3.4.2.3");
static const md5 = const OID._internal("1.2.840.113549.2.5");
static const VeriSignEVpolicy =
const OID._internal("2.16.840.1.113733.1.7.23.6");
static const extendedValidation = const OID._internal("2.23.140.1.1");
@ -278,10 +288,15 @@ class OID {
"1.3.6.1.5.5.7.9.1": "dateOfBirth",
"1.3.14.3.2.7": "desCBC",
"1.3.14.3.2.26": "sha1",
"1.3.6.1.4.1.22554.1.2.1": "pkcsSha256",
"1.3.6.1.4.1.22554.1.2": "sha2Family",
"2.16.840.1.101.3.4.2.7": "sha3_244",
"2.16.840.1.101.3.4.2.8": "sha3_256",
"2.16.840.1.101.3.4.2.9": "sha3_384",
"2.16.840.1.101.3.4.2.1": "sha256",
"2.16.840.1.101.3.4.2.2": "sha384",
"2.16.840.1.101.3.4.2.3": "sha512",
"1.2.840.113549.2.5": "md5",
"0.2.262.1.10.1.3.2": "md5",
"2.16.840.1.113733.1.7.23.6": "VeriSign EV policy",
"2.23.140.1.1": "extendedValidation",
"2.23.140.1.2.2": "organizationValidated",

View File

@ -131,7 +131,7 @@ class X509Certificate {
String? get issuerDistinguishedName {
var issuerBlock = block1?.atIndex(X509BlockPosition.issuer);
if (issuerBlock != null) {
return blockDistinguishedName(block: issuerBlock);
return ASN1DistinguishedNames.string(block: issuerBlock);
}
return null;
}
@ -175,7 +175,7 @@ class X509Certificate {
String? get subjectDistinguishedName {
var subjectBlock = block1?.atIndex(X509BlockPosition.subject);
if (subjectBlock != null) {
return blockDistinguishedName(block: subjectBlock);
return ASN1DistinguishedNames.string(block: subjectBlock);
}
return null;
}
@ -278,11 +278,11 @@ class X509Certificate {
///Gets a collection of subject alternative names from the SubjectAltName extension, (OID = 2.5.29.17).
List<String> get subjectAlternativeNames =>
extensionObject(oid: OID.subjectAltName)?.valueAsStrings ?? <String>[];
extensionObject(oid: OID.subjectAltName)?.alternativeNameAsStrings ?? <String>[];
///Gets a collection of issuer alternative names from the IssuerAltName extension, (OID = 2.5.29.18).
List<String> get issuerAlternativeNames =>
extensionObject(oid: OID.issuerAltName)?.valueAsStrings ?? <String>[];
extensionObject(oid: OID.issuerAltName)?.alternativeNameAsStrings ?? <String>[];
///Gets the informations of the public key from this certificate.
X509PublicKey? get publicKey {
@ -321,81 +321,24 @@ class X509Certificate {
///Gets the certificate constraints path length from the
///critical BasicConstraints extension, (OID = 2.5.29.19).
int get basicConstraints {
var sub = extensionObject(oid: OID.basicConstraints)
?.block
?.lastSub()
?.lastSub()
?.lastSub();
if (sub != null) {
if (sub.value is List<int>) {
return (sub.value as List<int>).length;
}
}
return -1;
}
BasicConstraintExtension? get basicConstraints => extensionObject(oid: OID.basicConstraints) as BasicConstraintExtension?;
///Gets the raw bits from the Subject Key Identifier (SKID) extension, (OID = 2.5.29.14).
List<int> get subjectKeyIdentifier =>
extensionObject(oid: OID.subjectKeyIdentifier)
?.block
?.lastSub()
?.lastSub()
?.value ??
<int>[];
SubjectKeyIdentifierExtension? get subjectKeyIdentifier => extensionObject(oid: OID.subjectKeyIdentifier) as SubjectKeyIdentifierExtension?;
///Gets the raw bits from the Authority Key Identifier extension, (OID = 2.5.29.35).
List<int> get authorityKeyIdentifier =>
extensionObject(oid: OID.authorityKeyIdentifier)
?.block
?.lastSub()
?.lastSub()
?.firstSub()
?.value ??
<int>[];
AuthorityKeyIdentifierExtension? get authorityKeyIdentifier => extensionObject(oid: OID.authorityKeyIdentifier) as AuthorityKeyIdentifierExtension?;
///Gets the list of certificate policies from the CertificatePolicies extension, (OID = 2.5.29.32).
List<String> get certificatePolicies =>
extensionObject(oid: OID.certificatePolicies)
?.block
?.lastSub()
?.firstSub()
?.sub
?.map((e) => e.firstSub()?.value as String)
.toList() ??
<String>[];
CertificatePoliciesExtension? get certificatePolicies => extensionObject(oid: OID.certificatePolicies) as CertificatePoliciesExtension?;
///Gets the list of CRL distribution points from the CRLDistributionPoints extension, (OID = 2.5.29.31).
List<String> get cRLDistributionPoints =>
extensionObject(oid: OID.cRLDistributionPoints)
?.block
?.lastSub()
?.firstSub()
?.sub
?.map((e) => e.firstSub()?.firstSub()?.firstSub()?.value as String)
.toList() ??
<String>[];
CRLDistributionPointsExtension? get cRLDistributionPoints => extensionObject(oid: OID.cRLDistributionPoints) as CRLDistributionPointsExtension?;
///Gets the map of the format (as a key) and location (as a value) of additional information
///about the CA who issued the certificate in which this extension appears
///from the AuthorityInfoAccess extension, (OID = 1.3.6.1.5.5.5.7.1.1).
Map<String, String> get authorityInfoAccess {
var result = <String, String>{};
var sub = extensionObject(oid: OID.authorityInfoAccess)
?.block
?.lastSub()
?.firstSub()
?.sub;
if (sub != null) {
sub.forEach((element) {
if (element.subCount() > 1) {
result.putIfAbsent(
element.subAtIndex(0)!.value, () => element.subAtIndex(1)!.value);
}
});
}
return result;
}
AuthorityInfoAccessExtension? get authorityInfoAccess => extensionObject(oid: OID.authorityInfoAccess) as AuthorityInfoAccessExtension?;
List<ASN1Object>? get extensionBlocks =>
block1?.atIndex(X509BlockPosition.extensions)?.subAtIndex(0)?.sub;
@ -410,46 +353,25 @@ class X509Certificate {
?.findOid(oidValue: oidValue)
?.parent;
if (block != null) {
if (oidValue == OID.basicConstraints.toValue()) {
return BasicConstraintExtension(block: block);
} else if (oidValue == OID.subjectKeyIdentifier.toValue()) {
return SubjectKeyIdentifierExtension(block: block);
} else if (oidValue == OID.authorityInfoAccess.toValue()) {
return AuthorityInfoAccessExtension(block: block);
} else if (oidValue == OID.authorityKeyIdentifier.toValue()) {
return AuthorityKeyIdentifierExtension(block: block);
} else if (oidValue == OID.certificatePolicies.toValue()) {
return CertificatePoliciesExtension(block: block);
} else if (oidValue == OID.cRLDistributionPoints.toValue()) {
return CRLDistributionPointsExtension(block: block);
}
return X509Extension(block: block);
}
}
return null;
}
///Format subject/issuer information in RFC1779
String blockDistinguishedName({required ASN1Object block}) {
var result = "";
for (var oidName in ASN1DistinguishedNames.values) {
var oidBlock = block.findOid(oidValue: oidName.oid());
if (oidBlock != null) {
if (result.isNotEmpty) {
result += ", ";
}
result += oidName.representation();
result += "=";
var sub = oidBlock.parent?.sub;
if (sub != null && sub.length > 0) {
var value = sub.last.value as String?;
if (value != null) {
var specialChar = ",+=\n<>#;\\";
var quote = "";
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (specialChar.contains(char)) {
quote = "\"";
}
}
result += quote;
result += value;
result += quote;
}
}
}
}
return result;
}
@override
String toString() {
return description;
@ -457,7 +379,7 @@ class X509Certificate {
Map<String, dynamic> toMap() {
return {
"basicConstraints": basicConstraints,
"basicConstraints": basicConstraints?.toMap(),
"subjectAlternativeNames": subjectAlternativeNames,
"issuerAlternativeNames": issuerAlternativeNames,
"extendedKeyUsage": extendedKeyUsage,
@ -476,11 +398,11 @@ class X509Certificate {
"nonCriticalExtensionOIDs": nonCriticalExtensionOIDs,
"encoded": encoded,
"publicKey": publicKey?.toMap(),
"subjectKeyIdentifier": subjectKeyIdentifier,
"authorityKeyIdentifier": authorityKeyIdentifier,
"certificatePolicies": certificatePolicies,
"cRLDistributionPoints": cRLDistributionPoints,
"authorityInfoAccess": authorityInfoAccess,
"subjectKeyIdentifier": subjectKeyIdentifier?.toMap(),
"authorityKeyIdentifier": authorityKeyIdentifier?.toMap(),
"certificatePolicies": certificatePolicies?.toMap(),
"cRLDistributionPoints": cRLDistributionPoints?.toMap(),
"authorityInfoAccess": authorityInfoAccess?.toMap(),
};
}

View File

@ -1,6 +1,12 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'x509_certificate.dart';
import 'asn1_object.dart';
import 'oid.dart';
import 'asn1_distinguished_names.dart';
class X509Extension {
ASN1Object? block;
@ -59,4 +65,413 @@ class X509Extension {
}
return result;
}
// Used for SubjectAltName and IssuerAltName
// Every name can be one of these subtype:
// - otherName [0] INSTANCE OF OTHER-NAME,
// - rfc822Name [1] IA5String,
// - dNSName [2] IA5String,
// - x400Address [3] ORAddress,
// - directoryName [4] Name,
// - ediPartyName [5] EDIPartyName,
// - uniformResourceIdentifier [6] IA5String,
// - IPAddress [7] OCTET STRING,
// - registeredID [8] OBJECT IDENTIFIER
//
// Result does not support: x400Address and ediPartyName
//
List<String> get alternativeNameAsStrings {
List<String> result = [];
var sub = <ASN1Object>[];
try {
sub = block?.sub?.last.sub?.last.sub ?? <ASN1Object>[];
} catch (e) {}
for (var item in sub) {
var name = generalName(item: item);
if (name != null) {
result.add(name);
}
}
return result;
}
String? generalName({required ASN1Object item}) {
var nameType = item.identifier?.tagNumber().toValue();
if (nameType == null) {
return null;
}
switch (nameType) {
case 0:
String? name;
try {
name = item.sub?.last.sub?.last.value as String?;
} catch (e) {}
return name;
case 1:
case 2:
case 6:
String? name = item.value as String?;
return name;
case 4:
return ASN1DistinguishedNames.string(block: item);
case 7:
var ip = item.value as List<int>?;
if (ip != null) {
return ip.map((e) => e.toString()).join(".");
}
break;
case 8:
var value = item.value as String?;
if (value != null) {
try {
var data = utf8.encode(value);
var oid = ASN1DERDecoder.decodeOid(contentData: data);
return oid;
} catch (e) {}
}
break;
default:
return null;
}
return null;
}
}
/// Recognition for Basic Constraint Extension (2.5.29.19)
class BasicConstraintExtension extends X509Extension {
BasicConstraintExtension({required block}) : super(block: block);
bool get isCA => valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value as bool? ?? false;
int? get pathLenConstraint {
var data = valueAsBlock?.subAtIndex(0)?.subAtIndex(0)?.value as List<int>?;
if (data != null) {
return data.length;
}
return null;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"isCA": isCA,
"pathLenConstraint": pathLenConstraint,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
/// Recognition for Subject Key Identifier Extension (2.5.29.14)
class SubjectKeyIdentifierExtension extends X509Extension {
SubjectKeyIdentifierExtension({required block}) : super(block: block);
@override
List<int>? get value {
var rawValue = valueAsBlock?.encoded;
if (rawValue != null) {
return ASN1DERDecoder.sequenceContent(data: rawValue.toList());
}
return null;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"value": value,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
class AuthorityInfoAccess {
String method;
String location;
AuthorityInfoAccess({required this.method, required this.location});
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"method": method,
"location": location,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
/// Recognition for Authority Info Access Extension (1.3.6.1.5.5.7.1.1)
class AuthorityInfoAccessExtension extends X509Extension {
AuthorityInfoAccessExtension({required block}) : super(block: block);
List<AuthorityInfoAccess>? get infoAccess {
if (valueAsBlock == null) {
return null;
}
var subs = valueAsBlock!.subAtIndex(0)?.sub ?? <ASN1Object>[];
List<AuthorityInfoAccess> result = <AuthorityInfoAccess>[];
subs.forEach((sub) {
var oidData = sub.subAtIndex(0)?.encoded;
var nameBlock = sub.subAtIndex(1);
if (oidData == null || nameBlock == null) {
return;
}
var oid = ASN1DERDecoder.decodeOid(contentData: oidData.toList());
var location = generalName(item: nameBlock);
if (oid != null && location != null) {
result.add(AuthorityInfoAccess(method: oid, location: location));
}
});
return result;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"infoAccess": infoAccess?.map((e) => e.toMap()).toList(),
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
/// Recognition for Authority Key Identifier Extension (2.5.29.35)
class AuthorityKeyIdentifierExtension extends X509Extension {
AuthorityKeyIdentifierExtension({required block}) : super(block: block);
///AuthorityKeyIdentifier ::= SEQUENCE {
/// keyIdentifier [0] KeyIdentifier OPTIONAL,
/// authorityCertIssuer [1] GeneralNames OPTIONAL,
/// authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
List<int>? get keyIdentifier {
var sequence = valueAsBlock?.subAtIndex(0)?.sub;
if (sequence == null) {
return null;
}
ASN1Object? sub;
try {
sub = sequence.firstWhere((element) => element.identifier?.tagNumber().toValue() == 0);
return sub.encoded;
} catch (e) {}
return null;
}
List<String>? get certificateIssuer {
var sequence = valueAsBlock?.subAtIndex(0)?.sub;
if (sequence == null) {
return null;
}
ASN1Object? sub;
try {
sub = sequence.firstWhere((element) => element.identifier?.tagNumber().toValue() == 1);
List<String>? result;
if (sub.sub != null) {
result = <String>[];
sub.sub?.forEach((e) {
var name = generalName(item: e);
if (name != null) {
result!.add(name);
}
});
}
return result;
} catch (e) {}
return null;
}
List<int>? get serialNumber {
var sequence = valueAsBlock?.subAtIndex(0)?.sub;
if (sequence == null) {
return null;
}
ASN1Object? sub;
try {
sub = sequence.firstWhere((element) => element.identifier?.tagNumber().toValue() == 2);
return sub.encoded;
} catch (e) {}
return null;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"keyIdentifier": keyIdentifier,
"certificateIssuer": certificateIssuer,
"serialNumber": serialNumber,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
class CertificatePolicyQualifier {
String oid;
String? value;
CertificatePolicyQualifier({required this.oid, this.value});
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"oid": oid,
"value": value,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
class CertificatePolicy {
String oid;
List<CertificatePolicyQualifier>? qualifiers;
CertificatePolicy({required this.oid, this.qualifiers});
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"oid": oid,
"qualifiers": qualifiers?.map((e) => e.toMap()).toList(),
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
/// Recognition for Certificate Policies Extension (2.5.29.32)
class CertificatePoliciesExtension extends X509Extension {
CertificatePoliciesExtension({required block}) : super(block: block);
List<CertificatePolicy>? get policies {
if (valueAsBlock == null) {
return null;
}
var subs = valueAsBlock!.subAtIndex(0)?.sub ?? <ASN1Object>[];
List<CertificatePolicy> result = <CertificatePolicy>[];
subs.forEach((sub) {
var data = sub.subAtIndex(0)?.encoded;
String? oid;
if (data != null) {
oid = ASN1DERDecoder.decodeOid(contentData: data.toList());
if (oid == null) {
return;
}
} else {
return;
}
List<CertificatePolicyQualifier>? qualifiers;
var subQualifiers = sub.subAtIndex(1);
if (subQualifiers != null && subQualifiers.sub != null) {
qualifiers = <CertificatePolicyQualifier>[];
subQualifiers.sub!.forEach((sub) {
var rawValue = sub.subAtIndex(0)?.encoded;
String? oid;
if (rawValue != null) {
oid = ASN1DERDecoder.decodeOid(contentData: rawValue.toList());
if (oid == null) {
return;
}
var value = sub.subAtIndex(1)?.asString;
qualifiers!.add(CertificatePolicyQualifier(oid: oid, value: value));
}
});
}
result.add(CertificatePolicy(oid: oid, qualifiers: qualifiers));
});
return result;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"policies": policies?.map((e) => e.toMap()).toList(),
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}
class CRLDistributionPointsExtension extends X509Extension {
CRLDistributionPointsExtension({required block}) : super(block: block);
List<String>? get crls {
if (valueAsBlock == null) {
return null;
}
var subs = valueAsBlock!.subAtIndex(0)?.sub ?? <ASN1Object>[];
List<String> result = <String>[];
subs.forEach((sub) {
var asString = sub.asString;
if (asString != null) {
result.add(asString);
}
});
return result;
}
@override
String toString() {
return toMap().toString();
}
Map<String, dynamic> toMap() {
return {
"crls": crls,
};
}
Map<String, dynamic> toJson() {
return toMap();
}
}

View File

@ -1,5 +1,7 @@
import 'dart:typed_data';
import 'package:flutter_inappwebview/src/X509Certificate/asn1_der_encoder.dart';
import 'asn1_decoder.dart';
import 'asn1_object.dart';
import 'oid.dart';
@ -15,6 +17,14 @@ class X509PublicKey {
String? get algParams => pkBlock?.subAtIndex(0)?.subAtIndex(1)?.value;
Uint8List? get derEncodedKey {
var value = pkBlock?.encoded;
if (value != null) {
return ASN1DEREncoder.encodeSequence(content: value);
}
return null;
}
Uint8List? get encoded {
var oid = OID.fromValue(algOid);
var keyData = pkBlock?.subAtIndex(1)?.value ?? null;

View File

@ -70,7 +70,6 @@ class HeadlessInAppWebView implements WebView {
this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission,
this.androidOnScaleChanged,
this.androidOnRequestFocus,
this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload,
@ -230,9 +229,6 @@ class HeadlessInAppWebView implements WebView {
@override
final void Function(InAppWebViewController controller)? onWindowBlur;
@override
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
@override
final void Function(InAppWebViewController controller, String url)?
onDownloadStart;

View File

@ -686,14 +686,6 @@ class InAppBrowser {
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebViewClient#onScaleChanged(android.webkit.WebView,%20float,%20float)
void androidOnScaleChanged(double oldScale, double newScale) {}
///Event fired when there is a request to display and focus for this WebView.
///This may happen due to another WebView opening a link in this WebView and requesting that this WebView be displayed.
///
///**NOTE**: available only on Android.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onRequestFocus(android.webkit.WebView)
void androidOnRequestFocus() {}
///Event fired when there is new favicon for the current page.
///
///[icon] represents the favicon for the current page.

View File

@ -82,7 +82,6 @@ class InAppWebView extends StatefulWidget implements WebView {
this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission,
this.androidOnScaleChanged,
this.androidOnRequestFocus,
this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload,
@ -191,9 +190,6 @@ class InAppWebView extends StatefulWidget implements WebView {
@override
final void Function(InAppWebViewController controller)? onWindowBlur;
@override
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
@override
final void Function(InAppWebViewController controller, Uint8List icon)?
androidOnReceivedIcon;

View File

@ -373,11 +373,6 @@ class InAppWebViewController {
else if (_inAppBrowser != null)
_inAppBrowser!.androidOnScaleChanged(oldScale, newScale);
break;
case "onRequestFocus":
if (_webview != null && _webview!.androidOnRequestFocus != null)
_webview!.androidOnRequestFocus!(this);
else if (_inAppBrowser != null) _inAppBrowser!.androidOnRequestFocus();
break;
case "onReceivedIcon":
Uint8List icon = Uint8List.fromList(call.arguments["icon"].cast<int>());
@ -1250,15 +1245,26 @@ class InAppWebViewController {
///Loads the given [url] with optional [headers] specified as a map from name to value.
///
///[iosAllowingReadAccessTo], used in combination with [url] (using the `file://` scheme),
///is an iOS-specific argument that represents the URL from which to read the web content.
///This URL must be a file-based URL (using the `file://` scheme).
///Specify the same value as the URL parameter to prevent WebView from reading any other content.
///Specify a directory to give WebView permission to read additional files in the specified directory.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#loadUrl(java.lang.String)
///
///**Official iOS API**: https://developer.apple.com/documentation/webkit/wkwebview/1414954-load
///**Official iOS API**:
///- https://developer.apple.com/documentation/webkit/wkwebview/1414954-load
///- if [iosAllowingReadAccessTo] is used, https://developer.apple.com/documentation/webkit/wkwebview/1414973-loadfileurl
Future<void> loadUrl(
{required String url, Map<String, String> headers = const {}}) async {
{required String url, Map<String, String> headers = const {}, String? iosAllowingReadAccessTo}) async {
assert(url.isNotEmpty);
assert(iosAllowingReadAccessTo == null || iosAllowingReadAccessTo.startsWith("file://"));
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('url', () => url);
args.putIfAbsent('headers', () => headers);
args.putIfAbsent('iosAllowingReadAccessTo', () => iosAllowingReadAccessTo);
await _channel.invokeMethod('loadUrl', args);
}

View File

@ -529,14 +529,6 @@ abstract class WebView {
InAppWebViewController controller, double oldScale, double newScale)?
androidOnScaleChanged;
///Event fired when there is a request to display and focus for this WebView.
///This may happen due to another WebView opening a link in this WebView and requesting that this WebView be displayed.
///
///**NOTE**: available only on Android.
///
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebChromeClient#onRequestFocus(android.webkit.WebView)
final void Function(InAppWebViewController controller)? androidOnRequestFocus;
///Event fired when there is new favicon for the current page.
///
///[icon] represents the favicon for the current page.
@ -696,7 +688,6 @@ abstract class WebView {
this.androidOnRenderProcessUnresponsive,
this.androidOnFormResubmission,
this.androidOnScaleChanged,
this.androidOnRequestFocus,
this.androidOnReceivedIcon,
this.androidOnReceivedTouchIconUrl,
this.androidOnJsBeforeUnload,

View File

@ -923,6 +923,12 @@ class IOSInAppWebViewOptions
///**NOTE**: available on iOS 13.0+.
bool applePayAPIEnabled;
///Used in combination with [WebView.initialUrl] (using the `file://` scheme), it represents the URL from which to read the web content.
///This URL must be a file-based URL (using the `file://` scheme).
///Specify the same value as the [WebView.initialUrl] parameter to prevent WebView from reading any other content.
///Specify a directory to give WebView permission to read additional files in the specified directory.
String? allowingReadAccessTo;
IOSInAppWebViewOptions(
{this.disallowOverScroll = false,
this.enableViewportScale = false,
@ -953,7 +959,10 @@ class IOSInAppWebViewOptions
this.pageZoom = 1.0,
this.limitsNavigationsToAppBoundDomains = false,
this.useOnNavigationResponse = false,
this.applePayAPIEnabled = false});
this.applePayAPIEnabled = false,
this.allowingReadAccessTo}) {
assert(allowingReadAccessTo == null || allowingReadAccessTo!.startsWith("file://"));
}
@override
Map<String, dynamic> toMap() {
@ -995,6 +1004,7 @@ class IOSInAppWebViewOptions
"limitsNavigationsToAppBoundDomains": limitsNavigationsToAppBoundDomains,
"useOnNavigationResponse": useOnNavigationResponse,
"applePayAPIEnabled": applePayAPIEnabled,
"allowingReadAccessTo": allowingReadAccessTo,
};
}
@ -1050,6 +1060,7 @@ class IOSInAppWebViewOptions
options.limitsNavigationsToAppBoundDomains = map["limitsNavigationsToAppBoundDomains"];
options.useOnNavigationResponse = map["useOnNavigationResponse"];
options.applePayAPIEnabled = map["applePayAPIEnabled"];
options.allowingReadAccessTo = map["allowingReadAccessTo"];
return options;
}