added getHtml method, updated android config, remove block on long press webview android, fixed other issues
This commit is contained in:
parent
6518697e55
commit
299042f828
383
.idea/workspace.xml
generated
383
.idea/workspace.xml
generated
@ -15,23 +15,41 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
|
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/example/assets/favicon.ico" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/CHANGELOG.md" beforeDir="false" afterPath="$PROJECT_DIR$/CHANGELOG.md" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/android/build.gradle" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/gradle.properties" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/AndroidManifest.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ChromeCustomTabs/ChromeCustomTabsActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ChromeCustomTabs/ChromeCustomTabsActivity.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabaseHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabaseHandler.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebView.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserActivity.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserFlutterPlugin.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserOptions.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebChromeClient.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebView.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/example/lib/chrome_safari_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/chrome_safari_example.screen.dart" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewClient.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InAppWebViewOptions.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InputAwareWebView.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InputAwareWebView.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/JavaScriptBridgeInterface.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/MyCookieManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/MyCookieManager.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/example/android/gradle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/example/android/gradle.properties" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/example/assets/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/assets/index.html" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/example/ios/Flutter/flutter_export_environment.sh" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Flutter/flutter_export_environment.sh" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/example/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/example/pubspec.yaml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/FlutterWebViewController.swift" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebView.swift" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" beforeDir="false" afterPath="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/channel_manager.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/channel_manager.dart" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/cookie_manager.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/cookie_manager.dart" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/in_app_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_browser.dart" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/lib/src/in_app_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_browser.dart" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/in_app_webview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_webview.dart" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/lib/src/in_app_webview.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/in_app_webview.dart" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/lib/src/types.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/types.dart" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/lib/src/webview_options.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/webview_options.dart" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<ignored path="$PROJECT_DIR$/.dart_tool/" />
|
<ignored path="$PROJECT_DIR$/.dart_tool/" />
|
||||||
<ignored path="$PROJECT_DIR$/.idea/" />
|
<ignored path="$PROJECT_DIR$/.idea/" />
|
||||||
@ -54,17 +72,26 @@
|
|||||||
<file pinned="false" current-in-tab="false">
|
<file pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="405">
|
<state relative-caret-position="336">
|
||||||
<caret line="27" column="92" selection-start-line="27" selection-start-column="92" selection-end-line="27" selection-end-column="92" />
|
<caret line="28" column="24" selection-start-line="28" selection-start-column="24" selection-end-line="28" selection-end-column="24" />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file pinned="false" current-in-tab="true">
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="423">
|
||||||
|
<caret line="49" column="46" selection-start-line="49" selection-start-column="46" selection-end-line="49" selection-end-column="46" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="296">
|
<state relative-caret-position="183">
|
||||||
<caret line="679" column="4" selection-start-line="679" selection-start-column="4" selection-end-line="679" selection-end-column="4" />
|
<caret line="114" column="101" selection-start-line="114" selection-start-column="87" selection-end-line="114" selection-end-column="101" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#0#17#0" expanded="true" />
|
<element signature="e#0#17#0" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
@ -73,22 +100,40 @@
|
|||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file pinned="false" current-in-tab="false">
|
<file pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="235">
|
<state relative-caret-position="142">
|
||||||
<caret line="424" column="64" selection-start-line="424" selection-start-column="64" selection-end-line="424" selection-end-column="64" />
|
<caret line="57" column="24" selection-start-line="57" selection-start-column="7" selection-end-line="57" selection-end-column="24" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#0#20#0" expanded="true" />
|
<element signature="e#0#17#0" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file pinned="false" current-in-tab="false">
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="888">
|
||||||
|
<caret line="79" column="11" selection-start-line="79" selection-start-column="11" selection-end-line="79" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="-107">
|
||||||
|
<caret line="8" column="36" selection-start-line="8" selection-start-column="36" selection-end-line="8" selection-end-column="36" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file pinned="false" current-in-tab="true">
|
||||||
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
|
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="-60">
|
<state relative-caret-position="294">
|
||||||
<caret line="85" column="43" selection-start-line="85" selection-start-column="43" selection-end-line="85" selection-end-column="43" />
|
<caret line="261" column="187" selection-start-line="259" selection-start-column="14" selection-end-line="261" selection-end-column="187" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#0#20#0" expanded="true" />
|
<element signature="e#0#20#0" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
@ -108,20 +153,6 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="FindInProjectRecents">
|
<component name="FindInProjectRecents">
|
||||||
<findStrings>
|
<findStrings>
|
||||||
<find>a</find>
|
|
||||||
<find>as</find>
|
|
||||||
<find>IABWebViewClient</find>
|
|
||||||
<find>clearCache</find>
|
|
||||||
<find>Auth</find>
|
|
||||||
<find>onReceivedHttpAuthRequestCallback</find>
|
|
||||||
<find>Protection</find>
|
|
||||||
<find>cast</find>
|
|
||||||
<find>clear</find>
|
|
||||||
<find>HttpAuthResponse</find>
|
|
||||||
<find>ClientCertResponse</find>
|
|
||||||
<find>onReceivedServerTrustAuthRequest</find>
|
|
||||||
<find>ServerTrustAuthResponse</find>
|
|
||||||
<find>certific</find>
|
|
||||||
<find>CER</find>
|
<find>CER</find>
|
||||||
<find>ServerTrustChallenge</find>
|
<find>ServerTrustChallenge</find>
|
||||||
<find>cONTENTMODE</find>
|
<find>cONTENTMODE</find>
|
||||||
@ -138,6 +169,20 @@
|
|||||||
<find>on</find>
|
<find>on</find>
|
||||||
<find>findAll</find>
|
<find>findAll</find>
|
||||||
<find>getFave</find>
|
<find>getFave</find>
|
||||||
|
<find>Uri</find>
|
||||||
|
<find>!= "an</find>
|
||||||
|
<find>_channel</find>
|
||||||
|
<find>getHtml</find>
|
||||||
|
<find>url</find>
|
||||||
|
<find>getOptions</find>
|
||||||
|
<find>gestureR</find>
|
||||||
|
<find>_dispose</find>
|
||||||
|
<find>dispose</find>
|
||||||
|
<find>Long</find>
|
||||||
|
<find>custom</find>
|
||||||
|
<find>scheme</find>
|
||||||
|
<find>useOnLoadResource</find>
|
||||||
|
<find>useShouldOverrideUrlLoading</find>
|
||||||
</findStrings>
|
</findStrings>
|
||||||
<replaceStrings>
|
<replaceStrings>
|
||||||
<replace>activity.getPreferences(0)</replace>
|
<replace>activity.getPreferences(0)</replace>
|
||||||
@ -175,7 +220,6 @@
|
|||||||
<option value="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" />
|
<option value="$PROJECT_DIR$/android/gradle/wrapper/gradle-wrapper.properties" />
|
||||||
<option value="$PROJECT_DIR$/example/android/app/build.gradle" />
|
<option value="$PROJECT_DIR$/example/android/app/build.gradle" />
|
||||||
<option value="$PROJECT_DIR$/example/android/gradle.properties" />
|
<option value="$PROJECT_DIR$/example/android/gradle.properties" />
|
||||||
<option value="$PROJECT_DIR$/android/build.gradle" />
|
|
||||||
<option value="$PROJECT_DIR$/example/android/build.gradle" />
|
<option value="$PROJECT_DIR$/example/android/build.gradle" />
|
||||||
<option value="$PROJECT_DIR$/example/assets/page-3.html" />
|
<option value="$PROJECT_DIR$/example/assets/page-3.html" />
|
||||||
<option value="$PROJECT_DIR$/example/assets/page-2.html" />
|
<option value="$PROJECT_DIR$/example/assets/page-2.html" />
|
||||||
@ -192,28 +236,29 @@
|
|||||||
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
|
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
|
||||||
<option value="$PROJECT_DIR$/example/lib/main.dart" />
|
<option value="$PROJECT_DIR$/example/lib/main.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/content_blocker.dart" />
|
<option value="$PROJECT_DIR$/lib/src/content_blocker.dart" />
|
||||||
<option value="$PROJECT_DIR$/example/assets/index.html" />
|
|
||||||
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
|
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/credentials_database.dart" />
|
<option value="$PROJECT_DIR$/lib/src/credentials_database.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
|
||||||
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
|
|
||||||
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
|
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
|
||||||
<option value="$PROJECT_DIR$/pubspec.yaml" />
|
|
||||||
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
|
|
||||||
<option value="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" />
|
|
||||||
<option value="$PROJECT_DIR$/lib/src/channel_manager.dart" />
|
<option value="$PROJECT_DIR$/lib/src/channel_manager.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/cookie_manager.dart" />
|
<option value="$PROJECT_DIR$/lib/src/cookie_manager.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" />
|
<option value="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" />
|
||||||
<option value="$PROJECT_DIR$/example/lib/chrome_safari_example.screen.dart" />
|
<option value="$PROJECT_DIR$/example/lib/chrome_safari_example.screen.dart" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
|
|
||||||
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
|
||||||
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
|
|
||||||
<option value="$PROJECT_DIR$/lib/src/types.dart" />
|
<option value="$PROJECT_DIR$/lib/src/types.dart" />
|
||||||
|
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
||||||
|
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
|
||||||
|
<option value="$PROJECT_DIR$/android/build.gradle" />
|
||||||
|
<option value="$PROJECT_DIR$/example/pubspec.yaml" />
|
||||||
|
<option value="$PROJECT_DIR$/pubspec.yaml" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
|
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
|
||||||
|
<option value="$PROJECT_DIR$/example/assets/index.html" />
|
||||||
|
<option value="$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js" />
|
||||||
|
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
|
||||||
|
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectFrameBounds" extendedState="6">
|
<component name="ProjectFrameBounds">
|
||||||
<option name="y" value="23" />
|
<option name="y" value="23" />
|
||||||
<option name="width" value="1920" />
|
<option name="width" value="1920" />
|
||||||
<option name="height" value="1057" />
|
<option name="height" value="1057" />
|
||||||
@ -235,33 +280,6 @@
|
|||||||
<select />
|
<select />
|
||||||
</subPane>
|
</subPane>
|
||||||
</pane>
|
</pane>
|
||||||
<pane id="ProjectPane">
|
|
||||||
<subPane>
|
|
||||||
<expand>
|
|
||||||
<path>
|
|
||||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
|
||||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
|
||||||
</path>
|
|
||||||
<path>
|
|
||||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
|
||||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
|
||||||
<item name="lib" type="462c0819:PsiDirectoryNode" />
|
|
||||||
</path>
|
|
||||||
<path>
|
|
||||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
|
||||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
|
||||||
<item name="lib" type="462c0819:PsiDirectoryNode" />
|
|
||||||
<item name="src" type="462c0819:PsiDirectoryNode" />
|
|
||||||
</path>
|
|
||||||
<path>
|
|
||||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
|
||||||
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
|
|
||||||
</path>
|
|
||||||
</expand>
|
|
||||||
<select />
|
|
||||||
</subPane>
|
|
||||||
</pane>
|
|
||||||
<pane id="PackagesPane" />
|
|
||||||
<pane id="AndroidView">
|
<pane id="AndroidView">
|
||||||
<subPane>
|
<subPane>
|
||||||
<expand>
|
<expand>
|
||||||
@ -291,6 +309,54 @@
|
|||||||
<select />
|
<select />
|
||||||
</subPane>
|
</subPane>
|
||||||
</pane>
|
</pane>
|
||||||
|
<pane id="ProjectPane">
|
||||||
|
<subPane>
|
||||||
|
<expand>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="android" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="assets" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="lib" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="lib" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="nodejs_server_test_auth_basic_and_ssl" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||||
|
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
|
||||||
|
</path>
|
||||||
|
</expand>
|
||||||
|
<select />
|
||||||
|
</subPane>
|
||||||
|
</pane>
|
||||||
|
<pane id="PackagesPane" />
|
||||||
</panes>
|
</panes>
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">
|
<component name="PropertiesComponent">
|
||||||
@ -310,13 +376,6 @@
|
|||||||
<property name="show.migrate.to.gradle.popup" value="false" />
|
<property name="show.migrate.to.gradle.popup" value="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
|
||||||
<recent name="$PROJECT_DIR$/example/assets" />
|
|
||||||
<recent name="$PROJECT_DIR$" />
|
|
||||||
<recent name="$PROJECT_DIR$/example" />
|
|
||||||
<recent name="$PROJECT_DIR$/example/assets/images" />
|
|
||||||
<recent name="$PROJECT_DIR$/android/libs" />
|
|
||||||
</key>
|
|
||||||
<key name="MoveFile.RECENT_KEYS">
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
<recent name="$PROJECT_DIR$/example/assets" />
|
<recent name="$PROJECT_DIR$/example/assets" />
|
||||||
<recent name="$PROJECT_DIR$/lib/src" />
|
<recent name="$PROJECT_DIR$/lib/src" />
|
||||||
@ -324,6 +383,13 @@
|
|||||||
<recent name="$PROJECT_DIR$/lib" />
|
<recent name="$PROJECT_DIR$/lib" />
|
||||||
<recent name="$PROJECT_DIR$/example/assets/images" />
|
<recent name="$PROJECT_DIR$/example/assets/images" />
|
||||||
</key>
|
</key>
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/example/assets" />
|
||||||
|
<recent name="$PROJECT_DIR$" />
|
||||||
|
<recent name="$PROJECT_DIR$/example" />
|
||||||
|
<recent name="$PROJECT_DIR$/example/assets/images" />
|
||||||
|
<recent name="$PROJECT_DIR$/android/libs" />
|
||||||
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunDashboard">
|
<component name="RunDashboard">
|
||||||
<option name="ruleStates">
|
<option name="ruleStates">
|
||||||
@ -442,10 +508,9 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<component name="ToolWindowManager">
|
||||||
<frame x="0" y="23" width="1920" height="1057" extended-state="6" />
|
<frame x="0" y="23" width="1920" height="1057" extended-state="6" />
|
||||||
<editor active="true" />
|
|
||||||
<layout>
|
<layout>
|
||||||
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.59067357" visible="true" weight="0.15867944" />
|
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.58835757" visible="true" weight="0.15867944" />
|
||||||
<window_info id="Structure" order="1" sideWeight="0.40932643" side_tool="true" weight="0.15867944" />
|
<window_info id="Structure" order="1" sideWeight="0.4116424" side_tool="true" visible="true" weight="0.15867944" />
|
||||||
<window_info id="Designer" order="2" />
|
<window_info id="Designer" order="2" />
|
||||||
<window_info id="Build Variants" order="3" side_tool="true" />
|
<window_info id="Build Variants" order="3" side_tool="true" />
|
||||||
<window_info id="Captures" order="4" side_tool="true" weight="0.32936507" />
|
<window_info id="Captures" order="4" side_tool="true" weight="0.32936507" />
|
||||||
@ -455,7 +520,7 @@
|
|||||||
<window_info id="Resources Explorer" order="8" />
|
<window_info id="Resources Explorer" order="8" />
|
||||||
<window_info anchor="bottom" id="Message" order="0" />
|
<window_info anchor="bottom" id="Message" order="0" />
|
||||||
<window_info anchor="bottom" id="Find" order="1" weight="0.32642487" />
|
<window_info anchor="bottom" id="Find" order="1" weight="0.32642487" />
|
||||||
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49307775" visible="true" weight="0.3253886" />
|
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49307775" visible="true" weight="0.5015544" />
|
||||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.34196892" />
|
<window_info anchor="bottom" id="Debug" order="3" weight="0.34196892" />
|
||||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||||
@ -491,29 +556,6 @@
|
|||||||
</ignored-roots>
|
</ignored-roots>
|
||||||
</component>
|
</component>
|
||||||
<component name="editorHistoryManager">
|
<component name="editorHistoryManager">
|
||||||
<entry file="file://$PROJECT_DIR$/example/assets/page-3.html" />
|
|
||||||
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/convert/json.dart" />
|
|
||||||
<entry file="file://$PROJECT_DIR$/example/assets/page-2.html">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="162">
|
|
||||||
<caret line="15" column="63" selection-start-line="15" selection-start-column="63" selection-end-line="15" selection-end-column="63" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/example/assets/page-1.html">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="104">
|
|
||||||
<caret line="15" column="63" selection-start-line="15" selection-start-column="63" selection-end-line="15" selection-end-column="63" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/android/build.gradle">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="256">
|
|
||||||
<caret line="25" column="1" lean-forward="true" selection-start-line="25" selection-start-column="1" selection-end-line="25" selection-end-column="1" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$USER_HOME$/flutter/packages/flutter/lib/src/widgets/platform_view.dart">
|
<entry file="file://$USER_HOME$/flutter/packages/flutter/lib/src/widgets/platform_view.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="-182">
|
<state relative-caret-position="-182">
|
||||||
@ -688,27 +730,6 @@
|
|||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="210">
|
|
||||||
<caret line="14" column="16" selection-start-line="14" selection-start-column="16" selection-end-line="14" selection-end-column="16" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="315">
|
|
||||||
<caret line="21" column="28" selection-start-line="21" selection-start-column="28" selection-end-line="22" selection-end-column="23" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="225">
|
|
||||||
<caret line="15" column="2" lean-forward="true" selection-start-line="15" selection-start-column="2" selection-end-line="15" selection-end-column="2" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/.gitignore">
|
<entry file="file://$PROJECT_DIR$/.gitignore">
|
||||||
<provider selected="true" editor-type-id="text-editor" />
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
</entry>
|
</entry>
|
||||||
@ -722,13 +743,6 @@
|
|||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="330">
|
|
||||||
<caret line="22" column="17" selection-start-line="22" selection-start-column="17" selection-end-line="22" selection-end-column="17" />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/example/lib/webview_example.screen.dart">
|
<entry file="file://$PROJECT_DIR$/example/lib/webview_example.screen.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="302">
|
<state relative-caret-position="302">
|
||||||
@ -785,30 +799,10 @@
|
|||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
|
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/core/uri.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="198">
|
<state relative-caret-position="15">
|
||||||
<caret line="168" column="6" selection-start-line="168" selection-start-column="6" selection-end-line="168" selection-end-column="6" />
|
<caret line="37" column="15" selection-start-line="37" selection-start-column="15" selection-end-line="37" selection-end-column="15" />
|
||||||
<folding>
|
|
||||||
<element signature="e#0#17#0" expanded="true" />
|
|
||||||
</folding>
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="401">
|
|
||||||
<caret line="426" column="51" selection-start-line="426" selection-start-column="51" selection-end-line="426" selection-end-column="51" />
|
|
||||||
<folding>
|
|
||||||
<element signature="e#0#20#0" expanded="true" />
|
|
||||||
</folding>
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="405">
|
|
||||||
<caret line="27" column="92" selection-start-line="27" selection-start-column="92" selection-end-line="27" selection-end-column="92" />
|
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
@ -822,26 +816,97 @@
|
|||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="-60">
|
<state relative-caret-position="76">
|
||||||
<caret line="85" column="43" selection-start-line="85" selection-start-column="43" selection-end-line="85" selection-end-column="43" />
|
<caret line="268" column="65" selection-start-line="268" selection-start-column="65" selection-end-line="268" selection-end-column="65" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#0#20#0" expanded="true" />
|
<element signature="e#0#20#0" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
<entry file="file://$PROJECT_DIR$/example/android/gradle.properties">
|
||||||
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/android/local.properties">
|
||||||
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/android/gradle.properties">
|
||||||
|
<provider selected="true" editor-type-id="text-editor" />
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="296">
|
<state relative-caret-position="141">
|
||||||
<caret line="679" column="4" selection-start-line="679" selection-start-column="4" selection-end-line="679" selection-end-column="4" />
|
<caret line="12" column="32" selection-start-line="12" selection-start-column="32" selection-end-line="12" selection-end-column="32" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="-107">
|
||||||
|
<caret line="8" column="36" selection-start-line="8" selection-start-column="36" selection-end-line="8" selection-end-column="36" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/android/build.gradle">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="256">
|
||||||
|
<caret line="25" selection-start-line="25" selection-end-line="25" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="336">
|
||||||
|
<caret line="28" column="24" selection-start-line="28" selection-start-column="24" selection-end-line="28" selection-end-column="24" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="888">
|
||||||
|
<caret line="79" column="11" selection-start-line="79" selection-start-column="11" selection-end-line="79" selection-end-column="11" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/nodejs_server_test_auth_basic_and_ssl/index.js">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="423">
|
||||||
|
<caret line="49" column="46" selection-start-line="49" selection-start-column="46" selection-end-line="49" selection-end-column="46" />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="142">
|
||||||
|
<caret line="57" column="24" selection-start-line="57" selection-start-column="7" selection-end-line="57" selection-end-column="24" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#0#17#0" expanded="true" />
|
<element signature="e#0#17#0" expanded="true" />
|
||||||
</folding>
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="183">
|
||||||
|
<caret line="114" column="101" selection-start-line="114" selection-start-column="87" selection-end-line="114" selection-end-column="101" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#17#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/example/lib/inline_example.screen.dart">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="294">
|
||||||
|
<caret line="261" column="187" selection-start-line="259" selection-start-column="14" selection-end-line="261" selection-end-column="187" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#20#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="masterDetails">
|
<component name="masterDetails">
|
||||||
<states>
|
<states>
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
- Added `HttpAuthCredentialDatabase` class
|
- Added `HttpAuthCredentialDatabase` class
|
||||||
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
|
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
|
||||||
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
|
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
|
||||||
|
- Added `getHtml` method
|
||||||
|
|
||||||
### BREAKING CHANGES
|
### BREAKING CHANGES
|
||||||
- Deleted `WebResourceRequest` class
|
- Deleted `WebResourceRequest` class
|
||||||
@ -34,6 +35,7 @@
|
|||||||
- Updated `onLoadResource` event
|
- Updated `onLoadResource` event
|
||||||
- Updated `CookieManager` class
|
- Updated `CookieManager` class
|
||||||
- WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSSafariOptions`
|
- WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSSafariOptions`
|
||||||
|
- Renamed `getFavicon` to `getFavicons`, now it returns a list of all favicons (`List<Favicon>`) found
|
||||||
|
|
||||||
## 1.2.1
|
## 1.2.1
|
||||||
|
|
||||||
|
@ -33,11 +33,34 @@ android {
|
|||||||
lintOptions {
|
lintOptions {
|
||||||
disable 'InvalidPackage'
|
disable 'InvalidPackage'
|
||||||
}
|
}
|
||||||
|
dependencies {
|
||||||
|
implementation 'androidx.webkit:webkit:1.0.0'
|
||||||
|
implementation 'androidx.browser:browser:1.0.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||||
|
implementation 'com.squareup.okhttp3:mockwebserver:3.11.0'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
afterEvaluate {
|
||||||
implementation 'androidx.webkit:webkit:1.0.0'
|
def containsEmbeddingDependencies = false
|
||||||
implementation 'androidx.browser:browser:1.0.0'
|
for (def configuration : configurations.all) {
|
||||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
for (def dependency : configuration.dependencies) {
|
||||||
implementation 'com.squareup.okhttp3:mockwebserver:3.11.0'
|
if (dependency.group == 'io.flutter' &&
|
||||||
}
|
dependency.name.startsWith('flutter_embedding') &&
|
||||||
|
dependency.isTransitive())
|
||||||
|
{
|
||||||
|
containsEmbeddingDependencies = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!containsEmbeddingDependencies) {
|
||||||
|
android {
|
||||||
|
dependencies {
|
||||||
|
def lifecycle_version = "1.1.1"
|
||||||
|
compileOnly "android.arch.lifecycle:common-java8:$lifecycle_version"
|
||||||
|
compileOnly "android.arch.lifecycle:runtime:$lifecycle_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
android.enableJetifier=true
|
|
||||||
android.useAndroidX=true
|
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
|
@ -1,9 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.pichillilorenzo.flutter_inappbrowser">
|
package="com.pichillilorenzo.flutter_inappbrowser">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<activity android:theme="@style/AppTheme" android:name=".InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
|
<activity android:theme="@style/AppTheme" android:name=".InAppBrowserActivity" android:configChanges="orientation|screenSize"></activity>
|
||||||
<activity android:theme="@style/ThemeTransparent" android:name=".ChromeCustomTabs.ChromeCustomTabsActivity" android:configChanges="orientation|screenSize"></activity>
|
<activity android:theme="@style/ThemeTransparent" android:name=".ChromeCustomTabs.ChromeCustomTabsActivity" android:configChanges="orientation|screenSize"></activity>
|
||||||
|
@ -36,7 +36,7 @@ public class ChromeCustomTabsActivity extends Activity {
|
|||||||
options = new ChromeCustomTabsOptions();
|
options = new ChromeCustomTabsOptions();
|
||||||
options.parse((HashMap<String, Object>) b.getSerializable("options"));
|
options.parse((HashMap<String, Object>) b.getSerializable("options"));
|
||||||
|
|
||||||
InAppBrowserFlutterPlugin.instance.chromeCustomTabsActivities.put(uuid, this);
|
InAppBrowserFlutterPlugin.inAppBrowser.chromeCustomTabsActivities.put(uuid, this);
|
||||||
|
|
||||||
customTabActivityHelper = new CustomTabActivityHelper();
|
customTabActivityHelper = new CustomTabActivityHelper();
|
||||||
builder = new CustomTabsIntent.Builder();
|
builder = new CustomTabsIntent.Builder();
|
||||||
@ -49,8 +49,8 @@ public class ChromeCustomTabsActivity extends Activity {
|
|||||||
|
|
||||||
Map<String, Object> obj = new HashMap<>();
|
Map<String, Object> obj = new HashMap<>();
|
||||||
obj.put("uuid", uuid);
|
obj.put("uuid", uuid);
|
||||||
InAppBrowserFlutterPlugin.instance.channel.invokeMethod("onChromeSafariBrowserOpened", obj);
|
InAppBrowserFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserOpened", obj);
|
||||||
InAppBrowserFlutterPlugin.instance.channel.invokeMethod("onChromeSafariBrowserLoaded", obj);
|
InAppBrowserFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserLoaded", obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareCustomTabs() {
|
private void prepareCustomTabs() {
|
||||||
@ -86,7 +86,7 @@ public class ChromeCustomTabsActivity extends Activity {
|
|||||||
finish();
|
finish();
|
||||||
Map<String, Object> obj = new HashMap<>();
|
Map<String, Object> obj = new HashMap<>();
|
||||||
obj.put("uuid", uuid);
|
obj.put("uuid", uuid);
|
||||||
InAppBrowserFlutterPlugin.instance.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
InAppBrowserFlutterPlugin.inAppBrowser.channel.invokeMethod("onChromeSafariBrowserClosed", obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,18 +7,16 @@ import android.util.Log;
|
|||||||
import android.webkit.WebResourceResponse;
|
import android.webkit.WebResourceResponse;
|
||||||
|
|
||||||
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
|
import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
|
||||||
|
import com.pichillilorenzo.flutter_inappbrowser.Util;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -163,8 +161,7 @@ public class ContentBlockerHandler {
|
|||||||
Response response = null;
|
Response response = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
response = Util.getUnsafeOkHttpClient().newCall(mRequest).execute();
|
||||||
response = webView.httpClient.newCall(mRequest).execute();
|
|
||||||
byte[] dataBytes = response.body().bytes();
|
byte[] dataBytes = response.body().bytes();
|
||||||
InputStream dataStream = new ByteArrayInputStream(dataBytes);
|
InputStream dataStream = new ByteArrayInputStream(dataBytes);
|
||||||
|
|
||||||
@ -195,7 +192,7 @@ public class ContentBlockerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException, MalformedURLException {
|
public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException, MalformedURLException {
|
||||||
ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromUrl(webView, url);
|
ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromUrl(url);
|
||||||
return checkUrl(webView, url, responseResourceType);
|
return checkUrl(webView, url, responseResourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +201,7 @@ public class ContentBlockerHandler {
|
|||||||
return checkUrl(webView, url, responseResourceType);
|
return checkUrl(webView, url, responseResourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentBlockerTriggerResourceType getResourceTypeFromUrl(InAppWebView webView, String url) {
|
public ContentBlockerTriggerResourceType getResourceTypeFromUrl(String url) {
|
||||||
ContentBlockerTriggerResourceType responseResourceType = ContentBlockerTriggerResourceType.RAW;
|
ContentBlockerTriggerResourceType responseResourceType = ContentBlockerTriggerResourceType.RAW;
|
||||||
|
|
||||||
if (url.startsWith("http://") || url.startsWith("https://")) {
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||||
@ -212,7 +209,7 @@ public class ContentBlockerHandler {
|
|||||||
Request mRequest = new Request.Builder().url(url).head().build();
|
Request mRequest = new Request.Builder().url(url).head().build();
|
||||||
Response response = null;
|
Response response = null;
|
||||||
try {
|
try {
|
||||||
response = webView.httpClient.newCall(mRequest).execute();
|
response = Util.getUnsafeOkHttpClient().newCall(mRequest).execute();
|
||||||
|
|
||||||
if (response.header("content-type") != null) {
|
if (response.header("content-type") != null) {
|
||||||
String[] contentTypeSplitted = response.header("content-type").split(";");
|
String[] contentTypeSplitted = response.header("content-type").split(";");
|
||||||
|
@ -116,4 +116,8 @@ public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -289,10 +289,6 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||||||
result.success(false);
|
result.success(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "dispose":
|
|
||||||
dispose();
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
result.notImplemented();
|
result.notImplemented();
|
||||||
}
|
}
|
||||||
@ -300,10 +296,12 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
if (webView != null) {
|
if (webView != null) {
|
||||||
webView.setWebChromeClient(new WebChromeClient());
|
webView.setWebChromeClient(new WebChromeClient());
|
||||||
webView.setWebViewClient(new WebViewClient() {
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
|
webView.dispose();
|
||||||
webView.destroy();
|
webView.destroy();
|
||||||
webView = null;
|
webView = null;
|
||||||
}
|
}
|
||||||
@ -324,4 +322,12 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||||||
webView.unlockInputConnection();
|
webView.unlockInputConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onFlutterViewAttached(View flutterView) {
|
||||||
|
webView.setContainerView(flutterView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFlutterViewDetached() {
|
||||||
|
webView.setContainerView(null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,739 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.pichillilorenzo.flutter_inappbrowser;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.provider.Browser;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.webkit.WebViewClient;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.ChromeCustomTabsActivity;
|
||||||
|
import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.CustomTabActivityHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger;
|
||||||
|
import io.flutter.plugin.common.MethodCall;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
import io.flutter.plugin.common.MethodChannel.Result;
|
||||||
|
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InAppBrowser
|
||||||
|
*/
|
||||||
|
public class InAppBrowser implements MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
|
public Registrar registrar;
|
||||||
|
public MethodChannel channel;
|
||||||
|
public Map<String, InAppBrowserActivity> webViewActivities = new HashMap<>();
|
||||||
|
public Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>();
|
||||||
|
|
||||||
|
protected static final String LOG_TAG = "IABFlutterPlugin";
|
||||||
|
|
||||||
|
public InAppBrowser(Registrar r) {
|
||||||
|
registrar = r;
|
||||||
|
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
|
||||||
|
channel.setMethodCallHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMethodCall(final MethodCall call, final Result result) {
|
||||||
|
String source;
|
||||||
|
String urlFile;
|
||||||
|
final Activity activity = registrar.activity();
|
||||||
|
final String uuid = (String) call.argument("uuid");
|
||||||
|
|
||||||
|
switch (call.method) {
|
||||||
|
case "open":
|
||||||
|
boolean isData = (boolean) call.argument("isData");
|
||||||
|
if (!isData) {
|
||||||
|
final String url_final = (String) call.argument("url");
|
||||||
|
|
||||||
|
final boolean useChromeSafariBrowser = (boolean) call.argument("useChromeSafariBrowser");
|
||||||
|
|
||||||
|
final Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
||||||
|
|
||||||
|
Log.d(LOG_TAG, "use Chrome Custom Tabs = " + useChromeSafariBrowser);
|
||||||
|
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
if (useChromeSafariBrowser) {
|
||||||
|
|
||||||
|
final String uuidFallback = (String) call.argument("uuidFallback");
|
||||||
|
|
||||||
|
final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
||||||
|
|
||||||
|
final HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
|
||||||
|
|
||||||
|
open(activity, uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String url = url_final;
|
||||||
|
|
||||||
|
final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
||||||
|
|
||||||
|
final boolean isLocalFile = (boolean) call.argument("isLocalFile");
|
||||||
|
final boolean openWithSystemBrowser = (boolean) call.argument("openWithSystemBrowser");
|
||||||
|
|
||||||
|
if (isLocalFile) {
|
||||||
|
// check if the asset file exists
|
||||||
|
try {
|
||||||
|
url = Util.getUrlAsset(registrar, url);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
result.error(LOG_TAG, url + " asset file cannot be found!", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SYSTEM
|
||||||
|
if (openWithSystemBrowser) {
|
||||||
|
Log.d(LOG_TAG, "in system");
|
||||||
|
openExternal(activity, url, result);
|
||||||
|
} else {
|
||||||
|
//Load the dialer
|
||||||
|
if (url.startsWith(WebView.SCHEME_TEL)) {
|
||||||
|
try {
|
||||||
|
Log.d(LOG_TAG, "loading in dialer");
|
||||||
|
Intent intent = new Intent(Intent.ACTION_DIAL);
|
||||||
|
intent.setData(Uri.parse(url));
|
||||||
|
activity.startActivity(intent);
|
||||||
|
} catch (android.content.ActivityNotFoundException e) {
|
||||||
|
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// load in InAppBrowser
|
||||||
|
else {
|
||||||
|
Log.d(LOG_TAG, "loading in InAppBrowser");
|
||||||
|
open(activity, uuid, null, url, options, headers, false, null, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
||||||
|
String data = (String) call.argument("data");
|
||||||
|
String mimeType = (String) call.argument("mimeType");
|
||||||
|
String encoding = (String) call.argument("encoding");
|
||||||
|
String baseUrl = (String) call.argument("baseUrl");
|
||||||
|
openData(activity, uuid, options, data, mimeType, encoding, baseUrl);
|
||||||
|
result.success(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "getUrl":
|
||||||
|
result.success(getUrl(uuid));
|
||||||
|
break;
|
||||||
|
case "getTitle":
|
||||||
|
result.success(getTitle(uuid));
|
||||||
|
break;
|
||||||
|
case "getProgress":
|
||||||
|
result.success(getProgress(uuid));
|
||||||
|
break;
|
||||||
|
case "loadUrl":
|
||||||
|
loadUrl(uuid, (String) call.argument("url"), (Map<String, String>) call.argument("headers"), result);
|
||||||
|
break;
|
||||||
|
case "postUrl":
|
||||||
|
postUrl(uuid, (String) call.argument("url"), (byte[]) call.argument("postData"), result);
|
||||||
|
break;
|
||||||
|
case "loadData":
|
||||||
|
{
|
||||||
|
String data = (String) call.argument("data");
|
||||||
|
String mimeType = (String) call.argument("mimeType");
|
||||||
|
String encoding = (String) call.argument("encoding");
|
||||||
|
String baseUrl = (String) call.argument("baseUrl");
|
||||||
|
loadData(uuid, data, mimeType, encoding, baseUrl, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "loadFile":
|
||||||
|
loadFile(uuid, (String) call.argument("url"), (Map<String, String>) call.argument("headers"), result);
|
||||||
|
break;
|
||||||
|
case "close":
|
||||||
|
close(activity, uuid, result);
|
||||||
|
break;
|
||||||
|
case "injectScriptCode":
|
||||||
|
source = (String) call.argument("source");
|
||||||
|
injectScriptCode(uuid, source, result);
|
||||||
|
break;
|
||||||
|
case "injectScriptFile":
|
||||||
|
urlFile = (String) call.argument("urlFile");
|
||||||
|
injectScriptFile(uuid, urlFile);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "injectStyleCode":
|
||||||
|
source = (String) call.argument("source");
|
||||||
|
injectStyleCode(uuid, source);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "injectStyleFile":
|
||||||
|
urlFile = (String) call.argument("urlFile");
|
||||||
|
injectStyleFile(uuid, urlFile);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "show":
|
||||||
|
show(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "hide":
|
||||||
|
hide(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "reload":
|
||||||
|
reload(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "goBack":
|
||||||
|
goBack(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "canGoBack":
|
||||||
|
result.success(canGoBack(uuid));
|
||||||
|
break;
|
||||||
|
case "goForward":
|
||||||
|
goForward(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "canGoForward":
|
||||||
|
result.success(canGoForward(uuid));
|
||||||
|
break;
|
||||||
|
case "goBackOrForward":
|
||||||
|
goBackOrForward(uuid, (Integer) call.argument("steps"));
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "canGoBackOrForward":
|
||||||
|
result.success(canGoBackOrForward(uuid, (Integer) call.argument("steps")));
|
||||||
|
break;
|
||||||
|
case "stopLoading":
|
||||||
|
stopLoading(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "isLoading":
|
||||||
|
result.success(isLoading(uuid));
|
||||||
|
break;
|
||||||
|
case "isHidden":
|
||||||
|
result.success(isHidden(uuid));
|
||||||
|
break;
|
||||||
|
case "takeScreenshot":
|
||||||
|
result.success(takeScreenshot(uuid));
|
||||||
|
break;
|
||||||
|
case "setOptions":
|
||||||
|
{
|
||||||
|
String optionsType = (String) call.argument("optionsType");
|
||||||
|
switch (optionsType){
|
||||||
|
case "InAppBrowserOptions":
|
||||||
|
InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions();
|
||||||
|
HashMap<String, Object> inAppBrowserOptionsMap = (HashMap<String, Object>) call.argument("options");
|
||||||
|
inAppBrowserOptions.parse(inAppBrowserOptionsMap);
|
||||||
|
setOptions(uuid, inAppBrowserOptions, inAppBrowserOptionsMap);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.error(LOG_TAG, "Options " + optionsType + " not available.", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "getOptions":
|
||||||
|
result.success(getOptions(uuid));
|
||||||
|
break;
|
||||||
|
case "getCopyBackForwardList":
|
||||||
|
result.success(getCopyBackForwardList(uuid));
|
||||||
|
break;
|
||||||
|
case "startSafeBrowsing":
|
||||||
|
startSafeBrowsing(uuid, result);
|
||||||
|
break;
|
||||||
|
case "setSafeBrowsingWhitelist":
|
||||||
|
setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result);
|
||||||
|
break;
|
||||||
|
case "clearCache":
|
||||||
|
clearCache(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "clearSslPreferences":
|
||||||
|
clearSslPreferences(uuid);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "clearClientCertPreferences":
|
||||||
|
clearClientCertPreferences(uuid, result);
|
||||||
|
break;
|
||||||
|
case "findAllAsync":
|
||||||
|
String find = (String) call.argument("find");
|
||||||
|
findAllAsync(uuid, find);
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "findNext":
|
||||||
|
Boolean forward = (Boolean) call.argument("forward");
|
||||||
|
findNext(uuid, forward, result);
|
||||||
|
break;
|
||||||
|
case "clearMatches":
|
||||||
|
clearMatches(uuid, result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.notImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectScriptCode(String uuid, String source, final Result result) {
|
||||||
|
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
inAppBrowserActivity.injectScriptCode(source, result);
|
||||||
|
} else {
|
||||||
|
Log.d(LOG_TAG, "webView is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectScriptFile(String uuid, String urlFile) {
|
||||||
|
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
inAppBrowserActivity.injectScriptFile(urlFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectStyleCode(String uuid, String source) {
|
||||||
|
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
inAppBrowserActivity.injectStyleCode(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectStyleFile(String uuid, String urlFile) {
|
||||||
|
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
inAppBrowserActivity.injectStyleFile(urlFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMimeType(String url) {
|
||||||
|
String type = null;
|
||||||
|
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
|
||||||
|
if (extension != null) {
|
||||||
|
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a new browser with the specified URL.
|
||||||
|
*
|
||||||
|
* @param url the url to load.
|
||||||
|
* @param result
|
||||||
|
* @return "" if ok, or error message.
|
||||||
|
*/
|
||||||
|
public void openExternal(Activity activity, String url, Result result) {
|
||||||
|
try {
|
||||||
|
Intent intent;
|
||||||
|
intent = new Intent(Intent.ACTION_VIEW);
|
||||||
|
// Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
|
||||||
|
// Adding the MIME type to http: URLs causes them to not be handled by the downloader.
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
if ("file".equals(uri.getScheme())) {
|
||||||
|
intent.setDataAndType(uri, getMimeType(url));
|
||||||
|
} else {
|
||||||
|
intent.setData(uri);
|
||||||
|
}
|
||||||
|
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
|
||||||
|
// CB-10795: Avoid circular loops by preventing it from opening in the current app
|
||||||
|
this.openExternalExcludeCurrentApp(activity, intent);
|
||||||
|
result.success(true);
|
||||||
|
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
|
||||||
|
} catch (java.lang.RuntimeException e) {
|
||||||
|
Log.d(LOG_TAG, url + " cannot be opened: " + e.toString());
|
||||||
|
result.error(LOG_TAG, url + " cannot be opened!", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the intent, providing a chooser that excludes the current app to avoid
|
||||||
|
* circular loops.
|
||||||
|
*/
|
||||||
|
private void openExternalExcludeCurrentApp(Activity activity, Intent intent) {
|
||||||
|
String currentPackage = activity.getPackageName();
|
||||||
|
boolean hasCurrentPackage = false;
|
||||||
|
PackageManager pm = activity.getPackageManager();
|
||||||
|
List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
|
||||||
|
ArrayList<Intent> targetIntents = new ArrayList<Intent>();
|
||||||
|
for (ResolveInfo ri : activities) {
|
||||||
|
if (!currentPackage.equals(ri.activityInfo.packageName)) {
|
||||||
|
Intent targetIntent = (Intent) intent.clone();
|
||||||
|
targetIntent.setPackage(ri.activityInfo.packageName);
|
||||||
|
targetIntents.add(targetIntent);
|
||||||
|
} else {
|
||||||
|
hasCurrentPackage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the current app package isn't a target for this URL, then use
|
||||||
|
// the normal launch behavior
|
||||||
|
if (!hasCurrentPackage || targetIntents.size() == 0) {
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
// If there's only one possible intent, launch it directly
|
||||||
|
else if (targetIntents.size() == 1) {
|
||||||
|
activity.startActivity(targetIntents.get(0));
|
||||||
|
}
|
||||||
|
// Otherwise, show a custom chooser without the current app listed
|
||||||
|
else if (targetIntents.size() > 0) {
|
||||||
|
Intent chooser = Intent.createChooser(targetIntents.remove(targetIntents.size() - 1), null);
|
||||||
|
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
|
||||||
|
activity.startActivity(chooser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Activity activity, String uuid, String uuidFallback, String url, HashMap<String, Object> options, Map<String, String> headers, boolean useChromeSafariBrowser, HashMap<String, Object> optionsFallback, Result result) {
|
||||||
|
|
||||||
|
Intent intent = null;
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
extras.putString("fromActivity", activity.getClass().getName());
|
||||||
|
extras.putString("url", url);
|
||||||
|
extras.putBoolean("isData", false);
|
||||||
|
extras.putString("uuid", uuid);
|
||||||
|
extras.putSerializable("options", options);
|
||||||
|
extras.putSerializable("headers", (Serializable) headers);
|
||||||
|
|
||||||
|
if (useChromeSafariBrowser && CustomTabActivityHelper.isAvailable(activity)) {
|
||||||
|
intent = new Intent(activity, ChromeCustomTabsActivity.class);
|
||||||
|
}
|
||||||
|
// check for webview fallback
|
||||||
|
else if (useChromeSafariBrowser && !CustomTabActivityHelper.isAvailable(activity) && !uuidFallback.isEmpty()) {
|
||||||
|
Log.d(LOG_TAG, "WebView fallback declared.");
|
||||||
|
// overwrite with extras fallback parameters
|
||||||
|
extras.putString("uuid", uuidFallback);
|
||||||
|
if (optionsFallback != null)
|
||||||
|
extras.putSerializable("options", optionsFallback);
|
||||||
|
else
|
||||||
|
extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap());
|
||||||
|
extras.putSerializable("headers", (Serializable) headers);
|
||||||
|
intent = new Intent(activity, InAppBrowserActivity.class);
|
||||||
|
}
|
||||||
|
// native webview
|
||||||
|
else if (!useChromeSafariBrowser) {
|
||||||
|
intent = new Intent(activity, InAppBrowserActivity.class);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.d(LOG_TAG, "No WebView fallback declared.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent != null) {
|
||||||
|
intent.putExtras(extras);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
result.success(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.error(LOG_TAG, "No WebView fallback declared.", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl) {
|
||||||
|
Intent intent = new Intent(activity, InAppBrowserActivity.class);
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
|
||||||
|
extras.putBoolean("isData", true);
|
||||||
|
extras.putString("uuid", uuid);
|
||||||
|
extras.putSerializable("options", options);
|
||||||
|
extras.putString("data", data);
|
||||||
|
extras.putString("mimeType", mimeType);
|
||||||
|
extras.putString("encoding", encoding);
|
||||||
|
extras.putString("baseUrl", baseUrl);
|
||||||
|
|
||||||
|
intent.putExtras(extras);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUrl(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.getUrl();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTitle(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.getWebViewTitle();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getProgress(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.getProgress();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadUrl(String uuid, String url, Map<String, String> headers, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
if (headers != null)
|
||||||
|
inAppBrowserActivity.loadUrl(url, headers, result);
|
||||||
|
else
|
||||||
|
inAppBrowserActivity.loadUrl(url, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void postUrl(String uuid, String url, byte[] postData, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.postUrl(url, postData, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadData(String uuid, String data, String mimeType, String encoding, String baseUrl, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.loadData(data, mimeType, encoding, baseUrl, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFile(String uuid, String url, Map<String, String> headers, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
if (headers != null)
|
||||||
|
inAppBrowserActivity.loadFile(url, headers, result);
|
||||||
|
else
|
||||||
|
inAppBrowserActivity.loadFile(url, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoading(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.isLoading();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHidden(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.isHidden;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopLoading(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.stopLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void goBack(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canGoBack(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.canGoBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void goForward(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.goForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canGoForward(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.canGoForward();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void goBackOrForward(String uuid, int steps) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.goBackOrForward(steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canGoBackOrForward(String uuid, int steps) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.canGoBackOrForward(steps);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(Activity activity, final String uuid, final Result result) {
|
||||||
|
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null) {
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
Map<String, Object> obj = new HashMap<>();
|
||||||
|
obj.put("uuid", uuid);
|
||||||
|
channel.invokeMethod("onExit", obj);
|
||||||
|
|
||||||
|
// The JS protects against multiple calls, so this should happen only when
|
||||||
|
// close() is called by other native code.
|
||||||
|
if (inAppBrowserActivity == null) {
|
||||||
|
if (result != null) {
|
||||||
|
result.success(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inAppBrowserActivity.webView.setWebViewClient(new WebViewClient() {
|
||||||
|
// NB: wait for about:blank before dismissing
|
||||||
|
public void onPageFinished(WebView view, String url) {
|
||||||
|
inAppBrowserActivity.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// NB: From SDK 19: "If you call methods on WebView from any thread
|
||||||
|
// other than your app's UI thread, it can cause unexpected results."
|
||||||
|
// http://developer.android.com/guide/webapps/migrating.html#Threads
|
||||||
|
inAppBrowserActivity.webView.loadUrl("about:blank");
|
||||||
|
if (result != null) {
|
||||||
|
result.success(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (result != null) {
|
||||||
|
result.success(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] takeScreenshot(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.takeScreenshot();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOptions(String uuid, InAppBrowserOptions options, HashMap<String, Object> optionsMap) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.setOptions(options, optionsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, Object> getOptions(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.getOptions();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, Object> getCopyBackForwardList(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
return inAppBrowserActivity.getCopyBackForwardList();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSafeBrowsing(String uuid, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.startSafeBrowsing(result);
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSafeBrowsingWhitelist(String uuid, List<String> hosts, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result);
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCache(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.clearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSslPreferences(String uuid) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.clearSslPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearClientCertPreferences(String uuid, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.clearClientCertPreferences(result);
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findAllAsync(String uuid, String find) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.findAllAsync(find);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findNext(String uuid, Boolean forward, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.findNext(forward, result);
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearMatches(String uuid, Result result) {
|
||||||
|
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||||
|
if (inAppBrowserActivity != null)
|
||||||
|
inAppBrowserActivity.clearMatches(result);
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
for ( InAppBrowserActivity activity : webViewActivities.values()) {
|
||||||
|
activity.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.pichillilorenzo.flutter_inappbrowser;
|
package com.pichillilorenzo.flutter_inappbrowser;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@ -18,6 +17,9 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.webkit.WebChromeClient;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
|
|
||||||
@ -26,13 +28,10 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebViewOptions
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.flutter.app.FlutterActivity;
|
|
||||||
import io.flutter.app.FlutterApplication;
|
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
public class InAppBrowserActivity extends AppCompatActivity {
|
public class InAppBrowserActivity extends AppCompatActivity {
|
||||||
@ -71,7 +70,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||||||
webViewOptions.parse(optionsMap);
|
webViewOptions.parse(optionsMap);
|
||||||
webView.options = webViewOptions;
|
webView.options = webViewOptions;
|
||||||
|
|
||||||
InAppBrowserFlutterPlugin.instance.webViewActivities.put(uuid, this);
|
InAppBrowserFlutterPlugin.inAppBrowser.webViewActivities.put(uuid, this);
|
||||||
|
|
||||||
actionBar = getSupportActionBar();
|
actionBar = getSupportActionBar();
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
Map<String, Object> obj = new HashMap<>();
|
Map<String, Object> obj = new HashMap<>();
|
||||||
obj.put("uuid", uuid);
|
obj.put("uuid", uuid);
|
||||||
InAppBrowserFlutterPlugin.instance.channel.invokeMethod("onBrowserCreated", obj);
|
InAppBrowserFlutterPlugin.inAppBrowser.channel.invokeMethod("onBrowserCreated", obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +256,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||||||
if (canGoBack())
|
if (canGoBack())
|
||||||
goBack();
|
goBack();
|
||||||
else if (options.closeOnCannotGoBack)
|
else if (options.closeOnCannotGoBack)
|
||||||
InAppBrowserFlutterPlugin.instance.close(this, uuid, null);
|
InAppBrowserFlutterPlugin.inAppBrowser.close(this, uuid, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onKeyDown(keyCode, event);
|
return super.onKeyDown(keyCode, event);
|
||||||
@ -356,7 +355,7 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void closeButtonClicked(MenuItem item) {
|
public void closeButtonClicked(MenuItem item) {
|
||||||
InAppBrowserFlutterPlugin.instance.close(this, uuid, null);
|
InAppBrowserFlutterPlugin.inAppBrowser.close(this, uuid, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] takeScreenshot() {
|
public byte[] takeScreenshot() {
|
||||||
@ -522,4 +521,18 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||||||
else
|
else
|
||||||
result.success(false);
|
result.success(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
if (webView != null) {
|
||||||
|
webView.setWebChromeClient(new WebChromeClient());
|
||||||
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
|
public void onPageFinished(WebView view, String url) {
|
||||||
|
webView.dispose();
|
||||||
|
webView.destroy();
|
||||||
|
webView = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
webView.loadUrl("about:blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,754 +1,65 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.pichillilorenzo.flutter_inappbrowser;
|
package com.pichillilorenzo.flutter_inappbrowser;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.provider.Browser;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.webkit.MimeTypeMap;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.webkit.WebViewClient;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.ChromeCustomTabsActivity;
|
|
||||||
import com.pichillilorenzo.flutter_inappbrowser.ChromeCustomTabs.CustomTabActivityHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.flutter.plugin.common.MethodCall;
|
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
import io.flutter.plugin.common.PluginRegistry;
|
||||||
import io.flutter.plugin.common.MethodChannel.Result;
|
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||||
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
|
||||||
|
|
||||||
/**
|
public class InAppBrowserFlutterPlugin implements FlutterPlugin {
|
||||||
* InAppBrowserFlutterPlugin
|
public PluginRegistry.Registrar registrar;
|
||||||
*/
|
|
||||||
public class InAppBrowserFlutterPlugin implements MethodCallHandler {
|
|
||||||
|
|
||||||
public static InAppBrowserFlutterPlugin instance;
|
|
||||||
public Registrar registrar;
|
|
||||||
public MethodChannel channel;
|
public MethodChannel channel;
|
||||||
public Map<String, InAppBrowserActivity> webViewActivities = new HashMap<>();
|
|
||||||
public Map<String, ChromeCustomTabsActivity> chromeCustomTabsActivities = new HashMap<>();
|
|
||||||
|
|
||||||
protected static final String LOG_TAG = "IABFlutterPlugin";
|
protected static final String LOG_TAG = "InAppBrowserFlutterPlugin";
|
||||||
|
|
||||||
public InAppBrowserFlutterPlugin(Registrar r) {
|
public static InAppBrowser inAppBrowser;
|
||||||
registrar = r;
|
public static MyCookieManager myCookieManager;
|
||||||
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser");
|
public static CredentialDatabaseHandler credentialDatabaseHandler;
|
||||||
channel.setMethodCallHandler(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public InAppBrowserFlutterPlugin() {}
|
||||||
* Plugin registration.
|
|
||||||
*/
|
|
||||||
public static void registerWith(Registrar registrar) {
|
|
||||||
Activity activity = registrar.activity();
|
|
||||||
// registrar.activity() may return null because of Flutter's background execution feature
|
|
||||||
// described here: https://medium.com/flutter-io/executing-dart-in-the-background-with-flutter-plugins-and-geofencing-2b3e40a1a124
|
|
||||||
if (activity != null) {
|
|
||||||
instance = new InAppBrowserFlutterPlugin(registrar);
|
|
||||||
|
|
||||||
new MyCookieManager(registrar);
|
public static void registerWith(PluginRegistry.Registrar registrar) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
inAppBrowser = new InAppBrowser(registrar);
|
||||||
new CredentialDatabaseHandler(registrar);
|
|
||||||
}
|
|
||||||
|
|
||||||
registrar
|
registrar
|
||||||
.platformViewRegistry()
|
.platformViewRegistry()
|
||||||
.registerViewFactory(
|
.registerViewFactory(
|
||||||
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, registrar.view()));
|
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar, registrar.view()));
|
||||||
|
new MyCookieManager(registrar);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
new CredentialDatabaseHandler(registrar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMethodCall(final MethodCall call, final Result result) {
|
public void onAttachedToEngine(FlutterPluginBinding binding) {
|
||||||
String source;
|
//BinaryMessenger messenger = binding.getFlutterEngine().getDartExecutor();
|
||||||
String urlFile;
|
inAppBrowser = new InAppBrowser(registrar);
|
||||||
final Activity activity = registrar.activity();
|
binding
|
||||||
final String uuid = (String) call.argument("uuid");
|
.getFlutterEngine()
|
||||||
|
.getPlatformViewsController()
|
||||||
switch (call.method) {
|
.getRegistry()
|
||||||
case "open":
|
.registerViewFactory(
|
||||||
boolean isData = (boolean) call.argument("isData");
|
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(registrar,null));
|
||||||
if (!isData) {
|
myCookieManager = new MyCookieManager(registrar);
|
||||||
final String url_final = (String) call.argument("url");
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
credentialDatabaseHandler = new CredentialDatabaseHandler(registrar);
|
||||||
final boolean useChromeSafariBrowser = (boolean) call.argument("useChromeSafariBrowser");
|
|
||||||
|
|
||||||
final Map<String, String> headers = (Map<String, String>) call.argument("headers");
|
|
||||||
|
|
||||||
Log.d(LOG_TAG, "use Chrome Custom Tabs = " + useChromeSafariBrowser);
|
|
||||||
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
if (useChromeSafariBrowser) {
|
|
||||||
|
|
||||||
final String uuidFallback = (String) call.argument("uuidFallback");
|
|
||||||
|
|
||||||
final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
|
||||||
|
|
||||||
final HashMap<String, Object> optionsFallback = (HashMap<String, Object>) call.argument("optionsFallback");
|
|
||||||
|
|
||||||
open(activity, uuid, uuidFallback, url_final, options, headers, true, optionsFallback, result);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
String url = url_final;
|
|
||||||
|
|
||||||
final HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
|
||||||
|
|
||||||
final boolean isLocalFile = (boolean) call.argument("isLocalFile");
|
|
||||||
final boolean openWithSystemBrowser = (boolean) call.argument("openWithSystemBrowser");
|
|
||||||
|
|
||||||
if (isLocalFile) {
|
|
||||||
// check if the asset file exists
|
|
||||||
try {
|
|
||||||
url = Util.getUrlAsset(registrar, url);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
result.error(LOG_TAG, url + " asset file cannot be found!", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SYSTEM
|
|
||||||
if (openWithSystemBrowser) {
|
|
||||||
Log.d(LOG_TAG, "in system");
|
|
||||||
openExternal(activity, url, result);
|
|
||||||
} else {
|
|
||||||
//Load the dialer
|
|
||||||
if (url.startsWith(WebView.SCHEME_TEL)) {
|
|
||||||
try {
|
|
||||||
Log.d(LOG_TAG, "loading in dialer");
|
|
||||||
Intent intent = new Intent(Intent.ACTION_DIAL);
|
|
||||||
intent.setData(Uri.parse(url));
|
|
||||||
activity.startActivity(intent);
|
|
||||||
} catch (android.content.ActivityNotFoundException e) {
|
|
||||||
Log.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// load in InAppBrowserFlutterPlugin
|
|
||||||
else {
|
|
||||||
Log.d(LOG_TAG, "loading in InAppBrowserFlutterPlugin");
|
|
||||||
open(activity, uuid, null, url, options, headers, false, null, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
HashMap<String, Object> options = (HashMap<String, Object>) call.argument("options");
|
|
||||||
String data = (String) call.argument("data");
|
|
||||||
String mimeType = (String) call.argument("mimeType");
|
|
||||||
String encoding = (String) call.argument("encoding");
|
|
||||||
String baseUrl = (String) call.argument("baseUrl");
|
|
||||||
openData(activity, uuid, options, data, mimeType, encoding, baseUrl);
|
|
||||||
result.success(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "getUrl":
|
|
||||||
result.success(getUrl(uuid));
|
|
||||||
break;
|
|
||||||
case "getTitle":
|
|
||||||
result.success(getTitle(uuid));
|
|
||||||
break;
|
|
||||||
case "getProgress":
|
|
||||||
result.success(getProgress(uuid));
|
|
||||||
break;
|
|
||||||
case "loadUrl":
|
|
||||||
loadUrl(uuid, (String) call.argument("url"), (Map<String, String>) call.argument("headers"), result);
|
|
||||||
break;
|
|
||||||
case "postUrl":
|
|
||||||
postUrl(uuid, (String) call.argument("url"), (byte[]) call.argument("postData"), result);
|
|
||||||
break;
|
|
||||||
case "loadData":
|
|
||||||
{
|
|
||||||
String data = (String) call.argument("data");
|
|
||||||
String mimeType = (String) call.argument("mimeType");
|
|
||||||
String encoding = (String) call.argument("encoding");
|
|
||||||
String baseUrl = (String) call.argument("baseUrl");
|
|
||||||
loadData(uuid, data, mimeType, encoding, baseUrl, result);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "loadFile":
|
|
||||||
loadFile(uuid, (String) call.argument("url"), (Map<String, String>) call.argument("headers"), result);
|
|
||||||
break;
|
|
||||||
case "close":
|
|
||||||
close(activity, uuid, result);
|
|
||||||
break;
|
|
||||||
case "injectScriptCode":
|
|
||||||
source = (String) call.argument("source");
|
|
||||||
injectScriptCode(uuid, source, result);
|
|
||||||
break;
|
|
||||||
case "injectScriptFile":
|
|
||||||
urlFile = (String) call.argument("urlFile");
|
|
||||||
injectScriptFile(uuid, urlFile);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "injectStyleCode":
|
|
||||||
source = (String) call.argument("source");
|
|
||||||
injectStyleCode(uuid, source);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "injectStyleFile":
|
|
||||||
urlFile = (String) call.argument("urlFile");
|
|
||||||
injectStyleFile(uuid, urlFile);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "show":
|
|
||||||
show(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "hide":
|
|
||||||
hide(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "reload":
|
|
||||||
reload(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "goBack":
|
|
||||||
goBack(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "canGoBack":
|
|
||||||
result.success(canGoBack(uuid));
|
|
||||||
break;
|
|
||||||
case "goForward":
|
|
||||||
goForward(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "canGoForward":
|
|
||||||
result.success(canGoForward(uuid));
|
|
||||||
break;
|
|
||||||
case "goBackOrForward":
|
|
||||||
goBackOrForward(uuid, (Integer) call.argument("steps"));
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "canGoBackOrForward":
|
|
||||||
result.success(canGoBackOrForward(uuid, (Integer) call.argument("steps")));
|
|
||||||
break;
|
|
||||||
case "stopLoading":
|
|
||||||
stopLoading(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "isLoading":
|
|
||||||
result.success(isLoading(uuid));
|
|
||||||
break;
|
|
||||||
case "isHidden":
|
|
||||||
result.success(isHidden(uuid));
|
|
||||||
break;
|
|
||||||
case "takeScreenshot":
|
|
||||||
result.success(takeScreenshot(uuid));
|
|
||||||
break;
|
|
||||||
case "setOptions":
|
|
||||||
{
|
|
||||||
String optionsType = (String) call.argument("optionsType");
|
|
||||||
switch (optionsType){
|
|
||||||
case "InAppBrowserOptions":
|
|
||||||
InAppBrowserOptions inAppBrowserOptions = new InAppBrowserOptions();
|
|
||||||
HashMap<String, Object> inAppBrowserOptionsMap = (HashMap<String, Object>) call.argument("options");
|
|
||||||
inAppBrowserOptions.parse(inAppBrowserOptionsMap);
|
|
||||||
setOptions(uuid, inAppBrowserOptions, inAppBrowserOptionsMap);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result.error(LOG_TAG, "Options " + optionsType + " not available.", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "getOptions":
|
|
||||||
result.success(getOptions(uuid));
|
|
||||||
break;
|
|
||||||
case "getCopyBackForwardList":
|
|
||||||
result.success(getCopyBackForwardList(uuid));
|
|
||||||
break;
|
|
||||||
case "startSafeBrowsing":
|
|
||||||
startSafeBrowsing(uuid, result);
|
|
||||||
break;
|
|
||||||
case "setSafeBrowsingWhitelist":
|
|
||||||
setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result);
|
|
||||||
break;
|
|
||||||
case "clearCache":
|
|
||||||
clearCache(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "clearSslPreferences":
|
|
||||||
clearSslPreferences(uuid);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "clearClientCertPreferences":
|
|
||||||
clearClientCertPreferences(uuid, result);
|
|
||||||
break;
|
|
||||||
case "findAllAsync":
|
|
||||||
String find = (String) call.argument("find");
|
|
||||||
findAllAsync(uuid, find);
|
|
||||||
result.success(true);
|
|
||||||
break;
|
|
||||||
case "findNext":
|
|
||||||
Boolean forward = (Boolean) call.argument("forward");
|
|
||||||
findNext(uuid, forward, result);
|
|
||||||
break;
|
|
||||||
case "clearMatches":
|
|
||||||
clearMatches(uuid, result);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result.notImplemented();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void injectScriptCode(String uuid, String source, final Result result) {
|
|
||||||
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
inAppBrowserActivity.injectScriptCode(source, result);
|
|
||||||
} else {
|
|
||||||
Log.d(LOG_TAG, "webView is null");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void injectScriptFile(String uuid, String urlFile) {
|
@Override
|
||||||
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
public void onDetachedFromEngine(FlutterPluginBinding binding) {
|
||||||
if (inAppBrowserActivity != null) {
|
if (inAppBrowser != null) {
|
||||||
inAppBrowserActivity.injectScriptFile(urlFile);
|
inAppBrowser.dispose();
|
||||||
|
inAppBrowser = null;
|
||||||
}
|
}
|
||||||
}
|
if (myCookieManager != null) {
|
||||||
|
myCookieManager.dispose();
|
||||||
private void injectStyleCode(String uuid, String source) {
|
myCookieManager = null;
|
||||||
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
inAppBrowserActivity.injectStyleCode(source);
|
|
||||||
}
|
}
|
||||||
}
|
if (credentialDatabaseHandler != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
credentialDatabaseHandler.dispose();
|
||||||
private void injectStyleFile(String uuid, String urlFile) {
|
credentialDatabaseHandler = null;
|
||||||
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
inAppBrowserActivity.injectStyleFile(urlFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getMimeType(String url) {
|
|
||||||
String type = null;
|
|
||||||
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
|
|
||||||
if (extension != null) {
|
|
||||||
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a new browser with the specified URL.
|
|
||||||
*
|
|
||||||
* @param url the url to load.
|
|
||||||
* @param result
|
|
||||||
* @return "" if ok, or error message.
|
|
||||||
*/
|
|
||||||
public void openExternal(Activity activity, String url, Result result) {
|
|
||||||
try {
|
|
||||||
Intent intent;
|
|
||||||
intent = new Intent(Intent.ACTION_VIEW);
|
|
||||||
// Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
|
|
||||||
// Adding the MIME type to http: URLs causes them to not be handled by the downloader.
|
|
||||||
Uri uri = Uri.parse(url);
|
|
||||||
if ("file".equals(uri.getScheme())) {
|
|
||||||
intent.setDataAndType(uri, getMimeType(url));
|
|
||||||
} else {
|
|
||||||
intent.setData(uri);
|
|
||||||
}
|
|
||||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
|
|
||||||
// CB-10795: Avoid circular loops by preventing it from opening in the current app
|
|
||||||
this.openExternalExcludeCurrentApp(activity, intent);
|
|
||||||
result.success(true);
|
|
||||||
// not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
|
|
||||||
} catch (java.lang.RuntimeException e) {
|
|
||||||
Log.d(LOG_TAG, url + " cannot be opened: " + e.toString());
|
|
||||||
result.error(LOG_TAG, url + " cannot be opened!", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the intent, providing a chooser that excludes the current app to avoid
|
|
||||||
* circular loops.
|
|
||||||
*/
|
|
||||||
private void openExternalExcludeCurrentApp(Activity activity, Intent intent) {
|
|
||||||
String currentPackage = activity.getPackageName();
|
|
||||||
boolean hasCurrentPackage = false;
|
|
||||||
PackageManager pm = activity.getPackageManager();
|
|
||||||
List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
|
|
||||||
ArrayList<Intent> targetIntents = new ArrayList<Intent>();
|
|
||||||
for (ResolveInfo ri : activities) {
|
|
||||||
if (!currentPackage.equals(ri.activityInfo.packageName)) {
|
|
||||||
Intent targetIntent = (Intent) intent.clone();
|
|
||||||
targetIntent.setPackage(ri.activityInfo.packageName);
|
|
||||||
targetIntents.add(targetIntent);
|
|
||||||
} else {
|
|
||||||
hasCurrentPackage = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the current app package isn't a target for this URL, then use
|
|
||||||
// the normal launch behavior
|
|
||||||
if (!hasCurrentPackage || targetIntents.size() == 0) {
|
|
||||||
activity.startActivity(intent);
|
|
||||||
}
|
|
||||||
// If there's only one possible intent, launch it directly
|
|
||||||
else if (targetIntents.size() == 1) {
|
|
||||||
activity.startActivity(targetIntents.get(0));
|
|
||||||
}
|
|
||||||
// Otherwise, show a custom chooser without the current app listed
|
|
||||||
else if (targetIntents.size() > 0) {
|
|
||||||
Intent chooser = Intent.createChooser(targetIntents.remove(targetIntents.size() - 1), null);
|
|
||||||
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
|
|
||||||
activity.startActivity(chooser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void open(Activity activity, String uuid, String uuidFallback, String url, HashMap<String, Object> options, Map<String, String> headers, boolean useChromeSafariBrowser, HashMap<String, Object> optionsFallback, Result result) {
|
|
||||||
|
|
||||||
Intent intent = null;
|
|
||||||
Bundle extras = new Bundle();
|
|
||||||
extras.putString("fromActivity", activity.getClass().getName());
|
|
||||||
extras.putString("url", url);
|
|
||||||
extras.putBoolean("isData", false);
|
|
||||||
extras.putString("uuid", uuid);
|
|
||||||
extras.putSerializable("options", options);
|
|
||||||
extras.putSerializable("headers", (Serializable) headers);
|
|
||||||
|
|
||||||
if (useChromeSafariBrowser && CustomTabActivityHelper.isAvailable(activity)) {
|
|
||||||
intent = new Intent(activity, ChromeCustomTabsActivity.class);
|
|
||||||
}
|
|
||||||
// check for webview fallback
|
|
||||||
else if (useChromeSafariBrowser && !CustomTabActivityHelper.isAvailable(activity) && !uuidFallback.isEmpty()) {
|
|
||||||
Log.d(LOG_TAG, "WebView fallback declared.");
|
|
||||||
// overwrite with extras fallback parameters
|
|
||||||
extras.putString("uuid", uuidFallback);
|
|
||||||
if (optionsFallback != null)
|
|
||||||
extras.putSerializable("options", optionsFallback);
|
|
||||||
else
|
|
||||||
extras.putSerializable("options", (new InAppBrowserOptions()).getHashMap());
|
|
||||||
extras.putSerializable("headers", (Serializable) headers);
|
|
||||||
intent = new Intent(activity, InAppBrowserActivity.class);
|
|
||||||
}
|
|
||||||
// native webview
|
|
||||||
else if (!useChromeSafariBrowser) {
|
|
||||||
intent = new Intent(activity, InAppBrowserActivity.class);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.d(LOG_TAG, "No WebView fallback declared.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intent != null) {
|
|
||||||
intent.putExtras(extras);
|
|
||||||
activity.startActivity(intent);
|
|
||||||
result.success(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.error(LOG_TAG, "No WebView fallback declared.", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openData(Activity activity, String uuid, HashMap<String, Object> options, String data, String mimeType, String encoding, String baseUrl) {
|
|
||||||
Intent intent = new Intent(activity, InAppBrowserActivity.class);
|
|
||||||
Bundle extras = new Bundle();
|
|
||||||
|
|
||||||
extras.putBoolean("isData", true);
|
|
||||||
extras.putString("uuid", uuid);
|
|
||||||
extras.putSerializable("options", options);
|
|
||||||
extras.putString("data", data);
|
|
||||||
extras.putString("mimeType", mimeType);
|
|
||||||
extras.putString("encoding", encoding);
|
|
||||||
extras.putString("baseUrl", baseUrl);
|
|
||||||
|
|
||||||
intent.putExtras(extras);
|
|
||||||
activity.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getUrl(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.getUrl();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTitle(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.getWebViewTitle();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer getProgress(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.getProgress();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadUrl(String uuid, String url, Map<String, String> headers, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
if (headers != null)
|
|
||||||
inAppBrowserActivity.loadUrl(url, headers, result);
|
|
||||||
else
|
|
||||||
inAppBrowserActivity.loadUrl(url, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postUrl(String uuid, String url, byte[] postData, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.postUrl(url, postData, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadData(String uuid, String data, String mimeType, String encoding, String baseUrl, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.loadData(data, mimeType, encoding, baseUrl, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadFile(String uuid, String url, Map<String, String> headers, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
if (headers != null)
|
|
||||||
inAppBrowserActivity.loadFile(url, headers, result);
|
|
||||||
else
|
|
||||||
inAppBrowserActivity.loadFile(url, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void show(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hide(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reload(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLoading(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.isLoading();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHidden(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.isHidden;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopLoading(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.stopLoading();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goBack(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.goBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canGoBack(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.canGoBack();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goForward(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.goForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canGoForward(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.canGoForward();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void goBackOrForward(String uuid, int steps) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.goBackOrForward(steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canGoBackOrForward(String uuid, int steps) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.canGoBackOrForward(steps);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close(Activity activity, final String uuid, final Result result) {
|
|
||||||
final InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null) {
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
|
|
||||||
Map<String, Object> obj = new HashMap<>();
|
|
||||||
obj.put("uuid", uuid);
|
|
||||||
channel.invokeMethod("onExit", obj);
|
|
||||||
|
|
||||||
// The JS protects against multiple calls, so this should happen only when
|
|
||||||
// close() is called by other native code.
|
|
||||||
if (inAppBrowserActivity == null) {
|
|
||||||
if (result != null) {
|
|
||||||
result.success(true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inAppBrowserActivity.webView.setWebViewClient(new WebViewClient() {
|
|
||||||
// NB: wait for about:blank before dismissing
|
|
||||||
public void onPageFinished(WebView view, String url) {
|
|
||||||
inAppBrowserActivity.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// NB: From SDK 19: "If you call methods on WebView from any thread
|
|
||||||
// other than your app's UI thread, it can cause unexpected results."
|
|
||||||
// http://developer.android.com/guide/webapps/migrating.html#Threads
|
|
||||||
inAppBrowserActivity.webView.loadUrl("about:blank");
|
|
||||||
if (result != null) {
|
|
||||||
result.success(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (result != null) {
|
|
||||||
result.success(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] takeScreenshot(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.takeScreenshot();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOptions(String uuid, InAppBrowserOptions options, HashMap<String, Object> optionsMap) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.setOptions(options, optionsMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<String, Object> getOptions(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.getOptions();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashMap<String, Object> getCopyBackForwardList(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
return inAppBrowserActivity.getCopyBackForwardList();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startSafeBrowsing(String uuid, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.startSafeBrowsing(result);
|
|
||||||
result.success(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSafeBrowsingWhitelist(String uuid, List<String> hosts, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result);
|
|
||||||
result.success(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearCache(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.clearCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearSslPreferences(String uuid) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.clearSslPreferences();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearClientCertPreferences(String uuid, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.clearClientCertPreferences(result);
|
|
||||||
result.success(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void findAllAsync(String uuid, String find) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.findAllAsync(find);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void findNext(String uuid, Boolean forward, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.findNext(forward, result);
|
|
||||||
result.success(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearMatches(String uuid, Result result) {
|
|
||||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
|
||||||
if (inAppBrowserActivity != null)
|
|
||||||
inAppBrowserActivity.clearMatches(result);
|
|
||||||
result.success(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package com.pichillilorenzo.flutter_inappbrowser;
|
|||||||
|
|
||||||
public class InAppBrowserOptions extends Options {
|
public class InAppBrowserOptions extends Options {
|
||||||
|
|
||||||
static final String LOG_TAG = "InAppBrowserOptions";
|
public static final String LOG_TAG = "InAppBrowserOptions";
|
||||||
|
|
||||||
public boolean hidden = false;
|
public boolean hidden = false;
|
||||||
public boolean toolbarTop = true;
|
public boolean toolbarTop = true;
|
||||||
|
@ -538,6 +538,6 @@ public class InAppWebChromeClient extends WebChromeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MethodChannel getChannel() {
|
private MethodChannel getChannel() {
|
||||||
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.instance.channel : flutterWebView.channel;
|
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,7 +686,7 @@ final public class InAppWebView extends InputAwareWebView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MethodChannel getChannel() {
|
private MethodChannel getChannel() {
|
||||||
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.instance.channel : flutterWebView.channel;
|
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startSafeBrowsing(final MethodChannel.Result result) {
|
public void startSafeBrowsing(final MethodChannel.Result result) {
|
||||||
@ -745,6 +745,11 @@ final public class InAppWebView extends InputAwareWebView {
|
|||||||
webSettings.setBuiltInZoomControls(enabled);
|
webSettings.setBuiltInZoomControls(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
|
@ -224,7 +224,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||||||
previousAuthRequestFailureCount = 0;
|
previousAuthRequestFailureCount = 0;
|
||||||
credentialsProposed = null;
|
credentialsProposed = null;
|
||||||
|
|
||||||
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
|
// CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
CookieManager.getInstance().flush();
|
CookieManager.getInstance().flush();
|
||||||
} else {
|
} else {
|
||||||
@ -667,7 +667,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MethodChannel getChannel() {
|
private MethodChannel getChannel() {
|
||||||
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.instance.channel : flutterWebView.channel;
|
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class InAppWebViewOptions extends Options {
|
public class InAppWebViewOptions extends Options {
|
||||||
|
|
||||||
static final String LOG_TAG = "InAppWebViewOptions";
|
public static final String LOG_TAG = "InAppWebViewOptions";
|
||||||
|
|
||||||
public boolean useShouldOverrideUrlLoading = false;
|
public boolean useShouldOverrideUrlLoading = false;
|
||||||
public boolean useOnLoadResource = false;
|
public boolean useOnLoadResource = false;
|
||||||
|
@ -4,6 +4,7 @@ import static android.content.Context.INPUT_METHOD_SERVICE;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
@ -15,8 +16,8 @@ import android.webkit.WebView;
|
|||||||
* https://github.com/flutter/plugins/blob/master/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
|
* https://github.com/flutter/plugins/blob/master/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
|
||||||
*/
|
*/
|
||||||
public class InputAwareWebView extends WebView {
|
public class InputAwareWebView extends WebView {
|
||||||
|
private static final String LOG_TAG = "InputAwareWebView";
|
||||||
public View containerView;
|
public View containerView;
|
||||||
|
|
||||||
private View threadedInputConnectionProxyView;
|
private View threadedInputConnectionProxyView;
|
||||||
private ThreadedInputConnectionProxyAdapterView proxyAdapterView;
|
private ThreadedInputConnectionProxyAdapterView proxyAdapterView;
|
||||||
|
|
||||||
@ -40,6 +41,19 @@ public class InputAwareWebView extends WebView {
|
|||||||
this.containerView = null;
|
this.containerView = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContainerView(View containerView) {
|
||||||
|
this.containerView = containerView;
|
||||||
|
|
||||||
|
if (proxyAdapterView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.w(LOG_TAG, "The containerView has changed while the proxyAdapterView exists.");
|
||||||
|
if (containerView != null) {
|
||||||
|
setInputConnectionTarget(proxyAdapterView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set our proxy adapter view to use its cached input connection instead of creating new ones.
|
* Set our proxy adapter view to use its cached input connection instead of creating new ones.
|
||||||
*
|
*
|
||||||
@ -82,8 +96,6 @@ public class InputAwareWebView extends WebView {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean checkInputConnectionProxy(final View view) {
|
public boolean checkInputConnectionProxy(final View view) {
|
||||||
if (containerView == null)
|
|
||||||
return super.checkInputConnectionProxy(view);
|
|
||||||
// Check to see if the view param is WebView's ThreadedInputConnectionProxyView.
|
// Check to see if the view param is WebView's ThreadedInputConnectionProxyView.
|
||||||
View previousProxy = threadedInputConnectionProxyView;
|
View previousProxy = threadedInputConnectionProxyView;
|
||||||
threadedInputConnectionProxyView = view;
|
threadedInputConnectionProxyView = view;
|
||||||
@ -91,6 +103,12 @@ public class InputAwareWebView extends WebView {
|
|||||||
// This isn't a new ThreadedInputConnectionProxyView. Ignore it.
|
// This isn't a new ThreadedInputConnectionProxyView. Ignore it.
|
||||||
return super.checkInputConnectionProxy(view);
|
return super.checkInputConnectionProxy(view);
|
||||||
}
|
}
|
||||||
|
if (containerView == null) {
|
||||||
|
Log.e(
|
||||||
|
LOG_TAG,
|
||||||
|
"Can't create a proxy view because there's no container view. Text input may not work.");
|
||||||
|
return super.checkInputConnectionProxy(view);
|
||||||
|
}
|
||||||
|
|
||||||
// We've never seen this before, so we make the assumption that this is WebView's
|
// We've never seen this before, so we make the assumption that this is WebView's
|
||||||
// ThreadedInputConnectionProxyView. We are making the assumption that the only view that could
|
// ThreadedInputConnectionProxyView. We are making the assumption that the only view that could
|
||||||
@ -115,8 +133,7 @@ public class InputAwareWebView extends WebView {
|
|||||||
@Override
|
@Override
|
||||||
public void clearFocus() {
|
public void clearFocus() {
|
||||||
super.clearFocus();
|
super.clearFocus();
|
||||||
if (containerView != null)
|
resetInputConnection();
|
||||||
resetInputConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,6 +148,10 @@ public class InputAwareWebView extends WebView {
|
|||||||
// No need to reset the InputConnection to the default thread if we've never changed it.
|
// No need to reset the InputConnection to the default thread if we've never changed it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (containerView == null) {
|
||||||
|
Log.e(LOG_TAG, "Can't reset the input connection to the container view because there is none.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
setInputConnectionTarget(/*targetView=*/ containerView);
|
setInputConnectionTarget(/*targetView=*/ containerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +164,13 @@ public class InputAwareWebView extends WebView {
|
|||||||
* InputConnections should be created on.
|
* InputConnections should be created on.
|
||||||
*/
|
*/
|
||||||
private void setInputConnectionTarget(final View targetView) {
|
private void setInputConnectionTarget(final View targetView) {
|
||||||
|
if (containerView == null) {
|
||||||
|
Log.e(
|
||||||
|
LOG_TAG,
|
||||||
|
"Can't set the input connection target because there is no containerView to use as a handler.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
targetView.requestFocus();
|
targetView.requestFocus();
|
||||||
containerView.post(
|
containerView.post(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
|
@ -11,8 +11,6 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
|
|||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -121,6 +119,6 @@ public class JavaScriptBridgeInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MethodChannel getChannel() {
|
private MethodChannel getChannel() {
|
||||||
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.instance.channel : flutterWebView.channel;
|
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,4 +226,7 @@ public class MyCookieManager implements MethodChannel.MethodCallHandler {
|
|||||||
return sdf.format(new Date(timestamp));
|
return sdf.format(new Date(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,24 @@ import java.security.Key;
|
|||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
import io.flutter.plugin.common.PluginRegistry;
|
import io.flutter.plugin.common.PluginRegistry;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
|
|
||||||
@ -148,4 +158,50 @@ public class Util {
|
|||||||
this.certificates = certificates;
|
this.certificates = certificates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OkHttpClient getUnsafeOkHttpClient() {
|
||||||
|
try {
|
||||||
|
// Create a trust manager that does not validate certificate chains
|
||||||
|
final TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new X509TrustManager() {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new java.security.cert.X509Certificate[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install the all-trusting trust manager
|
||||||
|
final SSLContext sslContext = SSLContext.getInstance("SSL");
|
||||||
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||||
|
// Create an ssl socket factory with our all-trusting manager
|
||||||
|
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
|
||||||
|
builder.hostnameVerifier(new HostnameVerifier() {
|
||||||
|
@Override
|
||||||
|
public boolean verify(String hostname, SSLSession session) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OkHttpClient okHttpClient = builder
|
||||||
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
return okHttpClient;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
android.enableJetifier=true
|
|
||||||
android.useAndroidX=true
|
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
|
android.enableR8=true
|
BIN
example/assets/favicon.ico
Normal file
BIN
example/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -8,6 +8,7 @@
|
|||||||
<link rel="stylesheet" href="http://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css">
|
<link rel="stylesheet" href="http://getbootstrap.com/docs/4.3/dist/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="css/style.css">
|
<link rel="stylesheet" href="css/style.css">
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body class="text-center">
|
<body class="text-center">
|
||||||
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||||
@ -26,6 +27,10 @@
|
|||||||
<h1 class="cover-heading">Inline WebView</h1>
|
<h1 class="cover-heading">Inline WebView</h1>
|
||||||
<img src="my-special-custom-scheme://images/flutter-logo.svg" alt="flutter logo">
|
<img src="my-special-custom-scheme://images/flutter-logo.svg" alt="flutter logo">
|
||||||
<p class="lead">Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.</p>
|
<p class="lead">Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.</p>
|
||||||
|
<select name="" id="">
|
||||||
|
<option value="1">option 1</option>
|
||||||
|
<option value="2">option 2</option>
|
||||||
|
</select>
|
||||||
<p>
|
<p>
|
||||||
<img src="https://via.placeholder.com/100x50" alt="placeholder 100x50">
|
<img src="https://via.placeholder.com/100x50" alt="placeholder 100x50">
|
||||||
</p>
|
</p>
|
||||||
|
@ -5,6 +5,6 @@ export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappbro
|
|||||||
export "FLUTTER_TARGET=lib/main.dart"
|
export "FLUTTER_TARGET=lib/main.dart"
|
||||||
export "FLUTTER_BUILD_DIR=build"
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
|
||||||
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios-release"
|
export "FLUTTER_FRAMEWORK_DIR=/Users/lorenzopichilli/flutter/bin/cache/artifacts/engine/ios"
|
||||||
export "FLUTTER_BUILD_NAME=1.0.0"
|
export "FLUTTER_BUILD_NAME=1.0.0"
|
||||||
export "FLUTTER_BUILD_NUMBER=1"
|
export "FLUTTER_BUILD_NUMBER=1"
|
||||||
|
@ -83,11 +83,11 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||||||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||||
child: InAppWebView(
|
child: InAppWebView(
|
||||||
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
|
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
|
||||||
initialUrl: "https://github.com",
|
//initialUrl: "https://github.com",
|
||||||
//initialUrl: "chrome://safe-browsing/match?type=malware",
|
//initialUrl: "chrome://safe-browsing/match?type=malware",
|
||||||
//initialUrl: "http://192.168.1.20:8081/",
|
//initialUrl: "http://192.168.1.20:8081/",
|
||||||
//initialUrl: "https://192.168.1.20:4433/",
|
//initialUrl: "https://192.168.1.20:4433/",
|
||||||
//initialFile: "assets/index.html",
|
initialFile: "assets/index.html",
|
||||||
initialHeaders: {},
|
initialHeaders: {},
|
||||||
initialOptions: [
|
initialOptions: [
|
||||||
InAppWebViewOptions(
|
InAppWebViewOptions(
|
||||||
@ -143,8 +143,8 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||||||
controller.clearSslPreferences();
|
controller.clearSslPreferences();
|
||||||
controller.clearClientCertPreferences();
|
controller.clearClientCertPreferences();
|
||||||
}
|
}
|
||||||
//controller.findAllAsync("a");
|
//controller.findAllAsync("flutter");
|
||||||
controller.getFavicon();
|
print(await controller.getFavicons());
|
||||||
},
|
},
|
||||||
onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
|
onLoadError: (InAppWebViewController controller, String url, int code, String message) async {
|
||||||
print("error $url: $code, $message");
|
print("error $url: $code, $message");
|
||||||
|
@ -48,6 +48,7 @@ flutter:
|
|||||||
- assets/page-2.html
|
- assets/page-2.html
|
||||||
- assets/css/
|
- assets/css/
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
- assets/favicon.ico
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
|
@ -301,25 +301,9 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
|
|||||||
}
|
}
|
||||||
result(true)
|
result(true)
|
||||||
break
|
break
|
||||||
case "dispose":
|
|
||||||
dispose()
|
|
||||||
result(true)
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
result(FlutterMethodNotImplemented)
|
result(FlutterMethodNotImplemented)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dispose() {
|
|
||||||
if webView != nil {
|
|
||||||
webView!.IABController = nil
|
|
||||||
webView!.IAWController = nil
|
|
||||||
webView!.uiDelegate = nil
|
|
||||||
webView!.navigationDelegate = nil
|
|
||||||
webView!.scrollView.delegate = nil
|
|
||||||
webView!.stopLoading()
|
|
||||||
webView = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||||||
var IAWController: FlutterWebViewController?
|
var IAWController: FlutterWebViewController?
|
||||||
var options: InAppWebViewOptions?
|
var options: InAppWebViewOptions?
|
||||||
var currentURL: URL?
|
var currentURL: URL?
|
||||||
var WKNavigationMap: [String: [String: Any]] = [:]
|
|
||||||
var startPageTime: Int64 = 0
|
var startPageTime: Int64 = 0
|
||||||
static var credentialsProposed: [URLCredential] = []
|
static var credentialsProposed: [URLCredential] = []
|
||||||
|
|
||||||
@ -786,13 +785,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||||||
let app = UIApplication.shared
|
let app = UIApplication.shared
|
||||||
|
|
||||||
if let url = navigationAction.request.url {
|
if let url = navigationAction.request.url {
|
||||||
if url.absoluteString != url.absoluteString && (options?.useOnLoadResource)! {
|
|
||||||
WKNavigationMap[url.absoluteString] = [
|
|
||||||
"startTime": currentTimeInMilliSeconds(),
|
|
||||||
"request": navigationAction.request
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle target="_blank"
|
// Handle target="_blank"
|
||||||
if navigationAction.targetFrame == nil && (options?.useOnTargetBlank)! {
|
if navigationAction.targetFrame == nil && (options?.useOnTargetBlank)! {
|
||||||
onTargetBlank(url: url)
|
onTargetBlank(url: url)
|
||||||
@ -834,17 +826,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||||||
decidePolicyFor navigationResponse: WKNavigationResponse,
|
decidePolicyFor navigationResponse: WKNavigationResponse,
|
||||||
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
|
||||||
|
|
||||||
// if (options?.useOnLoadResource)! {
|
|
||||||
// if let url = navigationResponse.response.url {
|
|
||||||
// if WKNavigationMap[url.absoluteString] != nil {
|
|
||||||
// let startResourceTime: Int64 = (WKNavigationMap[url.absoluteString]!["startTime"] as! Int64)
|
|
||||||
// let startTime: Int64 = startResourceTime - startPageTime;
|
|
||||||
// let duration: Int64 = currentTimeInMilliSeconds() - startResourceTime;
|
|
||||||
// onLoadResource(response: navigationResponse.response, fromRequest: WKNavigationMap[url.absoluteString]!["request"] as? URLRequest, withData: Data(), startTime: startTime, duration: duration)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (options?.useOnDownloadStart)! {
|
if (options?.useOnDownloadStart)! {
|
||||||
let mimeType = navigationResponse.response.mimeType
|
let mimeType = navigationResponse.response.mimeType
|
||||||
if let url = navigationResponse.response.url {
|
if let url = navigationResponse.response.url {
|
||||||
@ -875,7 +856,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||||
self.WKNavigationMap = [:]
|
|
||||||
currentURL = url
|
currentURL = url
|
||||||
InAppWebView.credentialsProposed = []
|
InAppWebView.credentialsProposed = []
|
||||||
onLoadStop(url: (currentURL?.absoluteString)!)
|
onLoadStop(url: (currentURL?.absoluteString)!)
|
||||||
|
@ -17,7 +17,7 @@ A new Flutter plugin.
|
|||||||
s.public_header_files = 'Classes/**/*.h'
|
s.public_header_files = 'Classes/**/*.h'
|
||||||
s.dependency 'Flutter'
|
s.dependency 'Flutter'
|
||||||
|
|
||||||
s.ios.deployment_target = '8.0'
|
s.platform = '8.0'
|
||||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
|
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
|
||||||
s.swift_version = '5.0'
|
s.swift_version = '5.0'
|
||||||
end
|
end
|
||||||
|
@ -268,7 +268,8 @@ class InAppBrowser {
|
|||||||
args.putIfAbsent('uuid', () => uuid);
|
args.putIfAbsent('uuid', () => uuid);
|
||||||
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
|
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
|
||||||
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
|
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
|
||||||
options = options.cast<String, dynamic>();
|
if (options != null)
|
||||||
|
options = options.cast<String, dynamic>();
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,10 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
|
|
||||||
|
import 'package:html/parser.dart' show parse;
|
||||||
|
|
||||||
import 'types.dart';
|
import 'types.dart';
|
||||||
import 'in_app_browser.dart';
|
import 'in_app_browser.dart';
|
||||||
import 'channel_manager.dart';
|
|
||||||
import 'webview_options.dart';
|
import 'webview_options.dart';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -255,15 +256,6 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||||||
|
|
||||||
InAppWebViewController _controller;
|
InAppWebViewController _controller;
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
if (_controller != null) {
|
|
||||||
_controller._dispose();
|
|
||||||
_controller = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Map<String, dynamic> initialOptions = {};
|
Map<String, dynamic> initialOptions = {};
|
||||||
@ -273,7 +265,22 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||||
return GestureDetector(
|
return AndroidView(
|
||||||
|
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||||
|
onPlatformViewCreated: _onPlatformViewCreated,
|
||||||
|
gestureRecognizers: widget.gestureRecognizers,
|
||||||
|
layoutDirection: TextDirection.rtl,
|
||||||
|
creationParams: <String, dynamic>{
|
||||||
|
'initialUrl': widget.initialUrl,
|
||||||
|
'initialFile': widget.initialFile,
|
||||||
|
'initialData': widget.initialData?.toMap(),
|
||||||
|
'initialHeaders': widget.initialHeaders,
|
||||||
|
'initialOptions': initialOptions
|
||||||
|
},
|
||||||
|
creationParamsCodec: const StandardMessageCodec(),
|
||||||
|
);
|
||||||
|
// onLongPress issue: https://github.com/flutter/plugins/blob/f31d16a6ca0c4bd6849cff925a00b6823973696b/packages/webview_flutter/lib/src/webview_android.dart#L31
|
||||||
|
/*return GestureDetector(
|
||||||
onLongPress: () {},
|
onLongPress: () {},
|
||||||
excludeFromSemantics: true,
|
excludeFromSemantics: true,
|
||||||
child: AndroidView(
|
child: AndroidView(
|
||||||
@ -290,7 +297,7 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||||||
},
|
},
|
||||||
creationParamsCodec: const StandardMessageCodec(),
|
creationParamsCodec: const StandardMessageCodec(),
|
||||||
),
|
),
|
||||||
);
|
);*/
|
||||||
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
|
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
|
||||||
return UiKitView(
|
return UiKitView(
|
||||||
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
viewType: 'com.pichillilorenzo/flutter_inappwebview',
|
||||||
@ -593,105 +600,146 @@ class InAppWebViewController {
|
|||||||
return await _channel.invokeMethod('getProgress', args);
|
return await _channel.invokeMethod('getProgress', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the favicon for the current page.
|
///Gets the content html of the page. It first tries to get the content through javascript.
|
||||||
Future<List<int>> getFavicon() async {
|
///If this doesn't work, it tries to get the content reading the file:
|
||||||
List<Favicon> favicons = [];
|
///- checking if it is an asset (`file:///`) or
|
||||||
HttpClient client = new HttpClient();
|
///- downloading it using an `HttpClient` through the WebView's current url.
|
||||||
var url = Uri.parse(await getUrl());
|
Future<String> getHtml() async {
|
||||||
|
var html = "";
|
||||||
var htmlRequest = await client.getUrl(url);
|
Map<String, dynamic> options = await getOptions();
|
||||||
var html = await (await htmlRequest.close()).transform(Utf8Decoder()).join();
|
if (options != null && options["javaScriptEnabled"] == true) {
|
||||||
/// TODO: parse HTML instead of using javascript code
|
html = await injectScriptCode("window.document.getElementsByTagName('html')[0].outerHTML;");
|
||||||
|
if (html.isNotEmpty)
|
||||||
try {
|
return html;
|
||||||
List<dynamic> faviconsJs = json.decode(await injectScriptCode("""
|
|
||||||
function flutter_inappbrowser_ger_favicons() {
|
|
||||||
var favicons = [];
|
|
||||||
var links = document.getElementsByTagName('link');
|
|
||||||
for (var i = 0; i < links.length; i++) {
|
|
||||||
var link = links[i];
|
|
||||||
if (link.rel.indexOf("icon") >= 0) {
|
|
||||||
favicons.push({
|
|
||||||
rel: link.rel,
|
|
||||||
href: link.href,
|
|
||||||
sizes: link.sizes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return favicons;
|
|
||||||
}
|
|
||||||
flutter_inappbrowser_ger_favicons();
|
|
||||||
"""));
|
|
||||||
for(Map<String, dynamic> favicon in faviconsJs) {
|
|
||||||
String sizes = favicon["sizes"];
|
|
||||||
if (sizes != null && sizes != "any") {
|
|
||||||
List<String> sizesSplitted = sizes.split(" ");
|
|
||||||
for (String size in sizesSplitted) {
|
|
||||||
int width = int.parse(size.split("x")[0]);
|
|
||||||
int height = int.parse(size.split("x")[1]);
|
|
||||||
favicons.add(Favicon(url: favicon["href"], rel: favicon["rel"], width: width, height: height));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
favicons.add(Favicon(url: favicon["href"], rel: favicon["rel"], width: null, height: null));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var webviewUrl = await getUrl();
|
||||||
|
if (webviewUrl.startsWith("file:///")) {
|
||||||
|
var assetPathSplitted = webviewUrl.split("/flutter_assets/");
|
||||||
|
var assetPath = assetPathSplitted[assetPathSplitted.length - 1];
|
||||||
|
var bytes = await rootBundle.load(assetPath);
|
||||||
|
html = utf8.decode(bytes.buffer.asUint8List());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
var url = Uri.parse(webviewUrl);
|
||||||
|
try {
|
||||||
|
var htmlRequest = await client.getUrl(url);
|
||||||
|
html = await (await htmlRequest.close()).transform(Utf8Decoder()).join();
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
}
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Gets the list of all favicons for the current page.
|
||||||
|
Future<List<Favicon>> getFavicons() async {
|
||||||
|
List<Favicon> favicons = [];
|
||||||
|
|
||||||
var completer = new Completer<List<int>>();
|
HttpClient client = new HttpClient();
|
||||||
var faviconData = new List<int>();
|
var webviewUrl = await getUrl();
|
||||||
|
var url = (webviewUrl.startsWith("file:///")) ? Uri.file(webviewUrl) : Uri.parse(webviewUrl);
|
||||||
|
String manifestUrl;
|
||||||
|
|
||||||
|
var html = await getHtml();
|
||||||
|
if (html.isEmpty) {
|
||||||
|
return favicons;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assetPathBase;
|
||||||
|
|
||||||
|
if (webviewUrl.startsWith("file:///")) {
|
||||||
|
var assetPathSplitted = webviewUrl.split("/flutter_assets/");
|
||||||
|
assetPathBase = assetPathSplitted[0] + "/flutter_assets/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all link html elements
|
||||||
|
var document = parse(html);
|
||||||
|
var links = document.getElementsByTagName('link');
|
||||||
|
for (var link in links) {
|
||||||
|
var attributes = link.attributes;
|
||||||
|
if (attributes["rel"] == "manifest") {
|
||||||
|
manifestUrl = attributes["href"];
|
||||||
|
if (!_isUrlAbsolute(manifestUrl)) {
|
||||||
|
if (manifestUrl.startsWith("/")) {
|
||||||
|
manifestUrl = manifestUrl.substring(1);
|
||||||
|
}
|
||||||
|
manifestUrl = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + manifestUrl;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!attributes["rel"].contains("icon")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
favicons.addAll(_createFavicons(url, assetPathBase, attributes["href"], attributes["rel"], attributes["sizes"], false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to get /favicon.ico
|
||||||
try {
|
try {
|
||||||
var faviconUrl = url.scheme + "://" + url.host + "/favicon.ico";
|
var faviconUrl = url.scheme + "://" + url.host + "/favicon.ico";
|
||||||
await client.headUrl(Uri.parse(faviconUrl));
|
await client.headUrl(Uri.parse(faviconUrl));
|
||||||
favicons.add(Favicon(url: faviconUrl, rel: "shortcut icon"));
|
favicons.add(Favicon(url: faviconUrl, rel: "shortcut icon"));
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
var manifestRequest;
|
|
||||||
try {
|
|
||||||
var manifestJsonUrl = url.scheme + "://" + url.host + "/manifest.json";
|
|
||||||
manifestRequest = await client.getUrl(Uri.parse(manifestJsonUrl));
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
/// TODO: find manifest throught rel="manifest"
|
print("/favicon.ico file not found: " + e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manifestRequest) {
|
// try to get the manifest file
|
||||||
Map<String, dynamic> manifest = json.decode(await (await manifestRequest.close()).transform(Utf8Decoder()).join());
|
HttpClientRequest manifestRequest;
|
||||||
|
HttpClientResponse manifestResponse;
|
||||||
|
bool manifestFound = false;
|
||||||
|
if (manifestUrl == null) {
|
||||||
|
manifestUrl = url.scheme + "://" + url.host + "/manifest.json";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
manifestRequest = await client.getUrl(Uri.parse(manifestUrl));
|
||||||
|
manifestResponse = await manifestRequest.close();
|
||||||
|
manifestFound = manifestResponse.statusCode == 200 && manifestResponse.headers.contentType?.mimeType == "application/json";
|
||||||
|
} catch(e) {
|
||||||
|
print("Manifest file not found: " + e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manifestFound) {
|
||||||
|
Map<String, dynamic> manifest = json.decode(await manifestResponse.transform(Utf8Decoder()).join());
|
||||||
if (manifest.containsKey("icons")) {
|
if (manifest.containsKey("icons")) {
|
||||||
for(Map<String, dynamic> icon in manifest["icons"]) {
|
for(Map<String, dynamic> icon in manifest["icons"]) {
|
||||||
String url = icon["src"];
|
favicons.addAll(_createFavicons(url, assetPathBase, icon["src"], icon["rel"], icon["sizes"], true));
|
||||||
List<String> urlSplitted = url.split("/");
|
|
||||||
String sizes = icon["sizes"];
|
|
||||||
String rel = (sizes != null) ? urlSplitted[urlSplitted.length - 1].replaceFirst("-" + sizes, "").split(" ")[0].split(".")[0] : null;
|
|
||||||
if (sizes != null && sizes != "any") {
|
|
||||||
List<String> sizesSplitted = sizes.split(" ");
|
|
||||||
for (String size in sizesSplitted) {
|
|
||||||
int width = int.parse(size.split("x")[0]);
|
|
||||||
int height = int.parse(size.split("x")[1]);
|
|
||||||
favicons.add(Favicon(url: url, rel: rel, width: width, height: height));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
favicons.add(Favicon(url: url, rel: rel, width: null, height: null));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//print(favicons);
|
return favicons;
|
||||||
|
}
|
||||||
|
|
||||||
// solution found here: https://stackoverflow.com/a/15750809/4637638
|
bool _isUrlAbsolute(String url) {
|
||||||
var googleFaviconUrl = Uri.parse("https://plus.google.com/_/favicon?domain_url=" + url.scheme + "://" + url.host);
|
return url.startsWith("http://") || url.startsWith("https://");
|
||||||
client.getUrl(googleFaviconUrl).then((HttpClientRequest request) {
|
}
|
||||||
return request.close();
|
|
||||||
}).then((HttpClientResponse response) {
|
List<Favicon> _createFavicons(Uri url, String assetPathBase, String urlIcon, String rel, String sizes, bool isManifest) {
|
||||||
response.listen((List<int> data) {
|
List<Favicon> favicons = [];
|
||||||
faviconData = data;
|
|
||||||
}, onDone: () => completer.complete(faviconData));
|
List<String> urlSplitted = urlIcon.split("/");
|
||||||
}).catchError((error) {
|
if (!_isUrlAbsolute(urlIcon)) {
|
||||||
completer.completeError(error);
|
if (urlIcon.startsWith("/")) {
|
||||||
});
|
urlIcon = urlIcon.substring(1);
|
||||||
return completer.future;
|
}
|
||||||
|
urlIcon = ((assetPathBase == null) ? url.scheme + "://" + url.host + "/" : assetPathBase) + urlIcon;
|
||||||
|
}
|
||||||
|
if (isManifest) {
|
||||||
|
rel = (sizes != null) ? urlSplitted[urlSplitted.length - 1].replaceFirst("-" + sizes, "").split(" ")[0].split(".")[0] : null;
|
||||||
|
}
|
||||||
|
if (sizes != null && sizes.isNotEmpty && sizes != "any") {
|
||||||
|
List<String> sizesSplitted = sizes.split(" ");
|
||||||
|
for (String size in sizesSplitted) {
|
||||||
|
int width = int.parse(size.split("x")[0]);
|
||||||
|
int height = int.parse(size.split("x")[1]);
|
||||||
|
favicons.add(Favicon(url: urlIcon, rel: rel, width: width, height: height));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
favicons.add(Favicon(url: urlIcon, rel: rel, width: null, height: null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return favicons;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Loads the given [url] with optional [headers] specified as a map from name to value.
|
///Loads the given [url] with optional [headers] specified as a map from name to value.
|
||||||
@ -1001,7 +1049,6 @@ flutter_inappbrowser_ger_favicons();
|
|||||||
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
|
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
|
||||||
}
|
}
|
||||||
args.putIfAbsent('options', () => options);
|
args.putIfAbsent('options', () => options);
|
||||||
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
|
|
||||||
await _channel.invokeMethod('setOptions', args);
|
await _channel.invokeMethod('setOptions', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,9 +1059,9 @@ flutter_inappbrowser_ger_favicons();
|
|||||||
_inAppBrowser.throwIsNotOpened();
|
_inAppBrowser.throwIsNotOpened();
|
||||||
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
|
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
|
||||||
}
|
}
|
||||||
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
|
Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args);
|
||||||
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
|
if (options != null)
|
||||||
options = options.cast<String, dynamic>();
|
options = options.cast<String, dynamic>();
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,9 +1230,4 @@ flutter_inappbrowser_ger_favicons();
|
|||||||
}
|
}
|
||||||
await _channel.invokeMethod('clearMatches', args);
|
await _channel.invokeMethod('clearMatches', args);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Dispose/Destroy the WebView.
|
|
||||||
Future<void> _dispose() async {
|
|
||||||
await _channel.invokeMethod('dispose');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOpti
|
|||||||
this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED}) {
|
this.resourceCustomSchemes = const [], this.contentBlockers = const [], this.preferredContentMode = InAppWebViewUserPreferredContentMode.RECOMMENDED}) {
|
||||||
if (this.minimumFontSize == null)
|
if (this.minimumFontSize == null)
|
||||||
this.minimumFontSize = Platform.isAndroid ? 8 : 0;
|
this.minimumFontSize = Platform.isAndroid ? 8 : 0;
|
||||||
|
assert(!this.resourceCustomSchemes.contains("http") && !this.resourceCustomSchemes.contains("https"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -23,7 +23,16 @@ appHttps.get('/', (req, res) => {
|
|||||||
// `localhost`.
|
// `localhost`.
|
||||||
|
|
||||||
if (req.client.authorized) {
|
if (req.client.authorized) {
|
||||||
res.send(`Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!`)
|
res.send(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="/fakeResource" type="text/javascript"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`)
|
||||||
// They can still provide a certificate which is not accepted by us. Unfortunately, the `cert` object will be an empty
|
// They can still provide a certificate which is not accepted by us. Unfortunately, the `cert` object will be an empty
|
||||||
// object instead of `null` if there is no certificate at all, so we have to check for a known field rather than
|
// object instead of `null` if there is no certificate at all, so we have to check for a known field rather than
|
||||||
// truthiness.
|
// truthiness.
|
||||||
@ -34,6 +43,13 @@ appHttps.get('/', (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
res.status(401).send(`Sorry, but you need to provide a client certificate to continue.`)
|
res.status(401).send(`Sorry, but you need to provide a client certificate to continue.`)
|
||||||
}
|
}
|
||||||
|
res.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
appHttps.get('/fakeResource', (req, res) => {
|
||||||
|
res.set("Content-Type", "text/javascript")
|
||||||
|
res.send(`alert("HI");`)
|
||||||
|
res.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Let's create our HTTPS server and we're ready to go.
|
// Let's create our HTTPS server and we're ready to go.
|
||||||
|
@ -5,14 +5,15 @@ author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
|
|||||||
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
|
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.0.0-dev <3.0.0"
|
sdk: ">=2.0.0-dev.68.0 <3.0.0"
|
||||||
flutter: ">=0.10.1 <2.0.0"
|
flutter: ">=1.9.1+hotfix.5 <2.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
uuid: ^2.0.0
|
uuid: ^2.0.0
|
||||||
mime: ^0.9.6+2
|
mime: ^0.9.6+2
|
||||||
|
html: ^0.14.0+3
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://www.dartlang.org/tools/pub/pubspec
|
# following page: https://www.dartlang.org/tools/pub/pubspec
|
||||||
|
Loading…
x
Reference in New Issue
Block a user