added HttpAuthCredentialDatabase class, clearCache method, onReceivedHttpAuthRequest event
This commit is contained in:
parent
fed99ec0e9
commit
68ff79c716
|
@ -15,20 +15,34 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<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/InAppWebView/InputAwareWebView.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/Credential.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/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$/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/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/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/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$/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/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_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" />
|
||||
|
@ -52,59 +66,11 @@
|
|||
<component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_XL_API_24" />
|
||||
<component name="FileEditorManager">
|
||||
<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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="557">
|
||||
<caret line="39" column="8" lean-forward="true" selection-start-line="39" selection-start-column="8" selection-end-line="39" selection-end-column="8" />
|
||||
</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 relative-caret-position="360">
|
||||
<caret line="24" column="42" selection-start-line="24" selection-start-column="42" selection-end-line="24" selection-end-column="42" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
|
@ -112,8 +78,8 @@
|
|||
<file pinned="false" current-in-tab="false">
|
||||
<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" />
|
||||
<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>
|
||||
|
@ -124,17 +90,50 @@
|
|||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/example/assets/index.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="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" />
|
||||
</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="-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">
|
||||
<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" />
|
||||
<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>
|
||||
|
@ -142,6 +141,27 @@
|
|||
</provider>
|
||||
</entry>
|
||||
</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>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
|
@ -154,16 +174,6 @@
|
|||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<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>uuid_</find>
|
||||
<find>javaScriptHandlersMap</find>
|
||||
|
@ -182,8 +192,18 @@
|
|||
<find>appCa</find>
|
||||
<find>onSafeBrowsingHit</find>
|
||||
<find>SafeBrowsingResponse</find>
|
||||
<find>onReceivedHttpAuthRequest</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>
|
||||
<replaceStrings>
|
||||
<replace>activity.getPreferences(0)</replace>
|
||||
|
@ -204,8 +224,6 @@
|
|||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<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/InAppBrowserClient.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/src/in_app_localhost_server.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$/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$/lib/src/chrome_safari_browser.dart" />
|
||||
<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$/example/assets/index.html" />
|
||||
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
|
||||
<option value="$PROJECT_DIR$/lib/src/types.dart" />
|
||||
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
|
||||
<option value="$PROJECT_DIR$/lib/src/cookie_manager.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_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/lib/inline_example.screen.dart" />
|
||||
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
|
||||
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="y" value="23" />
|
||||
<option name="width" value="1920" />
|
||||
<option name="height" value="1057" />
|
||||
|
@ -269,17 +289,6 @@
|
|||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<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">
|
||||
<subPane>
|
||||
<expand>
|
||||
|
@ -322,6 +331,12 @@
|
|||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="example" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="assets" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
|
||||
|
@ -347,6 +362,17 @@
|
|||
<select />
|
||||
</subPane>
|
||||
</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>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
|
@ -358,7 +384,7 @@
|
|||
<property name="android.project.structure.proportion" value="0.15" />
|
||||
<property name="dart.analysis.tool.window.force.activate" value="false" />
|
||||
<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.proportion" value="0.15" />
|
||||
<property name="project.structure.side.proportion" value="0.2" />
|
||||
|
@ -366,19 +392,19 @@
|
|||
<property name="show.migrate.to.gradle.popup" value="false" />
|
||||
</component>
|
||||
<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">
|
||||
<recent name="$PROJECT_DIR$/example/assets" />
|
||||
<recent name="$PROJECT_DIR$/lib/src" />
|
||||
<recent name="$PROJECT_DIR$/lib/in_app_browser.dart" />
|
||||
<recent name="$PROJECT_DIR$/lib" />
|
||||
<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>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
|
@ -497,11 +523,11 @@
|
|||
</todo-panel>
|
||||
</component>
|
||||
<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" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.5961821" visible="true" weight="0.15867944" />
|
||||
<window_info id="Structure" order="1" sideWeight="0.40381792" side_tool="true" 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.40789473" side_tool="true" visible="true" weight="0.15867944" />
|
||||
<window_info id="Designer" order="2" />
|
||||
<window_info id="Build Variants" order="3" side_tool="true" />
|
||||
<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 anchor="bottom" id="Message" order="0" />
|
||||
<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="Cvs" order="4" weight="0.25" />
|
||||
<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="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 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="Messages" order="12" weight="0.226943" />
|
||||
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
|
||||
|
@ -547,19 +573,6 @@
|
|||
</ignored-roots>
|
||||
</component>
|
||||
<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">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
|
@ -697,13 +710,6 @@
|
|||
</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="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$/README.md">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
|
@ -738,23 +744,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="990">
|
||||
|
@ -807,53 +796,6 @@
|
|||
</state>
|
||||
</provider>
|
||||
</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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="30">
|
||||
|
@ -861,10 +803,10 @@
|
|||
</state>
|
||||
</provider>
|
||||
</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">
|
||||
<state relative-caret-position="345">
|
||||
<caret line="23" column="28" selection-start-line="23" selection-start-column="28" selection-end-line="23" selection-end-column="28" />
|
||||
<state relative-caret-position="195">
|
||||
<caret line="32" column="47" selection-start-line="32" selection-start-column="47" selection-end-line="32" selection-end-column="47" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
|
@ -878,20 +820,111 @@
|
|||
</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="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">
|
||||
<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" />
|
||||
<state relative-caret-position="4635">
|
||||
<caret line="309" column="1" selection-start-line="309" selection-start-column="1" selection-end-line="309" selection-end-column="1" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/lib/src/in_app_browser.dart">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="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">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="557">
|
||||
<caret line="39" column="8" lean-forward="true" selection-start-line="39" selection-start-column="8" selection-end-line="39" selection-end-column="8" />
|
||||
<state relative-caret-position="360">
|
||||
<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>
|
||||
</provider>
|
||||
</entry>
|
||||
|
|
|
@ -20,13 +20,16 @@
|
|||
- Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android)
|
||||
- Added `onSafeBrowsingHit` event (available only for Android)
|
||||
- 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
|
||||
- Deleted `WebResourceRequest` class
|
||||
- Updated `WebResourceResponse` class
|
||||
- Updated `ConsoleMessageLevel` class
|
||||
- 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`
|
||||
|
||||
## 1.2.1
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -245,6 +245,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
|
|||
} else
|
||||
result.success(null);
|
||||
break;
|
||||
case "clearCache":
|
||||
if (webView != null)
|
||||
webView.clearAllCache();
|
||||
result.success(true);
|
||||
break;
|
||||
case "dispose":
|
||||
dispose();
|
||||
result.success(true);
|
||||
|
|
|
@ -474,4 +474,9 @@ public class InAppBrowserActivity extends AppCompatActivity {
|
|||
else
|
||||
result.success(false);
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
if (webView != null)
|
||||
webView.clearAllCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
package com.pichillilorenzo.flutter_inappbrowser;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Browser;
|
||||
import android.net.Uri;
|
||||
|
@ -45,7 +45,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.app.FlutterApplication;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
||||
|
@ -82,6 +81,9 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
|
|||
instance = new InAppBrowserFlutterPlugin(registrar);
|
||||
|
||||
new MyCookieManager(registrar);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
new CredentialDatabaseHandler(registrar);
|
||||
}
|
||||
|
||||
registrar
|
||||
.platformViewRegistry()
|
||||
|
@ -305,6 +307,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
|
|||
case "setSafeBrowsingWhitelist":
|
||||
setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result);
|
||||
break;
|
||||
case "clearCache":
|
||||
clearCache(uuid);
|
||||
result.success(true);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
}
|
||||
|
@ -687,4 +693,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
|
|||
inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result);
|
||||
result.success(false);
|
||||
}
|
||||
|
||||
public void clearCache(String uuid) {
|
||||
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
|
||||
if (inAppBrowserActivity != null)
|
||||
inAppBrowserActivity.clearCache();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -9,9 +7,6 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
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.InAppBrowserFlutterPlugin;
|
||||
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.Map;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.net.http.SslError;
|
||||
import android.os.Build;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.webkit.ClientCertRequest;
|
||||
import android.webkit.CookieManager;
|
||||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.HttpAuthHandler;
|
||||
|
@ -17,29 +19,48 @@ import android.webkit.WebResourceRequest;
|
|||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.webkit.WebViewDatabase;
|
||||
|
||||
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.InAppBrowserActivity;
|
||||
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
|
||||
import com.pichillilorenzo.flutter_inappbrowser.JavaScriptBridgeInterface;
|
||||
import com.pichillilorenzo.flutter_inappbrowser.Util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
|
||||
public class InAppWebViewClient extends WebViewClient {
|
||||
|
||||
private X509Certificate[] mCertificates;
|
||||
private PrivateKey mPrivateKey;
|
||||
|
||||
|
||||
protected static final String LOG_TAG = "IABWebViewClient";
|
||||
private FlutterWebView flutterWebView;
|
||||
private InAppBrowserActivity inAppBrowserActivity;
|
||||
Map<Integer, String> statusCodeMapping = new HashMap<Integer, String>();
|
||||
long startPageTime = 0;
|
||||
private static int previousAuthRequestFailureCount = 0;
|
||||
private static List<Credential> credentialsProposed = null;
|
||||
|
||||
public InAppWebViewClient(Object obj) {
|
||||
super();
|
||||
|
@ -50,7 +71,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
prepareStatusCodeMapping();
|
||||
}
|
||||
|
||||
private void prepareStatusCodeMapping () {
|
||||
private void prepareStatusCodeMapping() {
|
||||
statusCodeMapping.put(100, "Continue");
|
||||
statusCodeMapping.put(101, "Switching Protocols");
|
||||
statusCodeMapping.put(200, "OK");
|
||||
|
@ -167,7 +188,6 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
|
||||
return super.shouldOverrideUrlLoading(webView, url);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -208,6 +228,8 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
super.onPageFinished(view, url);
|
||||
|
||||
webView.isLoading = false;
|
||||
previousAuthRequestFailureCount = 0;
|
||||
credentialsProposed = null;
|
||||
|
||||
// CB-10395 InAppBrowserFlutterPlugin's WebView not storing cookies reliable to local device storage
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
|
@ -229,11 +251,10 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
view.loadUrl("javascript:"+InAppWebView.consoleLogJS);
|
||||
view.loadUrl("javascript:"+JavaScriptBridgeInterface.flutterInAppBroserJSClass);
|
||||
view.loadUrl("javascript:"+InAppWebView.platformReadyJS);
|
||||
} else {
|
||||
view.loadUrl("javascript:" + InAppWebView.consoleLogJS);
|
||||
view.loadUrl("javascript:" + JavaScriptBridgeInterface.flutterInAppBroserJSClass);
|
||||
view.loadUrl("javascript:" + InAppWebView.platformReadyJS);
|
||||
}
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
|
@ -247,6 +268,8 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
|
||||
((inAppBrowserActivity != null) ? inAppBrowserActivity.webView : flutterWebView.webView).isLoading = false;
|
||||
previousAuthRequestFailureCount = 0;
|
||||
credentialsProposed = null;
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
|
@ -258,7 +281,8 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
|
||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
previousAuthRequestFailureCount = 0;
|
||||
credentialsProposed = null;
|
||||
|
||||
Map<String, Object> obj = new HashMap<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
|
@ -291,6 +315,7 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
getChannel().invokeMethod("onLoadError", obj);
|
||||
|
||||
handler.cancel();
|
||||
//handler.proceed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,11 +323,34 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
*/
|
||||
@Override
|
||||
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<>();
|
||||
if (inAppBrowserActivity != null)
|
||||
obj.put("uuid", inAppBrowserActivity.uuid);
|
||||
obj.put("host", host);
|
||||
obj.put("protocol", protocol);
|
||||
obj.put("realm", realm);
|
||||
obj.put("port", port);
|
||||
obj.put("previousFailureCount", previousAuthRequestFailureCount);
|
||||
|
||||
getChannel().invokeMethod("onReceivedHttpAuthRequest", obj, new MethodChannel.Result() {
|
||||
@Override
|
||||
|
@ -310,12 +358,11 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
if (response != null) {
|
||||
Map<String, Object> responseMap = (Map<String, Object>) response;
|
||||
Integer action = (Integer) responseMap.get("action");
|
||||
|
||||
Log.d(LOG_TAG, "\n\naction: " + action);
|
||||
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case 0:
|
||||
credentialsProposed = null;
|
||||
previousAuthRequestFailureCount = 0;
|
||||
handler.cancel();
|
||||
return;
|
||||
case 1:
|
||||
|
@ -323,12 +370,20 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
String password = (String) responseMap.get("password");
|
||||
Boolean permanentPersistence = (Boolean) responseMap.get("permanentPersistence");
|
||||
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);
|
||||
return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
public void onScaleChanged(WebView view, float oldScale, float newScale) {
|
||||
final InAppWebView webView = (InAppWebView) view;
|
||||
|
@ -449,11 +548,13 @@ public class InAppWebViewClient extends WebViewClient {
|
|||
}
|
||||
|
||||
WebResourceResponse response = null;
|
||||
try {
|
||||
response = webView.contentBlockerHandler.checkUrl(webView, url);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, e.getMessage());
|
||||
if (webView.contentBlockerHandler.getRuleList().size() > 0) {
|
||||
try {
|
||||
response = webView.contentBlockerHandler.checkUrl(webView, url);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(LOG_TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ public class Util {
|
|||
static final String LOG_TAG = "Util";
|
||||
public static final String ANDROID_ASSET_URL = "file:///android_asset/";
|
||||
|
||||
private Util() {}
|
||||
|
||||
public static String getUrlAsset(PluginRegistry.Registrar registrar, String assetFilePath) throws IOException {
|
||||
String key = registrar.lookupKeyForAsset(assetFilePath);
|
||||
AssetManager mg = registrar.activeContext().getResources().getAssets();
|
||||
|
|
|
@ -40,7 +40,7 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> {
|
|||
onPressed: () async {
|
||||
await widget.browser.open("https://flutter.dev/", options: [
|
||||
AndroidChromeCustomTabsOptions(addShareButton: false),
|
||||
iOSChromeCustomTabsOptions(barCollapsingEnabled: true)
|
||||
iOSSafariOptions(barCollapsingEnabled: true)
|
||||
]);
|
||||
},
|
||||
child: Text("Open Chrome Safari Browser")),
|
||||
|
|
|
@ -46,6 +46,24 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||
|
||||
@override
|
||||
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(
|
||||
child: Column(children: <Widget>[
|
||||
Container(
|
||||
|
@ -66,11 +84,13 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
|
||||
//initialUrl: "https://flutter.dev/",
|
||||
//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",
|
||||
initialHeaders: {},
|
||||
initialOptions: [
|
||||
InAppWebViewOptions(
|
||||
clearCache: true,
|
||||
//clearCache: true,
|
||||
useShouldOverrideUrlLoading: true,
|
||||
useOnTargetBlank: true,
|
||||
//useOnLoadResource: true,
|
||||
|
@ -152,12 +172,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||
""");
|
||||
},
|
||||
onDownloadStart: (InAppWebViewController controller, String url) async {
|
||||
/*final taskId = await FlutterDownloader.enqueue(
|
||||
url: url,
|
||||
savedDir: await _findLocalPath(),
|
||||
showNotification: true, // show download progress in status bar (for Android)
|
||||
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
|
||||
);*/
|
||||
// final taskId = await FlutterDownloader.enqueue(
|
||||
// url: url,
|
||||
// savedDir: await _findLocalPath(),
|
||||
// showNotification: true, // show download progress in status bar (for Android)
|
||||
// openFileFromNotification: true, // click on notification to open downloaded file (for Android)
|
||||
// );
|
||||
},
|
||||
onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async {
|
||||
if (scheme == "my-special-custom-scheme") {
|
||||
|
@ -220,6 +240,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
|
|||
SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY;
|
||||
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);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -259,6 +259,12 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
|
|||
case "getCopyBackForwardList":
|
||||
result((webView != nil) ? webView!.getCopyBackForwardList() : nil)
|
||||
break
|
||||
case "clearCache":
|
||||
if webView != nil {
|
||||
webView!.clearCache()
|
||||
}
|
||||
result(true)
|
||||
break
|
||||
case "dispose":
|
||||
dispose()
|
||||
result(true)
|
||||
|
|
|
@ -90,6 +90,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
var currentURL: URL?
|
||||
var WKNavigationMap: [String: [String: Any]] = [:]
|
||||
var startPageTime: Int64 = 0
|
||||
static var credentialsProposed: [URLCredential] = []
|
||||
|
||||
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) {
|
||||
super.init(frame: frame, configuration: configuration)
|
||||
|
@ -203,7 +204,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
scrollView.showsVerticalScrollIndicator = (options?.verticalScrollBarEnabled)!
|
||||
scrollView.showsHorizontalScrollIndicator = (options?.horizontalScrollBarEnabled)!
|
||||
|
||||
|
||||
// options.debuggingEnabled is always enabled for iOS.
|
||||
|
||||
if (options?.clearCache)! {
|
||||
|
@ -721,6 +721,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
self.WKNavigationMap = [:]
|
||||
currentURL = url
|
||||
InAppWebView.credentialsProposed = []
|
||||
onLoadStop(url: (currentURL?.absoluteString)!)
|
||||
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) {
|
||||
InAppWebView.credentialsProposed = []
|
||||
|
||||
onLoadError(url: (currentURL?.absoluteString)!, error: error)
|
||||
|
||||
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) {
|
||||
let host = challenge.protectionSpace.host
|
||||
let realm = challenge.protectionSpace.realm
|
||||
onReceivedHttpAuthRequest(host: host, realm: realm, result: {(result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message)
|
||||
}
|
||||
else if (result as? NSObject) == FlutterMethodNotImplemented {
|
||||
completionHandler(.performDefaultHandling, nil)
|
||||
}
|
||||
else {
|
||||
//WKWebsiteDataStore.default()
|
||||
//URLCredentialStorage()
|
||||
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:
|
||||
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;
|
||||
|
||||
print (challenge.protectionSpace.authenticationMethod)
|
||||
|
||||
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodDefault ||
|
||||
challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPDigest {
|
||||
let host = challenge.protectionSpace.host
|
||||
let prot = challenge.protectionSpace.protocol
|
||||
let realm = challenge.protectionSpace.realm
|
||||
let port = challenge.protectionSpace.port
|
||||
onReceivedHttpAuthRequest(challenge: challenge, result: {(result) -> Void in
|
||||
if result is FlutterError {
|
||||
print((result as! FlutterError).message)
|
||||
}
|
||||
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) {
|
||||
|
@ -1101,8 +1153,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
|
|||
}
|
||||
}
|
||||
|
||||
public func onReceivedHttpAuthRequest(host: String, realm: String?, result: FlutterResult?) {
|
||||
var arguments: [String: Any] = ["host": host, "realm": realm as Any]
|
||||
public func onReceivedHttpAuthRequest(challenge: URLAuthenticationChallenge, result: FlutterResult?) {
|
||||
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 {
|
||||
arguments["uuid"] = IABController!.uuid
|
||||
}
|
||||
|
|
|
@ -52,17 +52,17 @@ class MyCookieManager: NSObject, FlutterPlugin {
|
|||
let name = arguments!["name"] as! String
|
||||
let domain = arguments!["domain"] 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;
|
||||
case "deleteCookies":
|
||||
let url = arguments!["url"] as! String
|
||||
let domain = arguments!["domain"] 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;
|
||||
case "deleteAllCookies":
|
||||
MyCookieManager.deleteAllCookies(result: result);
|
||||
break;
|
||||
MyCookieManager.deleteAllCookies(result: result)
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
|
|
|
@ -61,6 +61,8 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
|
||||
CredentialDatabase(registrar: registrar)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
|
@ -237,6 +239,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
case "getCopyBackForwardList":
|
||||
result(self.getCopyBackForwardList(uuid: uuid))
|
||||
break
|
||||
case "clearCache":
|
||||
self.clearCache(uuid: uuid)
|
||||
result(true)
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
|
@ -746,6 +752,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
|
|||
return nil
|
||||
}
|
||||
|
||||
func clearCache(uuid: String) {
|
||||
if let webViewController = self.webViewControllers[uuid] {
|
||||
webViewController!.webView.clearCache()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helper function inserted by Swift 4.2 migrator.
|
||||
|
|
|
@ -30,3 +30,4 @@ export 'src/chrome_safari_browser.dart';
|
|||
export 'src/in_app_localhost_server.dart';
|
||||
export 'src/webview_options.dart';
|
||||
export 'src/content_blocker.dart';
|
||||
export 'src/http_auth_credentials_database.dart';
|
||||
|
|
|
@ -70,7 +70,7 @@ class ChromeSafariBrowser {
|
|||
///- __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.
|
||||
///- __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);
|
||||
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
|
||||
|
||||
|
|
|
@ -4,32 +4,34 @@ import 'package:flutter/services.dart';
|
|||
///
|
||||
///**NOTE for iOS**: available from iOS 11.0+.
|
||||
class CookieManager {
|
||||
static bool _initialized = false;
|
||||
static CookieManager _instance;
|
||||
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_cookiemanager');
|
||||
|
||||
static void _init () {
|
||||
_channel.setMethodCallHandler(handleMethod);
|
||||
_initialized = true;
|
||||
static CookieManager instance() {
|
||||
return (_instance != null) ? _instance : _init();
|
||||
}
|
||||
|
||||
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.
|
||||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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 path = "/",
|
||||
int expiresDate,
|
||||
int maxAge,
|
||||
bool isSecure }) async {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
if (domain == null)
|
||||
domain = getDomainName(url);
|
||||
domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
@ -51,10 +53,7 @@ class CookieManager {
|
|||
}
|
||||
|
||||
///Gets all the cookies for the given [url].
|
||||
static Future<List<Map<String, dynamic>>> getCookies(String url) async {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
Future<List<Map<String, dynamic>>> getCookies(String url) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
|
@ -69,10 +68,7 @@ class CookieManager {
|
|||
}
|
||||
|
||||
///Gets a cookie by its [name] for the given [url].
|
||||
static Future<Map<String, dynamic>> getCookie(String url, String name) async {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
Future<Map<String, dynamic>> getCookie(String url, String name) async {
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
||||
|
@ -92,12 +88,9 @@ class CookieManager {
|
|||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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 {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
Future<void> deleteCookie(String url, String name, {String domain = "", String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty)
|
||||
domain = getDomainName(url);
|
||||
domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(name != null && name.isNotEmpty);
|
||||
|
@ -116,12 +109,9 @@ class CookieManager {
|
|||
///
|
||||
///The default value of [path] is `"/"`.
|
||||
///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 {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
Future<void> deleteCookies(String url, {String domain = "", String path = "/"}) async {
|
||||
if (domain == null || domain.isEmpty)
|
||||
domain = getDomainName(url);
|
||||
domain = _getDomainName(url);
|
||||
|
||||
assert(url != null && url.isNotEmpty);
|
||||
assert(domain != null && url.isNotEmpty);
|
||||
|
@ -135,15 +125,12 @@ class CookieManager {
|
|||
}
|
||||
|
||||
///Removes all cookies.
|
||||
static Future<void> deleteAllCookies() async {
|
||||
if (!_initialized)
|
||||
_init();
|
||||
|
||||
Future<void> deleteAllCookies() async {
|
||||
Map<String, dynamic> args = <String, dynamic>{};
|
||||
await _channel.invokeMethod('deleteAllCookies', args);
|
||||
}
|
||||
|
||||
static String getDomainName(String url) {
|
||||
String _getDomainName(String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String domain = uri.host;
|
||||
if (domain == null)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import 'dart:collection';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_inappbrowser/src/webview_options.dart';
|
||||
|
||||
import 'http_auth_credentials_database.dart';
|
||||
import 'types.dart';
|
||||
import 'channel_manager.dart';
|
||||
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.
|
||||
///
|
||||
///[host] represents the host requiring authentication.
|
||||
///
|
||||
///[realm] represents the realm for which authentication is required
|
||||
Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, String realm) {
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
|
||||
Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, HttpAuthChallenge challenge) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
|
||||
import 'http_auth_credentials_database.dart';
|
||||
import 'types.dart';
|
||||
import 'in_app_browser.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.
|
||||
///
|
||||
///[host] represents the host requiring authentication.
|
||||
///
|
||||
///[realm] represents the realm for which authentication is required
|
||||
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
|
||||
final onReceivedHttpAuthRequestCallback onReceivedHttpAuthRequest;
|
||||
|
||||
///Initial url that will be loaded.
|
||||
|
@ -251,7 +250,8 @@ class _InAppWebViewState extends State<InAppWebView> {
|
|||
Widget build(BuildContext context) {
|
||||
Map<String, dynamic> initialOptions = {};
|
||||
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) {
|
||||
|
@ -478,11 +478,16 @@ class InAppWebViewController {
|
|||
break;
|
||||
case "onReceivedHttpAuthRequest":
|
||||
String host = call.arguments["host"];
|
||||
String protocol = call.arguments["protocol"];
|
||||
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)
|
||||
return (await _widget.onReceivedHttpAuthRequest(this, host, realm))?.toMap();
|
||||
return (await _widget.onReceivedHttpAuthRequest(this, challenge))?.toMap();
|
||||
else if (_inAppBrowser != null)
|
||||
return (await _inAppBrowser.onReceivedHttpAuthRequest(host, realm))?.toMap();
|
||||
return (await _inAppBrowser.onReceivedHttpAuthRequest(host, challenge))?.toMap();
|
||||
break;
|
||||
case "onCallJsHandler":
|
||||
String handlerName = call.arguments["handlerName"];
|
||||
|
@ -960,6 +965,16 @@ class InAppWebViewController {
|
|||
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.
|
||||
Future<void> _dispose() async {
|
||||
await _channel.invokeMethod('dispose');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:uuid/uuid.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'in_app_webview.dart';
|
||||
|
||||
var uuidGenerator = new Uuid();
|
||||
|
@ -141,7 +142,7 @@ class GeolocationPermissionShowPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
class JsAlertResponseAction {
|
||||
final int _value;
|
||||
const JsAlertResponseAction._internal(this._value);
|
||||
|
@ -150,6 +151,7 @@ class JsAlertResponseAction {
|
|||
static const CONFIRM = const JsAlertResponseAction._internal(0);
|
||||
}
|
||||
|
||||
///
|
||||
class JsAlertResponse {
|
||||
String message;
|
||||
String confirmButtonTitle;
|
||||
|
@ -168,6 +170,7 @@ class JsAlertResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
class JsConfirmResponseAction {
|
||||
final int _value;
|
||||
const JsConfirmResponseAction._internal(this._value);
|
||||
|
@ -177,6 +180,7 @@ class JsConfirmResponseAction {
|
|||
static const CANCEL = const JsConfirmResponseAction._internal(1);
|
||||
}
|
||||
|
||||
///
|
||||
class JsConfirmResponse {
|
||||
String message;
|
||||
String confirmButtonTitle;
|
||||
|
@ -197,6 +201,7 @@ class JsConfirmResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
class JsPromptResponseAction {
|
||||
final int _value;
|
||||
const JsPromptResponseAction._internal(this._value);
|
||||
|
@ -206,6 +211,7 @@ class JsPromptResponseAction {
|
|||
static const CANCEL = const JsPromptResponseAction._internal(1);
|
||||
}
|
||||
|
||||
///
|
||||
class JsPromptResponse {
|
||||
String message;
|
||||
String defaultValue;
|
||||
|
@ -230,6 +236,7 @@ class JsPromptResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
class SafeBrowsingThreat {
|
||||
final int _value;
|
||||
const SafeBrowsingThreat._internal(this._value);
|
||||
|
@ -247,6 +254,7 @@ class SafeBrowsingThreat {
|
|||
static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4);
|
||||
}
|
||||
|
||||
///
|
||||
class SafeBrowsingResponseAction {
|
||||
final int _value;
|
||||
const SafeBrowsingResponseAction._internal(this._value);
|
||||
|
@ -256,6 +264,8 @@ class SafeBrowsingResponseAction {
|
|||
static const PROCEED = const SafeBrowsingResponseAction._internal(1);
|
||||
static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2);
|
||||
}
|
||||
|
||||
///
|
||||
class SafeBrowsingResponse {
|
||||
bool report;
|
||||
SafeBrowsingResponseAction action;
|
||||
|
@ -270,6 +280,7 @@ class SafeBrowsingResponse {
|
|||
}
|
||||
}
|
||||
|
||||
///
|
||||
class HttpAuthResponseAction {
|
||||
final int _value;
|
||||
const HttpAuthResponseAction._internal(this._value);
|
||||
|
@ -277,9 +288,10 @@ class HttpAuthResponseAction {
|
|||
|
||||
static const CANCEL = const HttpAuthResponseAction._internal(0);
|
||||
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 {
|
||||
String username;
|
||||
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 onWebViewLoadStartCallback = 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 onJsPromptCallback = Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue);
|
||||
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);
|
|
@ -1,7 +1,11 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'types.dart';
|
||||
import 'package:flutter_inappbrowser/src/content_blocker.dart';
|
||||
|
||||
class AndroidOptions {}
|
||||
class iOSOptions {}
|
||||
|
||||
class WebViewOptions {
|
||||
Map<String, dynamic> toMap() {
|
||||
return {};
|
||||
|
@ -14,7 +18,7 @@ class BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class InAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
||||
class InAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions, iOSOptions {
|
||||
bool useShouldOverrideUrlLoading;
|
||||
bool useOnLoadResource;
|
||||
bool useOnDownloadStart;
|
||||
|
@ -66,58 +70,7 @@ class InAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
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 AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
||||
class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions, AndroidOptions {
|
||||
bool clearSessionCache;
|
||||
bool builtInZoomControls;
|
||||
bool displayZoomControls;
|
||||
|
@ -211,43 +164,7 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
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 iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
||||
class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions, iOSOptions {
|
||||
bool disallowOverScroll;
|
||||
bool enableViewportScale;
|
||||
bool suppressesIncrementalRendering;
|
||||
|
@ -298,7 +215,7 @@ class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class InAppBrowserOptions implements BrowserOptions {
|
||||
class InAppBrowserOptions implements BrowserOptions, AndroidOptions, iOSOptions {
|
||||
bool hidden;
|
||||
bool toolbarTop;
|
||||
String toolbarTopBackgroundColor;
|
||||
|
@ -319,7 +236,7 @@ class InAppBrowserOptions implements BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class AndroidInAppBrowserOptions implements BrowserOptions {
|
||||
class AndroidInAppBrowserOptions implements BrowserOptions, AndroidOptions {
|
||||
bool hideTitleBar;
|
||||
bool closeOnCannotGoBack;
|
||||
bool progressBar;
|
||||
|
@ -336,47 +253,19 @@ class AndroidInAppBrowserOptions implements BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class iOSInAppBrowserOptionsPresentationStyle {
|
||||
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 {
|
||||
class iOSInAppBrowserOptions implements BrowserOptions, iOSOptions {
|
||||
bool toolbarBottom;
|
||||
String toolbarBottomBackgroundColor;
|
||||
bool toolbarBottomTranslucent;
|
||||
String closeButtonCaption;
|
||||
String closeButtonColor;
|
||||
iOSInAppBrowserOptionsPresentationStyle presentationStyle;
|
||||
iOSInAppBrowserOptionsTransitionStyle transitionStyle;
|
||||
iOSWebViewOptionsPresentationStyle presentationStyle;
|
||||
iOSWebViewOptionsTransitionStyle transitionStyle;
|
||||
bool spinner;
|
||||
|
||||
iOSInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "",
|
||||
this.closeButtonColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true});
|
||||
this.closeButtonColor = "", this.presentationStyle = iOSWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = iOSWebViewOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
@ -393,13 +282,13 @@ class iOSInAppBrowserOptions implements BrowserOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class ChromeCustomTabsOptions {
|
||||
class ChromeSafariBrowserOptions {
|
||||
Map<String, dynamic> toMap() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidChromeCustomTabsOptions implements ChromeCustomTabsOptions {
|
||||
class AndroidChromeCustomTabsOptions implements ChromeSafariBrowserOptions, AndroidOptions {
|
||||
bool addShareButton;
|
||||
bool showTitle;
|
||||
String toolbarBackgroundColor;
|
||||
|
@ -420,28 +309,18 @@ class AndroidChromeCustomTabsOptions implements ChromeCustomTabsOptions {
|
|||
}
|
||||
}
|
||||
|
||||
class iOSChromeCustomTabsOptionsDismissButtonStyle {
|
||||
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 {
|
||||
class iOSSafariOptions implements ChromeSafariBrowserOptions, iOSOptions {
|
||||
bool entersReaderIfAvailable;
|
||||
bool barCollapsingEnabled;
|
||||
iOSChromeCustomTabsOptionsDismissButtonStyle dismissButtonStyle;
|
||||
iOSSafariOptionsDismissButtonStyle dismissButtonStyle;
|
||||
String preferredBarTintColor;
|
||||
String preferredControlTintColor;
|
||||
iOSInAppBrowserOptionsPresentationStyle presentationStyle;
|
||||
iOSInAppBrowserOptionsTransitionStyle transitionStyle;
|
||||
iOSWebViewOptionsPresentationStyle presentationStyle;
|
||||
iOSWebViewOptionsTransitionStyle transitionStyle;
|
||||
|
||||
iOSChromeCustomTabsOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = iOSChromeCustomTabsOptionsDismissButtonStyle.DONE,
|
||||
this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL});
|
||||
iOSSafariOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = iOSSafariOptionsDismissButtonStyle.DONE,
|
||||
this.preferredBarTintColor = "", this.preferredControlTintColor = "", this.presentationStyle = iOSWebViewOptionsPresentationStyle.FULL_SCREEN,
|
||||
this.transitionStyle = iOSWebViewOptionsTransitionStyle.COVER_VERTICAL});
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() {
|
||||
|
|
Loading…
Reference in New Issue