added HttpAuthCredentialDatabase class, clearCache method, onReceivedHttpAuthRequest event

This commit is contained in:
Lorenzo Pichilli 2019-10-31 03:20:07 +01:00
parent fed99ec0e9
commit 68ff79c716
32 changed files with 1623 additions and 478 deletions

View File

@ -15,20 +15,34 @@
</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/InAppWebView/DisplayListenerProxy.java" afterDir="false" /> <change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/Credential.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/InputAwareWebView.java" afterDir="false" /> <change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/CredentialContract.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppWebView/ThreadedInputConnectionProxyAdapterView.java" afterDir="false" /> <change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/CredentialDao.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/CredentialDatabase.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/CredentialDatabaseHelper.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/ProtectionSpace.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/ProtectionSpaceContract.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabase/ProtectionSpaceDao.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/CredentialDatabaseHandler.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/ios/Classes/CredentialDatabase.swift" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" 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/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/FlutterWebViewFactory.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/FlutterWebViewFactory.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/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/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/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/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/Util.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/Util.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$/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$/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/InAppWebViewOptions.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppWebViewOptions.swift" afterDir="false" /> <change beforePath="$PROJECT_DIR$/ios/Classes/MyCookieManager.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/MyCookieManager.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$/lib/flutter_inappbrowser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/chrome_safari_browser.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/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/types.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/types.dart" afterDir="false" />
@ -52,59 +66,11 @@
<component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" /> <component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" />
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="true"> <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="557"> <state relative-caret-position="360">
<caret line="39" column="8" lean-forward="true" selection-start-line="39" selection-start-column="8" selection-end-line="39" selection-end-column="8" /> <caret line="24" column="42" selection-start-line="24" selection-start-column="42" selection-end-line="24" selection-end-column="42" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="22" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="22" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/lib/webview_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="182">
<caret line="65" column="59" selection-start-line="65" selection-start-column="59" selection-end-line="65" selection-end-column="59" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="169" column="79" selection-start-line="169" selection-start-column="79" selection-end-line="169" selection-end-column="79" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="549">
<caret line="409" column="5" selection-start-line="409" selection-start-column="5" selection-end-line="409" selection-end-column="5" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
@ -112,8 +78,8 @@
<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/types.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-453"> <state relative-caret-position="147">
<caret line="241" selection-start-line="241" selection-end-line="241" /> <caret line="327" column="89" selection-start-line="327" selection-start-column="89" selection-end-line="327" selection-end-column="89" />
<folding> <folding>
<element signature="e#0#32#0" expanded="true" /> <element signature="e#0#32#0" expanded="true" />
</folding> </folding>
@ -124,17 +90,50 @@
<file pinned="false" current-in-tab="false"> <file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/assets/index.html"> <entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="514"> <state relative-caret-position="416">
<caret line="73" column="12" selection-start-line="73" selection-start-column="12" selection-end-line="73" selection-end-column="12" /> <caret line="73" column="12" selection-start-line="73" selection-start-column="12" selection-end-line="73" selection-end-column="12" />
</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$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-492">
<caret line="881" column="26" selection-start-line="881" selection-start-column="22" selection-end-line="881" selection-end-column="26" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="419">
<caret line="411" column="2" selection-start-line="411" selection-start-column="2" selection-end-line="411" selection-end-column="106" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="395">
<caret line="61" column="51" selection-start-line="61" selection-start-column="21" selection-end-line="61" selection-end-column="51" />
</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="1401"> <state relative-caret-position="253">
<caret line="222" column="12" selection-start-line="222" selection-start-column="12" selection-end-line="222" selection-end-column="12" /> <caret line="88" column="12" selection-start-line="88" selection-start-column="12" selection-end-line="88" selection-end-column="12" />
<folding> <folding>
<element signature="e#0#22#0" expanded="true" /> <element signature="e#0#22#0" expanded="true" />
</folding> </folding>
@ -142,6 +141,27 @@
</provider> </provider>
</entry> </entry>
</file> </file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="256">
<caret line="43" column="9" selection-start-line="43" selection-start-column="9" selection-end-line="43" selection-end-column="9" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="4" column="32" selection-start-line="4" selection-start-column="6" selection-end-line="4" selection-end-column="32" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf> </leaf>
</component> </component>
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
@ -154,16 +174,6 @@
</component> </component>
<component name="FindInProjectRecents"> <component name="FindInProjectRecents">
<findStrings> <findStrings>
<find>defaultWebpagePreferences</find>
<find>contentBlockers</find>
<find>preferredContentMode</find>
<find>useOnLoadResource</find>
<find>safe</find>
<find>InAppWebViewController</find>
<find>safeBrowsingEnabled</find>
<find>only</find>
<find>///**NOTE**: available only for Android.</find>
<find>_inAppBrowser</find>
<find>_channel</find> <find>_channel</find>
<find>uuid_</find> <find>uuid_</find>
<find>javaScriptHandlersMap</find> <find>javaScriptHandlersMap</find>
@ -182,8 +192,18 @@
<find>appCa</find> <find>appCa</find>
<find>onSafeBrowsingHit</find> <find>onSafeBrowsingHit</find>
<find>SafeBrowsingResponse</find> <find>SafeBrowsingResponse</find>
<find>onReceivedHttpAuthRequest</find>
<find>iOSInAppWebViewUserPreferredContentMode</find> <find>iOSInAppWebViewUserPreferredContentMode</find>
<find>getDomainName</find>
<find>a</find>
<find>as</find>
<find>IABWebViewClient</find>
<find>clearCache</find>
<find>Auth</find>
<find>onReceivedHttpAuthRequestCallback</find>
<find>onReceivedHttpAuthRequest</find>
<find>cast</find>
<find>Protection</find>
<find>clear</find>
</findStrings> </findStrings>
<replaceStrings> <replaceStrings>
<replace>activity.getPreferences(0)</replace> <replace>activity.getPreferences(0)</replace>
@ -204,8 +224,6 @@
<component name="IdeDocumentHistory"> <component name="IdeDocumentHistory">
<option name="CHANGED_PATHS"> <option name="CHANGED_PATHS">
<list> <list>
<option value="$PROJECT_DIR$/lib/flutter_webview.dart" />
<option value="$PROJECT_DIR$/example/ios/Flutter/Debug.xcconfig" />
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowser.java" /> <option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowser.java" />
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowserClient.java" /> <option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowserClient.java" />
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowserDialog.java" /> <option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutterwebview/InAppBrowserDialog.java" />
@ -236,10 +254,8 @@
<option value="$PROJECT_DIR$/lib/in_app_browser.dart" /> <option value="$PROJECT_DIR$/lib/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_localhost_server.dart" /> <option value="$PROJECT_DIR$/lib/src/in_app_localhost_server.dart" />
<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/web_history.dart" /> <option value="$PROJECT_DIR$/lib/src/web_history.dart" />
<option value="$PROJECT_DIR$/example/lib/test.dart" /> <option value="$PROJECT_DIR$/example/lib/test.dart" />
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.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/chrome_safari_browser.dart" /> <option value="$PROJECT_DIR$/lib/src/chrome_safari_browser.dart" />
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" /> <option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
@ -248,17 +264,21 @@
<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/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/types.dart" /> <option value="$PROJECT_DIR$/lib/src/cookie_manager.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" /> <option value="$PROJECT_DIR$/lib/src/credentials_database.dart" />
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" /> <option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/example/pubspec.yaml" /> <option value="$PROJECT_DIR$/example/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" /> <option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
</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" />
@ -269,17 +289,6 @@
<foldersAlwaysOnTop value="true" /> <foldersAlwaysOnTop value="true" />
</navigator> </navigator>
<panes> <panes>
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="AndroidView"> <pane id="AndroidView">
<subPane> <subPane>
<expand> <expand>
@ -322,6 +331,12 @@
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" /> <item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="example" type="462c0819:PsiDirectoryNode" /> <item name="example" type="462c0819:PsiDirectoryNode" />
</path> </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> <path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" /> <item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" /> <item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
@ -347,6 +362,17 @@
<select /> <select />
</subPane> </subPane>
</pane> </pane>
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes> </panes>
</component> </component>
<component name="PropertiesComponent"> <component name="PropertiesComponent">
@ -358,7 +384,7 @@
<property name="android.project.structure.proportion" value="0.15" /> <property name="android.project.structure.proportion" value="0.15" />
<property name="dart.analysis.tool.window.force.activate" value="false" /> <property name="dart.analysis.tool.window.force.activate" value="false" />
<property name="io.flutter.reload.alreadyRun" value="true" /> <property name="io.flutter.reload.alreadyRun" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" /> <property name="last_opened_file_path" value="$PROJECT_DIR$/example/assets" />
<property name="project.structure.last.edited" value="SDK Location" /> <property name="project.structure.last.edited" value="SDK Location" />
<property name="project.structure.proportion" value="0.15" /> <property name="project.structure.proportion" value="0.15" />
<property name="project.structure.side.proportion" value="0.2" /> <property name="project.structure.side.proportion" value="0.2" />
@ -366,19 +392,19 @@
<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$/lib/src" /> <recent name="$PROJECT_DIR$/lib/src" />
<recent name="$PROJECT_DIR$/lib/in_app_browser.dart" /> <recent name="$PROJECT_DIR$/lib/in_app_browser.dart" />
<recent name="$PROJECT_DIR$/lib" /> <recent name="$PROJECT_DIR$/lib" />
<recent name="$PROJECT_DIR$/example/assets/images" /> <recent name="$PROJECT_DIR$/example/assets/images" />
<recent name="$PROJECT_DIR$/android/src/main/java" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
<recent name="$PROJECT_DIR$/example" />
<recent name="$PROJECT_DIR$/example/assets" />
<recent name="$PROJECT_DIR$/example/assets/images" />
<recent name="$PROJECT_DIR$/android/libs" />
</key> </key>
</component> </component>
<component name="RunDashboard"> <component name="RunDashboard">
@ -497,11 +523,11 @@
</todo-panel> </todo-panel>
</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="0" />
<editor active="true" /> <editor active="true" />
<layout> <layout>
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.5961821" visible="true" weight="0.15867944" /> <window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.59210527" visible="true" weight="0.15867944" />
<window_info id="Structure" order="1" sideWeight="0.40381792" side_tool="true" visible="true" weight="0.15867944" /> <window_info id="Structure" order="1" sideWeight="0.40789473" 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" />
@ -511,7 +537,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 anchor="bottom" id="Run" order="2" sideWeight="0.49307775" weight="0.4580311" /> <window_info anchor="bottom" id="Run" order="2" sideWeight="0.49307775" visible="true" weight="0.5274611" />
<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" />
@ -519,7 +545,7 @@
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" /> <window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50692225" side_tool="true" weight="0.38445595" /> <window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50692225" side_tool="true" weight="0.38445595" />
<window_info anchor="bottom" id="Version Control" order="9" weight="0.32953367" /> <window_info anchor="bottom" id="Version Control" order="9" weight="0.32953367" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" visible="true" weight="0.29430053" /> <window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.49533224" weight="0.29430053" />
<window_info anchor="bottom" id="Logcat" order="11" weight="0.32953367" /> <window_info anchor="bottom" id="Logcat" order="11" weight="0.32953367" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.226943" /> <window_info anchor="bottom" id="Messages" order="12" weight="0.226943" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" /> <window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
@ -547,19 +573,6 @@
</ignored-roots> </ignored-roots>
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/AppFrameworkInfo.plist">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="211">
<caret line="453" column="10" selection-start-line="453" selection-start-column="10" selection-end-line="453" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/.packages">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/android/.idea/gradle.xml"> <entry file="file://$PROJECT_DIR$/android/.idea/gradle.xml">
<provider selected="true" editor-type-id="text-editor" /> <provider selected="true" editor-type-id="text-editor" />
</entry> </entry>
@ -697,13 +710,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2100">
<caret line="140" selection-start-line="140" selection-end-line="140" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/web_history.dart" /> <entry file="file://$PROJECT_DIR$/lib/src/web_history.dart" />
<entry file="file://$PROJECT_DIR$/README.md"> <entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
@ -738,23 +744,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="180">
<caret line="31" column="32" selection-start-line="31" selection-start-column="32" selection-end-line="31" selection-end-column="32" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/chrome_safari_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="736">
<caret line="76" column="41" selection-start-line="76" selection-start-column="41" selection-end-line="76" selection-end-column="41" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/ios/Podfile"> <entry file="file://$PROJECT_DIR$/example/ios/Podfile">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="990"> <state relative-caret-position="990">
@ -807,53 +796,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-453">
<caret line="241" selection-start-line="241" selection-end-line="241" />
<folding>
<element signature="e#0#32#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="1401">
<caret line="222" column="12" selection-start-line="222" selection-start-column="12" selection-end-line="222" selection-end-column="12" />
<folding>
<element signature="e#0#22#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="514">
<caret line="73" column="12" selection-start-line="73" selection-start-column="12" selection-end-line="73" selection-end-column="12" />
</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="549">
<caret line="409" column="5" selection-start-line="409" selection-start-column="5" selection-end-line="409" selection-end-column="5" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="169" column="79" selection-start-line="169" selection-start-column="79" selection-end-line="169" selection-end-column="79" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30"> <state relative-caret-position="30">
@ -861,10 +803,10 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml"> <entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="345"> <state relative-caret-position="195">
<caret line="23" column="28" selection-start-line="23" selection-start-column="28" selection-end-line="23" selection-end-column="28" /> <caret line="32" column="47" selection-start-line="32" selection-start-column="47" selection-end-line="32" selection-end-column="47" />
</state> </state>
</provider> </provider>
</entry> </entry>
@ -878,20 +820,111 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/lib/src/chrome_safari_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="15" column="25" selection-start-line="15" selection-start-column="6" selection-end-line="15" selection-end-column="25" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/webview_options.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="150"> <state relative-caret-position="4635">
<caret line="10" column="22" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="22" /> <caret line="309" column="1" selection-start-line="309" selection-start-column="1" selection-end-line="309" selection-end-column="1" />
<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_browser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="419">
<caret line="411" column="2" selection-start-line="411" selection-start-column="2" selection-end-line="411" selection-end-column="106" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="416">
<caret line="73" column="12" selection-start-line="73" selection-start-column="12" selection-end-line="73" selection-end-column="12" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/in_app_webview.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-492">
<caret line="881" column="26" selection-start-line="881" selection-start-column="22" selection-end-line="881" selection-end-column="26" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/cookie_manager.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="395">
<caret line="61" column="51" selection-start-line="61" selection-start-column="21" selection-end-line="61" selection-end-column="51" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="147">
<caret line="327" column="89" selection-start-line="327" selection-start-column="89" selection-end-line="327" selection-end-column="89" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<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="557"> <state relative-caret-position="360">
<caret line="39" column="8" lean-forward="true" selection-start-line="39" selection-start-column="8" selection-end-line="39" selection-end-column="8" /> <caret line="24" column="42" selection-start-line="24" selection-start-column="42" selection-end-line="24" selection-end-column="42" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/http_auth_credentials_database.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="60">
<caret line="4" column="32" selection-start-line="4" selection-start-column="6" selection-end-line="4" selection-end-column="32" />
<folding>
<element signature="e#0#10#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/client1-crt.pem">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/assets/client1-crt.crt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="72">
<caret line="11" column="57" lean-forward="true" selection-start-line="11" selection-start-column="57" selection-end-line="11" selection-end-column="57" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="256">
<caret line="43" column="9" selection-start-line="43" selection-start-column="9" selection-end-line="43" selection-end-column="9" />
</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="253">
<caret line="88" column="12" selection-start-line="88" selection-start-column="12" selection-end-line="88" selection-end-column="12" />
<folding>
<element signature="e#0#22#0" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>

View File

@ -20,13 +20,16 @@
- Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android) - Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android)
- Added `onSafeBrowsingHit` event (available only for Android) - Added `onSafeBrowsingHit` event (available only for Android)
- Added `onJsAlert`, `onJsConfirm` and `onJsPrompt` events to manage javascript popup dialogs - Added `onJsAlert`, `onJsConfirm` and `onJsPrompt` events to manage javascript popup dialogs
- Fixed `InputConnection` error on Android - Added `onReceivedHttpAuthRequest` event
- Added `clearCache()` method
- Added `HttpAuthCredentialDatabase` class
### BREAKING CHANGES ### BREAKING CHANGES
- Deleted `WebResourceRequest` class - Deleted `WebResourceRequest` class
- Updated `WebResourceResponse` class - Updated `WebResourceResponse` class
- Updated `ConsoleMessageLevel` class - Updated `ConsoleMessageLevel` class
- Updated `onLoadResource` event - Updated `onLoadResource` event
- Updated `CookieManager` class
- WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSChromeCustomTabsOptions` - WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSChromeCustomTabsOptions`
## 1.2.1 ## 1.2.1

View File

@ -0,0 +1,25 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import java.util.HashMap;
import java.util.Map;
public class Credential {
public Long id;
public String username;
public String password;
public Long protectionSpaceId;
public Credential (Long id, String username, String password, Long protectionSpaceId) {
this.id = id;
this.username = username;
this.password = password;
this.protectionSpaceId = protectionSpaceId;
}
public Map<String, Object> toMap() {
Map<String, Object> credentialMap = new HashMap<>();
credentialMap.put("username", username);
credentialMap.put("password", password);
return credentialMap;
}
}

View File

@ -0,0 +1,15 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.provider.BaseColumns;
public class CredentialContract {
private CredentialContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "credential";
public static final String COLUMN_NAME_USERNAME = "username";
public static final String COLUMN_NAME_PASSWORD = "password";
public static final String COLUMN_NAME_PROTECTION_SPACE_ID = "protection_space_id";
}
}

View File

@ -0,0 +1,104 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.ContentValues;
import android.database.Cursor;
import java.util.ArrayList;
import java.util.List;
public class CredentialDao {
CredentialDatabaseHelper credentialDatabaseHelper;
String[] projection = {
CredentialContract.FeedEntry._ID,
CredentialContract.FeedEntry.COLUMN_NAME_USERNAME,
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD,
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID
};
public CredentialDao(CredentialDatabaseHelper credentialDatabaseHelper) {
this.credentialDatabaseHelper = credentialDatabaseHelper;
}
public List<Credential> getAllByProtectionSpaceId(Long protectionSpaceId) {
String selection = CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] selectionArgs = {protectionSpaceId.toString()};
Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query(
CredentialContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
List<Credential> credentials = new ArrayList<>();
while (cursor.moveToNext()) {
Long id = cursor.getLong(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry._ID));
String username = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME));
String password = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD));
credentials.add(new Credential(id, username, password, protectionSpaceId));
}
cursor.close();
return credentials;
}
public Credential find(String username, String password, Long protectionSpaceId) {
String selection = CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + " = ? AND " +
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + " = ? AND " +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] selectionArgs = {username, password, protectionSpaceId.toString()};
Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query(
CredentialContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
Credential credential = null;
if (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry._ID));
String rowUsername = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME));
String rowPassword = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD));
credential = new Credential(rowId, rowUsername, rowPassword, protectionSpaceId);
}
cursor.close();
return credential;
}
public long insert(Credential credential) {
ContentValues credentialValues = new ContentValues();
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME, credential.username);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, credential.password);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID, credential.protectionSpaceId);
return credentialDatabaseHelper.getWritableDatabase().insert(CredentialContract.FeedEntry.TABLE_NAME, null, credentialValues);
}
public long update(Credential credential) {
ContentValues credentialValues = new ContentValues();
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME, credential.username);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, credential.password);
String whereClause = CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] whereArgs = {credential.protectionSpaceId.toString()};
return credentialDatabaseHelper.getWritableDatabase().update(CredentialContract.FeedEntry.TABLE_NAME, credentialValues, whereClause, whereArgs);
}
public long delete(Credential credential) {
String whereClause = CredentialContract.FeedEntry._ID + " = ?";
String[] whereArgs = {credential.id.toString()};
return credentialDatabaseHelper.getWritableDatabase().delete(CredentialContract.FeedEntry.TABLE_NAME, whereClause, whereArgs);
}
}

View File

@ -0,0 +1,92 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.Context;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class CredentialDatabase {
private static CredentialDatabase instance;
static final String LOG_TAG = "CredentialDatabase";
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 2;
public static final String DATABASE_NAME = "CredentialDatabase.db";
public ProtectionSpaceDao protectionSpaceDao;
public CredentialDao credentialDao;
public CredentialDatabaseHelper db;
private CredentialDatabase() {}
private CredentialDatabase(CredentialDatabaseHelper db, ProtectionSpaceDao protectionSpaceDao, CredentialDao credentialDao) {
this.db = db;
this.protectionSpaceDao = protectionSpaceDao;
this.credentialDao = credentialDao;
}
public static CredentialDatabase getInstance(Context context) {
if (instance != null)
return instance;
CredentialDatabaseHelper db = new CredentialDatabaseHelper(context);
instance = new CredentialDatabase(db, new ProtectionSpaceDao(db), new CredentialDao(db));
return instance;
}
public List<Credential> getHttpAuthCredentials(String host, String protocol, String realm, Integer port) {
List<Credential> credentialList = new ArrayList<>();
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
credentialList = credentialDao.getAllByProtectionSpaceId(protectionSpace.id);
}
return credentialList;
}
public void clearAllAuthCredentials() {
db.clearAllTables(db.getWritableDatabase());
}
public void removeHttpAuthCredentials(String host, String protocol, String realm, Integer port) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
protectionSpaceDao.delete(protectionSpace);
}
}
public void removeHttpAuthCredential(String host, String protocol, String realm, Integer port, String username, String password) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
credentialDao.find(username, password, protectionSpace.id);
}
}
public void setHttpAuthCredential(String host, String protocol, String realm, Integer port, String username, String password) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
Long protectionSpaceId;
if (protectionSpace == null) {
protectionSpaceId = protectionSpaceDao.insert(new ProtectionSpace(null, host, protocol, realm, port));
} else {
protectionSpaceId = protectionSpace.id;
}
Credential credential = credentialDao.find(username, password, protectionSpaceId);
if (credential != null) {
boolean needUpdate = false;
if (!credential.username.equals(username)) {
credential.username = username;
needUpdate = true;
}
if (!credential.password.equals(password)) {
credential.password = password;
needUpdate = true;
}
if (needUpdate)
credentialDao.update(credential);
} else {
credential = new Credential(null, username, password, protectionSpaceId);
credential.id = credentialDao.insert(credential);
}
}
}

View File

@ -0,0 +1,66 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class CredentialDatabaseHelper extends SQLiteOpenHelper {
private static final String SQL_CREATE_PROTECTION_SPACE_TABLE =
"CREATE TABLE " + ProtectionSpaceContract.FeedEntry.TABLE_NAME + " (" +
ProtectionSpaceContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + " TEXT NOT NULL," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + " TEXT," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + " TEXT," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT + " INTEGER," +
"UNIQUE(" + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + ", " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + ", " +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + ", " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT +
")" +
");";
private static final String SQL_CREATE_CREDENTIAL_TABLE =
"CREATE TABLE " + CredentialContract.FeedEntry.TABLE_NAME + " (" +
CredentialContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + " TEXT NOT NULL," +
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + " TEXT NOT NULL," +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " INTEGER NOT NULL," +
"UNIQUE(" + CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + ", " + CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + ", " +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID +
")," +
"FOREIGN KEY (" + CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + ") REFERENCES " +
ProtectionSpaceContract.FeedEntry.TABLE_NAME + " (" + ProtectionSpaceContract.FeedEntry._ID + ") ON DELETE CASCADE" +
");";
private static final String SQL_DELETE_PROTECTION_SPACE_TABLE =
"DROP TABLE IF EXISTS " + ProtectionSpaceContract.FeedEntry.TABLE_NAME;
private static final String SQL_DELETE_CREDENTIAL_TABLE =
"DROP TABLE IF EXISTS " + CredentialContract.FeedEntry.TABLE_NAME;
public CredentialDatabaseHelper(Context context) {
super(context, CredentialDatabase.DATABASE_NAME, null, CredentialDatabase.DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_CREATE_CREDENTIAL_TABLE);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_DELETE_CREDENTIAL_TABLE);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
public void clearAllTables(SQLiteDatabase db) {
db.execSQL(SQL_DELETE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_DELETE_CREDENTIAL_TABLE);
onCreate(db);
}
}

View File

@ -0,0 +1,29 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import java.util.HashMap;
import java.util.Map;
public class ProtectionSpace {
public Long id;
public String host;
public String procotol;
public String realm;
public Integer port;
public ProtectionSpace (Long id, String host, String protocol, String realm, Integer port) {
this.id = id;
this.host = host;
this.procotol = protocol;
this.realm = realm;
this.port = port;
}
public Map<String, Object> toMap() {
Map<String, Object> protectionSpaceMap = new HashMap<>();
protectionSpaceMap.put("host", host);
protectionSpaceMap.put("protocol", procotol);
protectionSpaceMap.put("realm", realm);
protectionSpaceMap.put("port", port);
return protectionSpaceMap;
}
}

View File

@ -0,0 +1,16 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.provider.BaseColumns;
public class ProtectionSpaceContract {
private ProtectionSpaceContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "protection_space";
public static final String COLUMN_NAME_HOST = "host";
public static final String COLUMN_NAME_PROTOCOL = "protocol";
public static final String COLUMN_NAME_REALM = "realm";
public static final String COLUMN_NAME_PORT = "port";
}
}

View File

@ -0,0 +1,98 @@
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;
public class ProtectionSpaceDao {
CredentialDatabaseHelper credentialDatabaseHelper;
String[] projection = {
ProtectionSpaceContract.FeedEntry._ID,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT
};
public ProtectionSpaceDao(CredentialDatabaseHelper credentialDatabaseHelper) {
this.credentialDatabaseHelper = credentialDatabaseHelper;
}
public List<ProtectionSpace> getAll() {
SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase();
Cursor cursor = readableDatabase.query(
ProtectionSpaceContract.FeedEntry.TABLE_NAME,
projection,
null,
null,
null,
null,
null
);
List<ProtectionSpace> protectionSpaces = new ArrayList<>();
while (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry._ID));
String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST));
String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL));
String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM));
Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT));
protectionSpaces.add(new ProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort));
}
cursor.close();
return protectionSpaces;
}
public ProtectionSpace find(String host, String protocol, String realm, Integer port) {
SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase();
String selection = ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + " = ? AND " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + " = ? AND " +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + " = ? AND " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT + " = ?";
String[] selectionArgs = {host, protocol, realm, port.toString()};
Cursor cursor = readableDatabase.query(
ProtectionSpaceContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
ProtectionSpace protectionSpace = null;
if (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry._ID));
String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST));
String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL));
String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM));
Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT));
protectionSpace = new ProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort);
}
cursor.close();
return protectionSpace;
}
public long insert(ProtectionSpace protectionSpace) {
ContentValues protectionSpaceValues = new ContentValues();
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST, protectionSpace.host);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL, protectionSpace.procotol);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM, protectionSpace.realm);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT, protectionSpace.port);
return credentialDatabaseHelper.getWritableDatabase().insert(ProtectionSpaceContract.FeedEntry.TABLE_NAME, null, protectionSpaceValues);
};
public long delete(ProtectionSpace protectionSpace) {
String whereClause = ProtectionSpaceContract.FeedEntry._ID + " = ?";
String[] whereArgs = {protectionSpace.id.toString()};
return credentialDatabaseHelper.getWritableDatabase().delete(ProtectionSpaceContract.FeedEntry.TABLE_NAME, whereClause, whereArgs);
}
}

View File

@ -0,0 +1,119 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.Credential;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.CredentialDatabase;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.ProtectionSpace;
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.PluginRegistry;
@RequiresApi(api = Build.VERSION_CODES.O)
public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "CredentialDatabaseHandler";
public static PluginRegistry.Registrar registrar;
public static MethodChannel channel;
public static CredentialDatabase credentialDatabase;
public CredentialDatabaseHandler(PluginRegistry.Registrar r) {
registrar = r;
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser_credential_database");
channel.setMethodCallHandler(this);
credentialDatabase = CredentialDatabase.getInstance(registrar.context());
}
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
switch (call.method) {
case "getAllAuthCredentials":
{
List<Map<String, Object>> allCredentials = new ArrayList<>();
List<ProtectionSpace> protectionSpaces = credentialDatabase.protectionSpaceDao.getAll();
for (ProtectionSpace protectionSpace : protectionSpaces) {
List<Map<String, Object>> credentials = new ArrayList<>();
for (Credential credential : credentialDatabase.credentialDao.getAllByProtectionSpaceId(protectionSpace.id)) {
credentials.add(credential.toMap());
}
Map<String, Object> obj = new HashMap<>();
obj.put("protectionSpace", protectionSpace.toMap());
obj.put("credentials", credentials);
allCredentials.add(obj);
}
result.success(allCredentials);
}
break;
case "getHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
List<Map<String, Object>> credentials = new ArrayList<>();
for (Credential credential : credentialDatabase.getHttpAuthCredentials(host, protocol, realm, port)) {
credentials.add(credential.toMap());
}
result.success(credentials);
}
break;
case "setHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.setHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
}
break;
case "removeHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
}
break;
case "removeHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port);
result.success(true);
}
break;
case "clearAllAuthCredentials":
credentialDatabase.clearAllAuthCredentials();
result.success(true);
break;
default:
result.notImplemented();
}
}
}

View File

@ -245,6 +245,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
} else } else
result.success(null); result.success(null);
break; break;
case "clearCache":
if (webView != null)
webView.clearAllCache();
result.success(true);
break;
case "dispose": case "dispose":
dispose(); dispose();
result.success(true); result.success(true);

View File

@ -474,4 +474,9 @@ public class InAppBrowserActivity extends AppCompatActivity {
else else
result.success(false); result.success(false);
} }
public void clearCache() {
if (webView != null)
webView.clearAllCache();
}
} }

View File

@ -22,10 +22,10 @@
package com.pichillilorenzo.flutter_inappbrowser; package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Parcelable; import android.os.Parcelable;
import android.provider.Browser; import android.provider.Browser;
import android.net.Uri; import android.net.Uri;
@ -45,7 +45,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.MethodCall; 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.MethodChannel.MethodCallHandler;
@ -82,6 +81,9 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
instance = new InAppBrowserFlutterPlugin(registrar); instance = new InAppBrowserFlutterPlugin(registrar);
new MyCookieManager(registrar); new MyCookieManager(registrar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
new CredentialDatabaseHandler(registrar);
}
registrar registrar
.platformViewRegistry() .platformViewRegistry()
@ -305,6 +307,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
case "setSafeBrowsingWhitelist": case "setSafeBrowsingWhitelist":
setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result); setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result);
break; break;
case "clearCache":
clearCache(uuid);
result.success(true);
break;
default: default:
result.notImplemented(); result.notImplemented();
} }
@ -687,4 +693,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result); inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result);
result.success(false); result.success(false);
} }
public void clearCache(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.clearCache();
}
} }

View File

@ -1,7 +1,5 @@
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView; package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -9,9 +7,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.ConsoleMessage; import android.webkit.ConsoleMessage;
@ -31,8 +26,6 @@ import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.R; import com.pichillilorenzo.flutter_inappbrowser.R;
import com.pichillilorenzo.flutter_inappbrowser.RequestPermissionHandler;
import com.pichillilorenzo.flutter_inappbrowser.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -1,12 +1,14 @@
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView; package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.content.Intent; import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.os.Build; import android.os.Build;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import android.webkit.ClientCertRequest;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager; import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
@ -17,29 +19,48 @@ import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse; import android.webkit.WebResourceResponse;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.webkit.WebViewDatabase;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.Credential;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.CredentialDatabase;
import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView; import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface; import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
import com.pichillilorenzo.flutter_inappbrowser.Util; import com.pichillilorenzo.flutter_inappbrowser.Util;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
public class InAppWebViewClient extends WebViewClient { public class InAppWebViewClient extends WebViewClient {
private X509Certificate[] mCertificates;
private PrivateKey mPrivateKey;
protected static final String LOG_TAG = "IABWebViewClient"; protected static final String LOG_TAG = "IABWebViewClient";
private FlutterWebView flutterWebView; private FlutterWebView flutterWebView;
private InAppBrowserActivity inAppBrowserActivity; private InAppBrowserActivity inAppBrowserActivity;
Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>(); Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>();
long startPageTime = 0; long startPageTime = 0;
private static int previousAuthRequestFailureCount = 0;
private static List<Credential> credentialsProposed = null;
public InAppWebViewClient(Object obj) { public InAppWebViewClient(Object obj) {
super(); super();
@ -50,7 +71,7 @@ public class InAppWebViewClient extends WebViewClient {
prepareStatusCodeMapping(); prepareStatusCodeMapping();
} }
private void prepareStatusCodeMapping () { private void prepareStatusCodeMapping() {
statusCodeMapping.put(100, "Continue"); statusCodeMapping.put(100, "Continue");
statusCodeMapping.put(101, "Switching Protocols"); statusCodeMapping.put(101, "Switching Protocols");
statusCodeMapping.put(200, "OK"); statusCodeMapping.put(200, "OK");
@ -167,7 +188,6 @@ public class InAppWebViewClient extends WebViewClient {
} }
return super.shouldOverrideUrlLoading(webView, url); return super.shouldOverrideUrlLoading(webView, url);
} }
@ -208,6 +228,8 @@ public class InAppWebViewClient extends WebViewClient {
super.onPageFinished(view, url); super.onPageFinished(view, url);
webView.isLoading = false; webView.isLoading = false;
previousAuthRequestFailureCount = 0;
credentialsProposed = null;
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage // CB-10395 InAppBrowserFlutterPlugin'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) {
@ -229,11 +251,10 @@ public class InAppWebViewClient extends WebViewClient {
} }
}); });
} } else {
else { view.loadUrl("javascript:" + InAppWebView.consoleLogJS);
view.loadUrl("javascript:"+InAppWebView.consoleLogJS); view.loadUrl("javascript:" + JavaScriptBridgeInterface.flutterInAppBroserJSClass);
view.loadUrl("javascript:"+JavaScriptBridgeInterface.flutterInAppBroserJSClass); view.loadUrl("javascript:" + InAppWebView.platformReadyJS);
view.loadUrl("javascript:"+InAppWebView.platformReadyJS);
} }
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
@ -247,6 +268,8 @@ public class InAppWebViewClient extends WebViewClient {
super.onReceivedError(view, errorCode, description, failingUrl); super.onReceivedError(view, errorCode, description, failingUrl);
((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false; ((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
previousAuthRequestFailureCount = 0;
credentialsProposed = null;
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
@ -258,7 +281,8 @@ public class InAppWebViewClient extends WebViewClient {
} }
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error); previousAuthRequestFailureCount = 0;
credentialsProposed = null;
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
@ -291,6 +315,7 @@ public class InAppWebViewClient extends WebViewClient {
getChannel().invokeMethod("onLoadError", obj); getChannel().invokeMethod("onLoadError", obj);
handler.cancel(); handler.cancel();
//handler.proceed();
} }
/** /**
@ -298,11 +323,34 @@ public class InAppWebViewClient extends WebViewClient {
*/ */
@Override @Override
public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler, final String host, final String realm) { public void onReceivedHttpAuthRequest(final WebView view, final HttpAuthHandler handler, final String host, final String realm) {
URL url;
try {
url = new URL(view.getUrl());
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(LOG_TAG, e.getMessage());
credentialsProposed = null;
previousAuthRequestFailureCount = 0;
handler.cancel();
return;
}
final String protocol = url.getProtocol();
final int port = url.getPort();
previousAuthRequestFailureCount++;
Map<String, Object> obj = new HashMap<>(); Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null) if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid); obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("host", host); obj.put("host", host);
obj.put("protocol", protocol);
obj.put("realm", realm); obj.put("realm", realm);
obj.put("port", port);
obj.put("previousFailureCount", previousAuthRequestFailureCount);
getChannel().invokeMethod("onReceivedHttpAuthRequest", obj, new MethodChannel.Result() { getChannel().invokeMethod("onReceivedHttpAuthRequest", obj, new MethodChannel.Result() {
@Override @Override
@ -310,12 +358,11 @@ public class InAppWebViewClient extends WebViewClient {
if (response != null) { if (response != null) {
Map<String, Object> responseMap = (Map<String, Object>) response; Map<String, Object> responseMap = (Map<String, Object>) response;
Integer action = (Integer) responseMap.get("action"); Integer action = (Integer) responseMap.get("action");
Log.d(LOG_TAG, "\n\naction: " + action);
if (action != null) { if (action != null) {
switch (action) { switch (action) {
case 0: case 0:
credentialsProposed = null;
previousAuthRequestFailureCount = 0;
handler.cancel(); handler.cancel();
return; return;
case 1: case 1:
@ -323,12 +370,20 @@ public class InAppWebViewClient extends WebViewClient {
String password = (String) responseMap.get("password"); String password = (String) responseMap.get("password");
Boolean permanentPersistence = (Boolean) responseMap.get("permanentPersistence"); Boolean permanentPersistence = (Boolean) responseMap.get("permanentPersistence");
if (permanentPersistence != null && permanentPersistence && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (permanentPersistence != null && permanentPersistence && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WebViewDatabase.getInstance(view.getContext()).setHttpAuthUsernamePassword(host, realm, username, password); CredentialDatabase.getInstance(view.getContext()).setHttpAuthCredential(host, protocol, realm, port, username, password);
} }
handler.proceed(username, password); handler.proceed(username, password);
return; return;
case 2: case 2:
handler.useHttpAuthUsernamePassword(); if (credentialsProposed == null)
credentialsProposed = CredentialDatabase.getInstance(view.getContext()).getHttpAuthCredentials(host, protocol, realm, port);
if (credentialsProposed.size() > 0) {
Credential credential = credentialsProposed.remove(0);
handler.proceed(credential.username, credential.password);
} else {
handler.cancel();
}
//handler.useHttpAuthUsernamePassword();
return; return;
} }
} }
@ -349,6 +404,50 @@ public class InAppWebViewClient extends WebViewClient {
}); });
} }
// private void loadCertificateAndPrivateKey(InAppWebView webView) {
//
// try {
// String key1 = webView.registrar.lookupKeyForAsset("assets/certificate.pfx");
// AssetManager mg = webView.registrar.activeContext().getResources().getAssets();
// InputStream certificateFileStream = mg.open(key1);//getClass().getResourceAsStream();
//
// KeyStore keyStore = KeyStore.getInstance("PKCS12");
// String password = "";
// keyStore.load(certificateFileStream, password != null ? password.toCharArray() : null);
//
// Enumeration<String> aliases = keyStore.aliases();
// String alias = aliases.nextElement();
//
// Key key = keyStore.getKey(alias, password.toCharArray());
// if (key instanceof PrivateKey) {
// mPrivateKey = (PrivateKey)key;
// Certificate cert = keyStore.getCertificate(alias);
// mCertificates = new X509Certificate[1];
// mCertificates[0] = (X509Certificate)cert;
// }
//
// certificateFileStream.close();
//
// } catch (Exception e) {
// e.printStackTrace();
// Log.e(LOG_TAG, e.getMessage());
// }
// }
//
// @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
// @Override
// public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
// Log.d(LOG_TAG, request.getHost());
// Log.d(LOG_TAG, request.getKeyTypes().toString());
// Log.d(LOG_TAG, request.getPort() + "");
// Log.d(LOG_TAG, request.getPrincipals().toString());
//
// if (mCertificates == null || mPrivateKey == null) {
// loadCertificateAndPrivateKey((InAppWebView) view);
// }
// request.proceed(mPrivateKey, mCertificates);
// }
@Override @Override
public void onScaleChanged(WebView view, float oldScale, float newScale) { public void onScaleChanged(WebView view, float oldScale, float newScale) {
final InAppWebView webView = (InAppWebView) view; final InAppWebView webView = (InAppWebView) view;
@ -449,11 +548,13 @@ public class InAppWebViewClient extends WebViewClient {
} }
WebResourceResponse response = null; WebResourceResponse response = null;
try { if (webView.contentBlockerHandler.getRuleList().size() > 0) {
response = webView.contentBlockerHandler.checkUrl(webView, url); try {
} catch (Exception e) { response = webView.contentBlockerHandler.checkUrl(webView, url);
e.printStackTrace(); } catch (Exception e) {
Log.e(LOG_TAG, e.getMessage()); e.printStackTrace();
Log.e(LOG_TAG, e.getMessage());
}
} }
return response; return response;
} }

View File

@ -19,6 +19,8 @@ public class Util {
static final String LOG_TAG = "Util"; static final String LOG_TAG = "Util";
public static final String ANDROID_ASSET_URL = "file:///android_asset/"; public static final String ANDROID_ASSET_URL = "file:///android_asset/";
private Util() {}
public static String getUrlAsset(PluginRegistry.Registrar registrar, String assetFilePath) throws IOException { public static String getUrlAsset(PluginRegistry.Registrar registrar, String assetFilePath) throws IOException {
String key = registrar.lookupKeyForAsset(assetFilePath); String key = registrar.lookupKeyForAsset(assetFilePath);
AssetManager mg = registrar.activeContext().getResources().getAssets(); AssetManager mg = registrar.activeContext().getResources().getAssets();

View File

@ -40,7 +40,7 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> {
onPressed: () async { onPressed: () async {
await widget.browser.open("https://flutter.dev/", options: [ await widget.browser.open("https://flutter.dev/", options: [
AndroidChromeCustomTabsOptions(addShareButton: false), AndroidChromeCustomTabsOptions(addShareButton: false),
iOSChromeCustomTabsOptions(barCollapsingEnabled: true) iOSSafariOptions(barCollapsingEnabled: true)
]); ]);
}, },
child: Text("Open Chrome Safari Browser")), child: Text("Open Chrome Safari Browser")),

View File

@ -46,6 +46,24 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// HttpAuthCredentialDatabase.instance().clearAllAuthCredentials();
//
// HttpAuthCredentialDatabase.instance().getHttpAuthCredentials(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081)).then((credentials) {
// for (var credential in credentials )
// print("\n\nCREDENTIAL: ${credential.username} ${credential.password}\n\n");
// });
// HttpAuthCredentialDatabase.instance().getAllAuthCredentials().then((result) {
// for (var r in result) {
// ProtectionSpace protectionSpace = r["protectionSpace"];
// print("\n\nProtectionSpace: ${protectionSpace.protocol} ${protectionSpace.host}:");
// List<HttpAuthCredential> credentials = r["credentials"];
// for (var credential in credentials)
// print("\tCREDENTIAL: ${credential.username} ${credential.password}");
// }
// });
// HttpAuthCredentialDatabase.instance().setHttpAuthCredential(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081), HttpAuthCredential(username: "user 1", password: "password 1"));
// HttpAuthCredentialDatabase.instance().setHttpAuthCredential(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081), HttpAuthCredential(username: "user 2", password: "password 2"));
return Container( return Container(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
Container( Container(
@ -66,11 +84,13 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1", //initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
//initialUrl: "https://flutter.dev/", //initialUrl: "https://flutter.dev/",
//initialUrl: "chrome://safe-browsing/match?type=malware", //initialUrl: "chrome://safe-browsing/match?type=malware",
//initialUrl: "http://192.168.1.20:8081/",
//initialUrl: "https://192.168.1.20:4433/authenticate",
initialFile: "assets/index.html", initialFile: "assets/index.html",
initialHeaders: {}, initialHeaders: {},
initialOptions: [ initialOptions: [
InAppWebViewOptions( InAppWebViewOptions(
clearCache: true, //clearCache: true,
useShouldOverrideUrlLoading: true, useShouldOverrideUrlLoading: true,
useOnTargetBlank: true, useOnTargetBlank: true,
//useOnLoadResource: true, //useOnLoadResource: true,
@ -152,12 +172,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
"""); """);
}, },
onDownloadStart: (InAppWebViewController controller, String url) async { onDownloadStart: (InAppWebViewController controller, String url) async {
/*final taskId = await FlutterDownloader.enqueue( // final taskId = await FlutterDownloader.enqueue(
url: url, // url: url,
savedDir: await _findLocalPath(), // savedDir: await _findLocalPath(),
showNotification: true, // show download progress in status bar (for Android) // showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android) // openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);*/ // );
}, },
onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async { onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async {
if (scheme == "my-special-custom-scheme") { if (scheme == "my-special-custom-scheme") {
@ -220,6 +240,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY; SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY;
return new SafeBrowsingResponse(report: true, action: action); return new SafeBrowsingResponse(report: true, action: action);
}, },
onReceivedHttpAuthRequest: (InAppWebViewController controller, HttpAuthChallenge challenge) async {
print("HTTP AUTH REQUEST: " + challenge.protectionSpace.host + ", realm: " + challenge.protectionSpace.realm +
", previous failure count: " + challenge.previousFailureCount.toString());
return new HttpAuthResponse(username: "USERNAME", password: "PASSWORD", action: HttpAuthResponseAction.USE_SAVED_HTTP_AUTH_CREDENTIALS, permanentPersistence: true);
},
), ),
), ),
), ),

View File

@ -0,0 +1,177 @@
//
// CredentialDatabase.swift
// flutter_inappbrowser
//
// Created by Lorenzo Pichilli on 29/10/2019.
//
import Foundation
class CredentialDatabase: NSObject, FlutterPlugin {
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var credentialStore: URLCredentialStorage?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
CredentialDatabase.registrar = registrar
CredentialDatabase.credentialStore = URLCredentialStorage.shared
CredentialDatabase.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser_credential_database", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: CredentialDatabase.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "getAllAuthCredentials":
var allCredentials: [[String: Any?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
let protectionSpaceDict = [
"host": protectionSpace.host,
"protocol": protectionSpace.protocol,
"realm": protectionSpace.realm,
"port": protectionSpace.port
] as [String : Any?]
var crendentials: [[String: String?]] = []
for c in credentials {
let credential: [String: String?] = [
"username": c.value.user,
"password": c.value.password,
]
crendentials.append(credential)
}
let dict = [
"protectionSpace": protectionSpaceDict,
"credentials": crendentials
] as [String : Any]
allCredentials.append(dict)
}
result(allCredentials)
break
case "getHttpAuthCredentials":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
var crendentials: [[String: String?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
let credential: [String: String?] = [
"username": c.value.user,
"password": c.value.password,
]
crendentials.append(credential)
}
break
}
}
result(crendentials)
break
case "setHttpAuthCredential":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
let username = arguments!["username"] as! String
let password = arguments!["password"] as! String
let credential = URLCredential(user: username, password: password, persistence: .permanent)
CredentialDatabase.credentialStore!.set(credential, for: URLProtectionSpace(host: host, port: urlPort, protocol: urlProtocol, realm: realm, authenticationMethod: NSURLAuthenticationMethodHTTPBasic))
result(true)
break
case "removeHttpAuthCredential":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
let username = arguments!["username"] as! String
let password = arguments!["password"] as! String
var credential: URLCredential? = nil;
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
if c.value.user == username, c.value.password == password {
credential = c.value
protectionSpaceCredential = protectionSpace
break
}
}
}
if credential != nil {
break
}
}
if let c = credential, let protectionSpace = protectionSpaceCredential {
CredentialDatabase.credentialStore!.remove(c, for: protectionSpace)
}
result(true)
break
case "removeHttpAuthCredentials":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
var credentialsToRemove: [URLCredential] = [];
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
protectionSpaceCredential = protectionSpace
for c in credentials {
credentialsToRemove.append(c.value)
}
}
}
if let protectionSpace = protectionSpaceCredential {
for credential in credentialsToRemove {
CredentialDatabase.credentialStore!.remove(credential, for: protectionSpace)
}
}
result(true)
break
case "clearAllAuthCredentials":
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
for credential in credentials {
CredentialDatabase.credentialStore!.remove(credential.value, for: protectionSpace)
}
}
result(true)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
}

View File

@ -259,6 +259,12 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
case "getCopyBackForwardList": case "getCopyBackForwardList":
result((webView != nil) ? webView!.getCopyBackForwardList() : nil) result((webView != nil) ? webView!.getCopyBackForwardList() : nil)
break break
case "clearCache":
if webView != nil {
webView!.clearCache()
}
result(true)
break
case "dispose": case "dispose":
dispose() dispose()
result(true) result(true)

View File

@ -90,6 +90,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
var currentURL: URL? var currentURL: URL?
var WKNavigationMap: [String: [String: Any]] = [:] var WKNavigationMap: [String: [String: Any]] = [:]
var startPageTime: Int64 = 0 var startPageTime: Int64 = 0
static var credentialsProposed: [URLCredential] = []
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) { init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) {
super.init(frame: frame, configuration: configuration) super.init(frame: frame, configuration: configuration)
@ -203,7 +204,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
scrollView.showsVerticalScrollIndicator = (options?.verticalScrollBarEnabled)! scrollView.showsVerticalScrollIndicator = (options?.verticalScrollBarEnabled)!
scrollView.showsHorizontalScrollIndicator = (options?.horizontalScrollBarEnabled)! scrollView.showsHorizontalScrollIndicator = (options?.horizontalScrollBarEnabled)!
// options.debuggingEnabled is always enabled for iOS. // options.debuggingEnabled is always enabled for iOS.
if (options?.clearCache)! { if (options?.clearCache)! {
@ -721,6 +721,7 @@ 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 = [:] self.WKNavigationMap = [:]
currentURL = url currentURL = url
InAppWebView.credentialsProposed = []
onLoadStop(url: (currentURL?.absoluteString)!) onLoadStop(url: (currentURL?.absoluteString)!)
evaluateJavaScript(platformReadyJS, completionHandler: nil) evaluateJavaScript(platformReadyJS, completionHandler: nil)
@ -739,6 +740,8 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
} }
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
InAppWebView.credentialsProposed = []
onLoadError(url: (currentURL?.absoluteString)!, error: error) onLoadError(url: (currentURL?.absoluteString)!, error: error)
if IABController != nil { if IABController != nil {
@ -749,51 +752,100 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
} }
public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let host = challenge.protectionSpace.host
let realm = challenge.protectionSpace.realm print (challenge.protectionSpace.authenticationMethod)
onReceivedHttpAuthRequest(host: host, realm: realm, result: {(result) -> Void in
if result is FlutterError { if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic ||
print((result as! FlutterError).message) challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodDefault ||
} challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest {
else if (result as? NSObject) == FlutterMethodNotImplemented { let host = challenge.protectionSpace.host
completionHandler(.performDefaultHandling, nil) let prot = challenge.protectionSpace.protocol
} let realm = challenge.protectionSpace.realm
else { let port = challenge.protectionSpace.port
//WKWebsiteDataStore.default() onReceivedHttpAuthRequest(challenge: challenge, result: {(result) -> Void in
//URLCredentialStorage() if result is FlutterError {
var response: [String: Any] print((result as! FlutterError).message)
if let r = result {
response = r as! [String: Any]
var action = response["action"] as? Int
action = action != nil ? action : 0;
switch action {
case 0:
completionHandler(.cancelAuthenticationChallenge, nil)
break
case 1:
let username = response["username"] as! String
let password = response["password"] as! String
let permanentPersistence = response["permanentPersistence"] as? Bool ?? false
let persistence = (permanentPersistence) ? URLCredential.Persistence.permanent : URLCredential.Persistence.forSession
let credential = URLCredential(user: username, password: password, persistence: persistence)
completionHandler(.useCredential, credential)
break
case 2:
if let credential = challenge.proposedCredential {
completionHandler(.useCredential, credential)
}
else {
completionHandler(.performDefaultHandling, nil)
}
break
default:
completionHandler(.performDefaultHandling, nil)
}
return;
} }
completionHandler(.performDefaultHandling, nil) else if (result as? NSObject) == FlutterMethodNotImplemented {
} completionHandler(.performDefaultHandling, nil)
}) }
else {
var response: [String: Any]
if let r = result {
response = r as! [String: Any]
var action = response["action"] as? Int
action = action != nil ? action : 0;
switch action {
case 0:
InAppWebView.credentialsProposed = []
completionHandler(.cancelAuthenticationChallenge, nil)
break
case 1:
let username = response["username"] as! String
let password = response["password"] as! String
let permanentPersistence = response["permanentPersistence"] as? Bool ?? false
let persistence = (permanentPersistence) ? URLCredential.Persistence.permanent : URLCredential.Persistence.forSession
let credential = URLCredential(user: username, password: password, persistence: persistence)
completionHandler(.useCredential, credential)
break
case 2:
if InAppWebView.credentialsProposed.count == 0 {
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == prot && protectionSpace.port == port {
for credential in credentials {
InAppWebView.credentialsProposed.append(credential.value)
}
break
}
}
}
if InAppWebView.credentialsProposed.count == 0, let credential = challenge.proposedCredential {
InAppWebView.credentialsProposed.append(credential)
}
if let credential = InAppWebView.credentialsProposed.popLast() {
completionHandler(.useCredential, credential)
}
else {
completionHandler(.performDefaultHandling, nil)
}
break
default:
completionHandler(.performDefaultHandling, nil)
}
return;
}
completionHandler(.performDefaultHandling, nil)
}
})
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
/// TODO: correspond to onSslError event of Android
completionHandler(.performDefaultHandling, nil)
// guard let serverTrust = challenge.protectionSpace.serverTrust else {
// completionHandler(.performDefaultHandling, nil)
// return
// }
// //if checkValidity(of: serverTrust) {
// if true {
// let exceptions = SecTrustCopyExceptions(serverTrust)
// SecTrustSetExceptions(serverTrust, exceptions)
// let credential = URLCredential(trust: serverTrust)
// completionHandler(.useCredential, credential)
// } else {
// // Show a UI here warning the user the server credentials are
// // invalid, and cancel the load.
// completionHandler(.cancelAuthenticationChallenge, nil)
// }
}
else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
/// TODO: load certificates
completionHandler(.performDefaultHandling, nil)
}
else {
completionHandler(.performDefaultHandling, nil)
}
} }
fileprivate func createAlertDialog(message: String?, responseMessage: String?, confirmButtonTitle: String?, completionHandler: @escaping () -> Void) { fileprivate func createAlertDialog(message: String?, responseMessage: String?, confirmButtonTitle: String?, completionHandler: @escaping () -> Void) {
@ -1101,8 +1153,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
} }
} }
public func onReceivedHttpAuthRequest(host: String, realm: String?, result: FlutterResult?) { public func onReceivedHttpAuthRequest(challenge: URLAuthenticationChallenge, result: FlutterResult?) {
var arguments: [String: Any] = ["host": host, "realm": realm as Any] var arguments: [String: Any?] = [
"host": challenge.protectionSpace.host,
"protocol": challenge.protectionSpace.protocol,
"realm": challenge.protectionSpace.realm,
"port": challenge.protectionSpace.port,
"previousFailureCount": challenge.previousFailureCount
]
if IABController != nil { if IABController != nil {
arguments["uuid"] = IABController!.uuid arguments["uuid"] = IABController!.uuid
} }

View File

@ -52,17 +52,17 @@ class MyCookieManager: NSObject, FlutterPlugin {
let name = arguments!["name"] as! String let name = arguments!["name"] as! String
let domain = arguments!["domain"] as! String let domain = arguments!["domain"] as! String
let path = arguments!["path"] as! String let path = arguments!["path"] as! String
MyCookieManager.deleteCookie(url: url, name: name, domain: domain, path: path, result: result); MyCookieManager.deleteCookie(url: url, name: name, domain: domain, path: path, result: result)
break; break;
case "deleteCookies": case "deleteCookies":
let url = arguments!["url"] as! String let url = arguments!["url"] as! String
let domain = arguments!["domain"] as! String let domain = arguments!["domain"] as! String
let path = arguments!["path"] as! String let path = arguments!["path"] as! String
MyCookieManager.deleteCookies(url: url, domain: domain, path: path, result: result); MyCookieManager.deleteCookies(url: url, domain: domain, path: path, result: result)
break; break;
case "deleteAllCookies": case "deleteAllCookies":
MyCookieManager.deleteAllCookies(result: result); MyCookieManager.deleteAllCookies(result: result)
break; break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break

View File

@ -61,6 +61,8 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
} else { } else {
// Fallback on earlier versions // Fallback on earlier versions
} }
CredentialDatabase(registrar: registrar)
} }
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
@ -237,6 +239,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
case "getCopyBackForwardList": case "getCopyBackForwardList":
result(self.getCopyBackForwardList(uuid: uuid)) result(self.getCopyBackForwardList(uuid: uuid))
break break
case "clearCache":
self.clearCache(uuid: uuid)
result(true)
break
default: default:
result(FlutterMethodNotImplemented) result(FlutterMethodNotImplemented)
break break
@ -746,6 +752,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
return nil return nil
} }
func clearCache(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.clearCache()
}
}
} }
// Helper function inserted by Swift 4.2 migrator. // Helper function inserted by Swift 4.2 migrator.

View File

@ -30,3 +30,4 @@ export 'src/chrome_safari_browser.dart';
export 'src/in_app_localhost_server.dart'; export 'src/in_app_localhost_server.dart';
export 'src/webview_options.dart'; export 'src/webview_options.dart';
export 'src/content_blocker.dart'; export 'src/content_blocker.dart';
export 'src/http_auth_credentials_database.dart';

View File

@ -70,7 +70,7 @@ class ChromeSafariBrowser {
///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar. ///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar.
///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles. ///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles.
///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles. ///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles.
Future<void> open(String url, {List<ChromeCustomTabsOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async { Future<void> open(String url, {List<ChromeSafariBrowserOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async {
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!'); this.throwIsAlreadyOpened(message: 'Cannot open $url!');

View File

@ -4,32 +4,34 @@ import 'package:flutter/services.dart';
/// ///
///**NOTE for iOS**: available from iOS 11.0+. ///**NOTE for iOS**: available from iOS 11.0+.
class CookieManager { class CookieManager {
static bool _initialized = false; static CookieManager _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_cookiemanager'); static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_cookiemanager');
static void _init () { static CookieManager instance() {
_channel.setMethodCallHandler(handleMethod); return (_instance != null) ? _instance : _init();
_initialized = true;
} }
static Future<dynamic> handleMethod(MethodCall call) async { static CookieManager _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = new CookieManager();
return _instance;
}
static Future<dynamic> _handleMethod(MethodCall call) async {
} }
///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie. The cookie being set will be ignored if it is expired. ///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie. The cookie being set will be ignored if it is expired.
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null`, its default value will be the domain name of [url]. ///If [domain] is `null`, its default value will be the domain name of [url].
static Future<void> setCookie(String url, String name, String value, Future<void> setCookie(String url, String name, String value,
{ String domain, { String domain,
String path = "/", String path = "/",
int expiresDate, int expiresDate,
int maxAge, int maxAge,
bool isSecure }) async { bool isSecure }) async {
if (!_initialized)
_init();
if (domain == null) if (domain == null)
domain = getDomainName(url); domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
@ -51,10 +53,7 @@ class CookieManager {
} }
///Gets all the cookies for the given [url]. ///Gets all the cookies for the given [url].
static Future<List<Map<String, dynamic>>> getCookies(String url) async { Future<List<Map<String, dynamic>>> getCookies(String url) async {
if (!_initialized)
_init();
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
@ -69,10 +68,7 @@ class CookieManager {
} }
///Gets a cookie by its [name] for the given [url]. ///Gets a cookie by its [name] for the given [url].
static Future<Map<String, dynamic>> getCookie(String url, String name) async { Future<Map<String, dynamic>> getCookie(String url, String name) async {
if (!_initialized)
_init();
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
@ -92,12 +88,9 @@ class CookieManager {
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url]. ///If [domain] is `null` or empty, its default value will be the domain name of [url].
static Future<void> deleteCookie(String url, String name, {String domain = "", String path = "/"}) async { Future<void> deleteCookie(String url, String name, {String domain = "", String path = "/"}) async {
if (!_initialized)
_init();
if (domain == null || domain.isEmpty) if (domain == null || domain.isEmpty)
domain = getDomainName(url); domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty); assert(name != null && name.isNotEmpty);
@ -116,12 +109,9 @@ class CookieManager {
/// ///
///The default value of [path] is `"/"`. ///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url]. ///If [domain] is `null` or empty, its default value will be the domain name of [url].
static Future<void> deleteCookies(String url, {String domain = "", String path = "/"}) async { Future<void> deleteCookies(String url, {String domain = "", String path = "/"}) async {
if (!_initialized)
_init();
if (domain == null || domain.isEmpty) if (domain == null || domain.isEmpty)
domain = getDomainName(url); domain = _getDomainName(url);
assert(url != null && url.isNotEmpty); assert(url != null && url.isNotEmpty);
assert(domain != null && url.isNotEmpty); assert(domain != null && url.isNotEmpty);
@ -135,15 +125,12 @@ class CookieManager {
} }
///Removes all cookies. ///Removes all cookies.
static Future<void> deleteAllCookies() async { Future<void> deleteAllCookies() async {
if (!_initialized)
_init();
Map<String, dynamic> args = <String, dynamic>{}; Map<String, dynamic> args = <String, dynamic>{};
await _channel.invokeMethod('deleteAllCookies', args); await _channel.invokeMethod('deleteAllCookies', args);
} }
static String getDomainName(String url) { String _getDomainName(String url) {
Uri uri = Uri.parse(url); Uri uri = Uri.parse(url);
String domain = uri.host; String domain = uri.host;
if (domain == null) if (domain == null)

View File

@ -0,0 +1,93 @@
import 'types.dart';
import 'package:flutter/services.dart';
///
class HttpAuthCredentialDatabase {
static HttpAuthCredentialDatabase _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_credential_database');
///
static HttpAuthCredentialDatabase instance() {
return (_instance != null) ? _instance : _init();
}
static HttpAuthCredentialDatabase _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = new HttpAuthCredentialDatabase();
return _instance;
}
static Future<dynamic> _handleMethod(MethodCall call) async {
}
///
Future<List<Map<String, dynamic>>> getAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
List<dynamic> allCredentials = await _channel.invokeMethod('getAllAuthCredentials', args);
List<Map<String, dynamic>> result = [];
for (Map<dynamic, dynamic> map in allCredentials) {
Map<dynamic, dynamic> protectionSpace = map["protectionSpace"];
List<dynamic> credentials = map["credentials"];
result.add({
"protectionSpace": ProtectionSpace(host: protectionSpace["host"], protocol: protectionSpace["protocol"], realm: protectionSpace["realm"], port: protectionSpace["port"]),
"credentials": credentials.map((credential) => HttpAuthCredential(username: credential["username"], password: credential["password"])).toList()
});
}
return result;
}
///
Future<List<HttpAuthCredential>> getHttpAuthCredentials(ProtectionSpace protectionSpace) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
List<dynamic> credentialList = await _channel.invokeMethod('getHttpAuthCredentials', args);
List<HttpAuthCredential> credentials = [];
for (Map<dynamic, dynamic> credential in credentialList) {
credentials.add(HttpAuthCredential(username: credential["username"], password: credential["password"]));
}
return credentials;
}
///
Future<void> setHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
args.putIfAbsent("username", () => credential.username);
args.putIfAbsent("password", () => credential.password);
await _channel.invokeMethod('setHttpAuthCredential', args);
}
///
Future<void> removeHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
args.putIfAbsent("username", () => credential.username);
args.putIfAbsent("password", () => credential.password);
await _channel.invokeMethod('removeHttpAuthCredential', args);
}
///
Future<void> removeHttpAuthCredentials(ProtectionSpace protectionSpace) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
await _channel.invokeMethod('removeHttpAuthCredentials', args);
}
///
Future<void> clearAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
await _channel.invokeMethod('clearAllAuthCredentials', args);
}
}

View File

@ -4,6 +4,7 @@ import 'dart:collection';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart'; import 'package:flutter_inappbrowser/src/webview_options.dart';
import 'http_auth_credentials_database.dart';
import 'types.dart'; import 'types.dart';
import 'channel_manager.dart'; import 'channel_manager.dart';
import 'in_app_webview.dart' show InAppWebViewController; import 'in_app_webview.dart' show InAppWebViewController;
@ -408,10 +409,8 @@ class InAppBrowser {
///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request. ///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request.
/// ///
///[host] represents the host requiring authentication. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
/// Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, HttpAuthChallenge challenge) {
///[realm] represents the realm for which authentication is required
Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, String realm) {
} }

View File

@ -10,6 +10,7 @@ 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 'http_auth_credentials_database.dart';
import 'types.dart'; import 'types.dart';
import 'in_app_browser.dart'; import 'in_app_browser.dart';
import 'channel_manager.dart'; import 'channel_manager.dart';
@ -178,9 +179,7 @@ class InAppWebView extends StatefulWidget {
///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request. ///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request.
/// ///
///[host] represents the host requiring authentication. ///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
///
///[realm] represents the realm for which authentication is required
final onReceivedHttpAuthRequestCallback onReceivedHttpAuthRequest; final onReceivedHttpAuthRequestCallback onReceivedHttpAuthRequest;
///Initial url that will be loaded. ///Initial url that will be loaded.
@ -251,7 +250,8 @@ class _InAppWebViewState extends State<InAppWebView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {}; Map<String, dynamic> initialOptions = {};
widget.initialOptions.forEach((webViewOption) { widget.initialOptions.forEach((webViewOption) {
initialOptions.addAll(webViewOption.toMap()); if ((Platform.isAndroid && webViewOption is AndroidOptions) || (Platform.isIOS && webViewOption is iOSOptions))
initialOptions.addAll(webViewOption.toMap());
}); });
if (defaultTargetPlatform == TargetPlatform.android) { if (defaultTargetPlatform == TargetPlatform.android) {
@ -478,11 +478,16 @@ class InAppWebViewController {
break; break;
case "onReceivedHttpAuthRequest": case "onReceivedHttpAuthRequest":
String host = call.arguments["host"]; String host = call.arguments["host"];
String protocol = call.arguments["protocol"];
String realm = call.arguments["realm"]; String realm = call.arguments["realm"];
int port = call.arguments["port"];
int previousFailureCount = call.arguments["previousFailureCount"];
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port);
var challenge = HttpAuthChallenge(previousFailureCount: previousFailureCount, protectionSpace: protectionSpace);
if (_widget != null && _widget.onReceivedHttpAuthRequest != null) if (_widget != null && _widget.onReceivedHttpAuthRequest != null)
return (await _widget.onReceivedHttpAuthRequest(this, host, realm))?.toMap(); return (await _widget.onReceivedHttpAuthRequest(this, challenge))?.toMap();
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
return (await _inAppBrowser.onReceivedHttpAuthRequest(host, realm))?.toMap(); return (await _inAppBrowser.onReceivedHttpAuthRequest(host, challenge))?.toMap();
break; break;
case "onCallJsHandler": case "onCallJsHandler":
String handlerName = call.arguments["handlerName"]; String handlerName = call.arguments["handlerName"];
@ -960,6 +965,16 @@ class InAppWebViewController {
return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args); return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
} }
///Clear all the webview's cache
Future<void> clearCache() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('clearCache', args);
}
///Dispose/Destroy the WebView. ///Dispose/Destroy the WebView.
Future<void> _dispose() async { Future<void> _dispose() async {
await _channel.invokeMethod('dispose'); await _channel.invokeMethod('dispose');

View File

@ -1,5 +1,6 @@
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'in_app_webview.dart'; import 'in_app_webview.dart';
var uuidGenerator = new Uuid(); var uuidGenerator = new Uuid();
@ -141,7 +142,7 @@ class GeolocationPermissionShowPromptResponse {
} }
} }
///
class JsAlertResponseAction { class JsAlertResponseAction {
final int _value; final int _value;
const JsAlertResponseAction._internal(this._value); const JsAlertResponseAction._internal(this._value);
@ -150,6 +151,7 @@ class JsAlertResponseAction {
static const CONFIRM = const JsAlertResponseAction._internal(0); static const CONFIRM = const JsAlertResponseAction._internal(0);
} }
///
class JsAlertResponse { class JsAlertResponse {
String message; String message;
String confirmButtonTitle; String confirmButtonTitle;
@ -168,6 +170,7 @@ class JsAlertResponse {
} }
} }
///
class JsConfirmResponseAction { class JsConfirmResponseAction {
final int _value; final int _value;
const JsConfirmResponseAction._internal(this._value); const JsConfirmResponseAction._internal(this._value);
@ -177,6 +180,7 @@ class JsConfirmResponseAction {
static const CANCEL = const JsConfirmResponseAction._internal(1); static const CANCEL = const JsConfirmResponseAction._internal(1);
} }
///
class JsConfirmResponse { class JsConfirmResponse {
String message; String message;
String confirmButtonTitle; String confirmButtonTitle;
@ -197,6 +201,7 @@ class JsConfirmResponse {
} }
} }
///
class JsPromptResponseAction { class JsPromptResponseAction {
final int _value; final int _value;
const JsPromptResponseAction._internal(this._value); const JsPromptResponseAction._internal(this._value);
@ -206,6 +211,7 @@ class JsPromptResponseAction {
static const CANCEL = const JsPromptResponseAction._internal(1); static const CANCEL = const JsPromptResponseAction._internal(1);
} }
///
class JsPromptResponse { class JsPromptResponse {
String message; String message;
String defaultValue; String defaultValue;
@ -230,6 +236,7 @@ class JsPromptResponse {
} }
} }
///
class SafeBrowsingThreat { class SafeBrowsingThreat {
final int _value; final int _value;
const SafeBrowsingThreat._internal(this._value); const SafeBrowsingThreat._internal(this._value);
@ -247,6 +254,7 @@ class SafeBrowsingThreat {
static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4); static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4);
} }
///
class SafeBrowsingResponseAction { class SafeBrowsingResponseAction {
final int _value; final int _value;
const SafeBrowsingResponseAction._internal(this._value); const SafeBrowsingResponseAction._internal(this._value);
@ -256,6 +264,8 @@ class SafeBrowsingResponseAction {
static const PROCEED = const SafeBrowsingResponseAction._internal(1); static const PROCEED = const SafeBrowsingResponseAction._internal(1);
static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2); static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2);
} }
///
class SafeBrowsingResponse { class SafeBrowsingResponse {
bool report; bool report;
SafeBrowsingResponseAction action; SafeBrowsingResponseAction action;
@ -270,6 +280,7 @@ class SafeBrowsingResponse {
} }
} }
///
class HttpAuthResponseAction { class HttpAuthResponseAction {
final int _value; final int _value;
const HttpAuthResponseAction._internal(this._value); const HttpAuthResponseAction._internal(this._value);
@ -277,9 +288,10 @@ class HttpAuthResponseAction {
static const CANCEL = const HttpAuthResponseAction._internal(0); static const CANCEL = const HttpAuthResponseAction._internal(0);
static const PROCEED = const HttpAuthResponseAction._internal(1); static const PROCEED = const HttpAuthResponseAction._internal(1);
static const USE_HTTP_AUTH_USERNAME_PASSWORD = const HttpAuthResponseAction._internal(2); static const USE_SAVED_HTTP_AUTH_CREDENTIALS = const HttpAuthResponseAction._internal(2);
} }
///
class HttpAuthResponse { class HttpAuthResponse {
String username; String username;
String password; String password;
@ -298,6 +310,168 @@ class HttpAuthResponse {
} }
} }
///
class HttpAuthChallenge {
int previousFailureCount;
ProtectionSpace protectionSpace;
HttpAuthChallenge({@required this.previousFailureCount, @required this.protectionSpace}): assert(previousFailureCount != null && protectionSpace != null);
}
///
class ProtectionSpace {
String host;
String protocol;
String realm;
int port;
ProtectionSpace({@required this.host, @required this.protocol, this.realm, this.port}): assert(host != null && protocol != null);
}
///
class HttpAuthCredential {
String username;
String password;
HttpAuthCredential({@required this.username, @required this.password}): assert(username != null && password != null);
}
///
class AndroidInAppWebViewCacheMode {
final int _value;
const AndroidInAppWebViewCacheMode._internal(this._value);
toValue() => _value;
static const LOAD_DEFAULT = const AndroidInAppWebViewCacheMode._internal(-1);
static const LOAD_CACHE_ELSE_NETWORK = const AndroidInAppWebViewCacheMode._internal(1);
static const LOAD_NO_CACHE = const AndroidInAppWebViewCacheMode._internal(2);
static const LOAD_CACHE_ONLY = const AndroidInAppWebViewCacheMode._internal(3);
}
///
class AndroidInAppWebViewModeMenuItem {
final int _value;
const AndroidInAppWebViewModeMenuItem._internal(this._value);
toValue() => _value;
static const MENU_ITEM_NONE = const AndroidInAppWebViewModeMenuItem._internal(0);
static const MENU_ITEM_SHARE = const AndroidInAppWebViewModeMenuItem._internal(1);
static const MENU_ITEM_WEB_SEARCH = const AndroidInAppWebViewModeMenuItem._internal(2);
static const MENU_ITEM_PROCESS_TEXT = const AndroidInAppWebViewModeMenuItem._internal(4);
}
///
class AndroidInAppWebViewForceDark {
final int _value;
const AndroidInAppWebViewForceDark._internal(this._value);
toValue() => _value;
static const FORCE_DARK_OFF = const AndroidInAppWebViewForceDark._internal(0);
static const FORCE_DARK_AUTO = const AndroidInAppWebViewForceDark._internal(1);
static const FORCE_DARK_ON = const AndroidInAppWebViewForceDark._internal(2);
}
///
class AndroidInAppWebViewLayoutAlgorithm {
final String _value;
const AndroidInAppWebViewLayoutAlgorithm._internal(this._value);
toValue() => _value;
static const NORMAL = const AndroidInAppWebViewLayoutAlgorithm._internal("NORMAL");
static const TEXT_AUTOSIZING = const AndroidInAppWebViewLayoutAlgorithm._internal("TEXT_AUTOSIZING");
}
///
class AndroidInAppWebViewMixedContentMode {
final int _value;
const AndroidInAppWebViewMixedContentMode._internal(this._value);
toValue() => _value;
static const MIXED_CONTENT_ALWAYS_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(0);
static const MIXED_CONTENT_NEVER_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(1);
static const MIXED_CONTENT_COMPATIBILITY_MODE = const AndroidInAppWebViewMixedContentMode._internal(2);
}
///
class iOSInAppWebViewSelectionGranularity {
final int _value;
const iOSInAppWebViewSelectionGranularity._internal(this._value);
toValue() => _value;
static const CHARACTER = const iOSInAppWebViewSelectionGranularity._internal(0);
static const DYNAMIC = const iOSInAppWebViewSelectionGranularity._internal(1);
}
///
class iOSInAppWebViewDataDetectorTypes {
final String _value;
const iOSInAppWebViewDataDetectorTypes._internal(this._value);
toValue() => _value;
static const NONE = const iOSInAppWebViewDataDetectorTypes._internal("NONE");
static const PHONE_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER");
static const LINK = const iOSInAppWebViewDataDetectorTypes._internal("LINK");
static const ADDRESS = const iOSInAppWebViewDataDetectorTypes._internal("ADDRESS");
static const CALENDAR_EVENT = const iOSInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT");
static const TRACKING_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER");
static const FLIGHT_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER");
static const LOOKUP_SUGGESTION = const iOSInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION");
static const SPOTLIGHT_SUGGESTION = const iOSInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION");
static const ALL = const iOSInAppWebViewDataDetectorTypes._internal("ALL");
}
///
class iOSInAppWebViewUserPreferredContentMode {
final int _value;
const iOSInAppWebViewUserPreferredContentMode._internal(this._value);
toValue() => _value;
static const RECOMMENDED = const iOSInAppWebViewUserPreferredContentMode._internal(0);
static const MOBILE = const iOSInAppWebViewUserPreferredContentMode._internal(1);
static const DESKTOP = const iOSInAppWebViewUserPreferredContentMode._internal(2);
}
///
class iOSWebViewOptionsPresentationStyle {
final int _value;
const iOSWebViewOptionsPresentationStyle._internal(this._value);
toValue() => _value;
static const FULL_SCREEN = const iOSWebViewOptionsPresentationStyle._internal(0);
static const PAGE_SHEET = const iOSWebViewOptionsPresentationStyle._internal(1);
static const FORM_SHEET = const iOSWebViewOptionsPresentationStyle._internal(2);
static const CURRENT_CONTEXT = const iOSWebViewOptionsPresentationStyle._internal(3);
static const CUSTOM = const iOSWebViewOptionsPresentationStyle._internal(4);
static const OVER_FULL_SCREEN = const iOSWebViewOptionsPresentationStyle._internal(5);
static const OVER_CURRENT_CONTEXT = const iOSWebViewOptionsPresentationStyle._internal(6);
static const POPOVER = const iOSWebViewOptionsPresentationStyle._internal(7);
static const NONE = const iOSWebViewOptionsPresentationStyle._internal(8);
static const AUTOMATIC = const iOSWebViewOptionsPresentationStyle._internal(9);
}
///
class iOSWebViewOptionsTransitionStyle {
final int _value;
const iOSWebViewOptionsTransitionStyle._internal(this._value);
toValue() => _value;
static const COVER_VERTICAL = const iOSWebViewOptionsTransitionStyle._internal(0);
static const FLIP_HORIZONTAL = const iOSWebViewOptionsTransitionStyle._internal(1);
static const CROSS_DISSOLVE = const iOSWebViewOptionsTransitionStyle._internal(2);
static const PARTIAL_CURL = const iOSWebViewOptionsTransitionStyle._internal(3);
}
///
class iOSSafariOptionsDismissButtonStyle {
final int _value;
const iOSSafariOptionsDismissButtonStyle._internal(this._value);
toValue() => _value;
static const DONE = const iOSSafariOptionsDismissButtonStyle._internal(0);
static const CLOSE = const iOSSafariOptionsDismissButtonStyle._internal(1);
static const CANCEL = const iOSSafariOptionsDismissButtonStyle._internal(2);
}
typedef onWebViewCreatedCallback = void Function(InAppWebViewController controller); typedef onWebViewCreatedCallback = void Function(InAppWebViewController controller);
typedef onWebViewLoadStartCallback = void Function(InAppWebViewController controller, String url); typedef onWebViewLoadStartCallback = void Function(InAppWebViewController controller, String url);
typedef onWebViewLoadStopCallback = void Function(InAppWebViewController controller, String url); typedef onWebViewLoadStopCallback = void Function(InAppWebViewController controller, String url);
@ -315,4 +489,4 @@ typedef onJsAlertCallback = Future<JsAlertResponse> Function(InAppWebViewControl
typedef onJsConfirmCallback = Future<JsConfirmResponse> Function(InAppWebViewController controller, String message); typedef onJsConfirmCallback = Future<JsConfirmResponse> Function(InAppWebViewController controller, String message);
typedef onJsPromptCallback = Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue); typedef onJsPromptCallback = Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue);
typedef onSafeBrowsingHitCallback = Future<SafeBrowsingResponse> Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType); typedef onSafeBrowsingHitCallback = Future<SafeBrowsingResponse> Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType);
typedef onReceivedHttpAuthRequestCallback = Future<HttpAuthResponse> Function(InAppWebViewController controller, String url, String realm); typedef onReceivedHttpAuthRequestCallback = Future<HttpAuthResponse> Function(InAppWebViewController controller, HttpAuthChallenge challenge);

View File

@ -1,7 +1,11 @@
import 'dart:io'; import 'dart:io';
import 'types.dart';
import 'package:flutter_inappbrowser/src/content_blocker.dart'; import 'package:flutter_inappbrowser/src/content_blocker.dart';
class AndroidOptions {}
class iOSOptions {}
class WebViewOptions { class WebViewOptions {
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return {}; return {};
@ -14,7 +18,7 @@ class BrowserOptions {
} }
} }
class InAppWebViewOptions implements WebViewOptions, BrowserOptions { class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions, iOSOptions {
bool useShouldOverrideUrlLoading; bool useShouldOverrideUrlLoading;
bool useOnLoadResource; bool useOnLoadResource;
bool useOnDownloadStart; bool useOnDownloadStart;
@ -66,58 +70,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions {
} }
} }
class AndroidInAppWebViewCacheMode { class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions {
final int _value;
const AndroidInAppWebViewCacheMode._internal(this._value);
toValue() => _value;
static const LOAD_DEFAULT = const AndroidInAppWebViewCacheMode._internal(-1);
static const LOAD_CACHE_ELSE_NETWORK = const AndroidInAppWebViewCacheMode._internal(1);
static const LOAD_NO_CACHE = const AndroidInAppWebViewCacheMode._internal(2);
static const LOAD_CACHE_ONLY = const AndroidInAppWebViewCacheMode._internal(3);
}
class AndroidInAppWebViewModeMenuItem {
final int _value;
const AndroidInAppWebViewModeMenuItem._internal(this._value);
toValue() => _value;
static const MENU_ITEM_NONE = const AndroidInAppWebViewModeMenuItem._internal(0);
static const MENU_ITEM_SHARE = const AndroidInAppWebViewModeMenuItem._internal(1);
static const MENU_ITEM_WEB_SEARCH = const AndroidInAppWebViewModeMenuItem._internal(2);
static const MENU_ITEM_PROCESS_TEXT = const AndroidInAppWebViewModeMenuItem._internal(4);
}
class AndroidInAppWebViewForceDark {
final int _value;
const AndroidInAppWebViewForceDark._internal(this._value);
toValue() => _value;
static const FORCE_DARK_OFF = const AndroidInAppWebViewForceDark._internal(0);
static const FORCE_DARK_AUTO = const AndroidInAppWebViewForceDark._internal(1);
static const FORCE_DARK_ON = const AndroidInAppWebViewForceDark._internal(2);
}
class AndroidInAppWebViewLayoutAlgorithm {
final String _value;
const AndroidInAppWebViewLayoutAlgorithm._internal(this._value);
toValue() => _value;
static const NORMAL = const AndroidInAppWebViewLayoutAlgorithm._internal("NORMAL");
static const TEXT_AUTOSIZING = const AndroidInAppWebViewLayoutAlgorithm._internal("TEXT_AUTOSIZING");
}
class AndroidInAppWebViewMixedContentMode {
final int _value;
const AndroidInAppWebViewMixedContentMode._internal(this._value);
toValue() => _value;
static const MIXED_CONTENT_ALWAYS_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(0);
static const MIXED_CONTENT_NEVER_ALLOW = const AndroidInAppWebViewMixedContentMode._internal(1);
static const MIXED_CONTENT_COMPATIBILITY_MODE = const AndroidInAppWebViewMixedContentMode._internal(2);
}
class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions {
bool clearSessionCache; bool clearSessionCache;
bool builtInZoomControls; bool builtInZoomControls;
bool displayZoomControls; bool displayZoomControls;
@ -211,43 +164,7 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions {
} }
} }
class iOSInAppWebViewSelectionGranularity { class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions, iOSOptions {
final int _value;
const iOSInAppWebViewSelectionGranularity._internal(this._value);
toValue() => _value;
static const CHARACTER = const iOSInAppWebViewSelectionGranularity._internal(0);
static const DYNAMIC = const iOSInAppWebViewSelectionGranularity._internal(1);
}
class iOSInAppWebViewDataDetectorTypes {
final String _value;
const iOSInAppWebViewDataDetectorTypes._internal(this._value);
toValue() => _value;
static const NONE = const iOSInAppWebViewDataDetectorTypes._internal("NONE");
static const PHONE_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("PHONE_NUMBER");
static const LINK = const iOSInAppWebViewDataDetectorTypes._internal("LINK");
static const ADDRESS = const iOSInAppWebViewDataDetectorTypes._internal("ADDRESS");
static const CALENDAR_EVENT = const iOSInAppWebViewDataDetectorTypes._internal("CALENDAR_EVENT");
static const TRACKING_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("TRACKING_NUMBER");
static const FLIGHT_NUMBER = const iOSInAppWebViewDataDetectorTypes._internal("FLIGHT_NUMBER");
static const LOOKUP_SUGGESTION = const iOSInAppWebViewDataDetectorTypes._internal("LOOKUP_SUGGESTION");
static const SPOTLIGHT_SUGGESTION = const iOSInAppWebViewDataDetectorTypes._internal("SPOTLIGHT_SUGGESTION");
static const ALL = const iOSInAppWebViewDataDetectorTypes._internal("ALL");
}
class iOSInAppWebViewUserPreferredContentMode {
final int _value;
const iOSInAppWebViewUserPreferredContentMode._internal(this._value);
toValue() => _value;
static const RECOMMENDED = const iOSInAppWebViewUserPreferredContentMode._internal(0);
static const MOBILE = const iOSInAppWebViewUserPreferredContentMode._internal(1);
static const DESKTOP = const iOSInAppWebViewUserPreferredContentMode._internal(2);
}
class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions {
bool disallowOverScroll; bool disallowOverScroll;
bool enableViewportScale; bool enableViewportScale;
bool suppressesIncrementalRendering; bool suppressesIncrementalRendering;
@ -298,7 +215,7 @@ class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions {
} }
} }
class InAppBrowserOptions implements BrowserOptions { class InAppBrowserOptions implements BrowserOptions, AndroidOptions, iOSOptions {
bool hidden; bool hidden;
bool toolbarTop; bool toolbarTop;
String toolbarTopBackgroundColor; String toolbarTopBackgroundColor;
@ -319,7 +236,7 @@ class InAppBrowserOptions implements BrowserOptions {
} }
} }
class AndroidInAppBrowserOptions implements BrowserOptions { class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
bool hideTitleBar; bool hideTitleBar;
bool closeOnCannotGoBack; bool closeOnCannotGoBack;
bool progressBar; bool progressBar;
@ -336,47 +253,19 @@ class AndroidInAppBrowserOptions implements BrowserOptions {
} }
} }
class iOSInAppBrowserOptionsPresentationStyle { class iOSInAppBrowserOptions implements BrowserOptions, iOSOptions {
final int _value;
const iOSInAppBrowserOptionsPresentationStyle._internal(this._value);
toValue() => _value;
static const FULL_SCREEN = const iOSInAppBrowserOptionsPresentationStyle._internal(0);
static const PAGE_SHEET = const iOSInAppBrowserOptionsPresentationStyle._internal(1);
static const FORM_SHEET = const iOSInAppBrowserOptionsPresentationStyle._internal(2);
static const CURRENT_CONTEXT = const iOSInAppBrowserOptionsPresentationStyle._internal(3);
static const CUSTOM = const iOSInAppBrowserOptionsPresentationStyle._internal(4);
static const OVER_FULL_SCREEN = const iOSInAppBrowserOptionsPresentationStyle._internal(5);
static const OVER_CURRENT_CONTEXT = const iOSInAppBrowserOptionsPresentationStyle._internal(6);
static const POPOVER = const iOSInAppBrowserOptionsPresentationStyle._internal(7);
static const NONE = const iOSInAppBrowserOptionsPresentationStyle._internal(8);
static const AUTOMATIC = const iOSInAppBrowserOptionsPresentationStyle._internal(9);
}
class iOSInAppBrowserOptionsTransitionStyle {
final int _value;
const iOSInAppBrowserOptionsTransitionStyle._internal(this._value);
toValue() => _value;
static const COVER_VERTICAL = const iOSInAppBrowserOptionsTransitionStyle._internal(0);
static const FLIP_HORIZONTAL = const iOSInAppBrowserOptionsTransitionStyle._internal(1);
static const CROSS_DISSOLVE = const iOSInAppBrowserOptionsTransitionStyle._internal(2);
static const PARTIAL_CURL = const iOSInAppBrowserOptionsTransitionStyle._internal(3);
}
class iOSInAppBrowserOptions implements BrowserOptions {
bool toolbarBottom; bool toolbarBottom;
String toolbarBottomBackgroundColor; String toolbarBottomBackgroundColor;
bool toolbarBottomTranslucent; bool toolbarBottomTranslucent;
String closeButtonCaption; String closeButtonCaption;
String closeButtonColor; String closeButtonColor;
iOSInAppBrowserOptionsPresentationStyle presentationStyle; iOSWebViewOptionsPresentationStyle presentationStyle;
iOSInAppBrowserOptionsTransitionStyle transitionStyle; iOSWebViewOptionsTransitionStyle transitionStyle;
bool spinner; bool spinner;
iOSInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "", iOSInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "",
this.closeButtonColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN, this.closeButtonColor = "", this.presentationStyle = iOSWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true}); this.transitionStyle = iOSWebViewOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
@ -393,13 +282,13 @@ class iOSInAppBrowserOptions implements BrowserOptions {
} }
} }
class ChromeCustomTabsOptions { class ChromeSafariBrowserOptions {
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return {}; return {};
} }
} }
class AndroidChromeCustomTabsOptions implements ChromeCustomTabsOptions { class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, AndroidOptions {
bool addShareButton; bool addShareButton;
bool showTitle; bool showTitle;
String toolbarBackgroundColor; String toolbarBackgroundColor;
@ -420,28 +309,18 @@ class AndroidChromeCustomTabsOptions implements ChromeCustomTabsOptions {
} }
} }
class iOSChromeCustomTabsOptionsDismissButtonStyle { class iOSSafariOptions implements ChromeSafariBrowserOptions, iOSOptions {
final int _value;
const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(this._value);
toValue() => _value;
static const DONE = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(0);
static const CLOSE = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(1);
static const CANCEL = const iOSChromeCustomTabsOptionsDismissButtonStyle._internal(2);
}
class iOSChromeCustomTabsOptions implements ChromeCustomTabsOptions {
bool entersReaderIfAvailable; bool entersReaderIfAvailable;
bool barCollapsingEnabled; bool barCollapsingEnabled;
iOSChromeCustomTabsOptionsDismissButtonStyle dismissButtonStyle; iOSSafariOptionsDismissButtonStyle dismissButtonStyle;
String preferredBarTintColor; String preferredBarTintColor;
String preferredControlTintColor; String preferredControlTintColor;
iOSInAppBrowserOptionsPresentationStyle presentationStyle; iOSWebViewOptionsPresentationStyle presentationStyle;
iOSInAppBrowserOptionsTransitionStyle transitionStyle; iOSWebViewOptionsTransitionStyle transitionStyle;
iOSChromeCustomTabsOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = iOSChromeCustomTabsOptionsDismissButtonStyle.DONE, iOSSafariOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = iOSSafariOptionsDismissButtonStyle.DONE,
this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN, this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = iOSWebViewOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL}); this.transitionStyle = iOSWebViewOptionsTransitionStyle.COVER_VERTICAL});
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {