updated android safe browsing, updated ios browser and SafariViewController options, added onSafeBrowsingHit event for android

This commit is contained in:
Lorenzo Pichilli 2019-10-29 15:27:50 +01:00
parent 153ab6023f
commit ab3b5c3935
12 changed files with 374 additions and 157 deletions

View File

@ -15,17 +15,17 @@
</component>
<component name="ChangeListManager">
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/android/build.gradle" 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/ContentBlocker/ContentBlockerHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/ContentBlocker/ContentBlockerHandler.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/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/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$/example/assets/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/example/assets/index.html" 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$/example/lib/inline_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/inline_example.screen.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/webview_example.screen.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/webview_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/flutter_inappbrowser.podspec" beforeDir="false" afterPath="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" 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" />
<change beforePath="$PROJECT_DIR$/lib/src/webview_options.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/src/webview_options.dart" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" />
@ -48,8 +48,20 @@
<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="454">
<caret line="39" column="107" selection-start-line="39" selection-start-column="107" selection-end-line="39" selection-end-column="107" />
<state relative-caret-position="300">
<caret line="20" column="62" selection-start-line="20" selection-start-column="62" selection-end-line="20" selection-end-column="62" />
</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="499">
<caret line="446" column="12" selection-start-line="446" selection-start-column="12" selection-end-line="446" selection-end-column="12" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
@ -57,8 +69,8 @@
<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="79">
<caret line="88" selection-start-line="88" selection-end-line="88" />
<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>
@ -78,8 +90,8 @@
<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="-727">
<caret line="439" column="66" selection-start-line="439" selection-start-column="58" selection-end-line="439" selection-end-column="66" />
<state relative-caret-position="380">
<caret line="462" column="29" selection-start-line="462" selection-start-column="12" selection-end-line="462" selection-end-column="29" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
@ -90,8 +102,8 @@
<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="222">
<caret line="370" selection-start-line="370" selection-end-line="370" />
<state relative-caret-position="372">
<caret line="397" column="102" selection-start-line="397" selection-start-column="102" selection-end-line="397" selection-end-column="102" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
@ -102,8 +114,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="477">
<caret line="212" column="22" selection-start-line="212" selection-start-column="7" selection-end-line="212" selection-end-column="22" />
<state relative-caret-position="261">
<caret line="264" column="32" selection-start-line="264" selection-start-column="32" selection-end-line="264" selection-end-column="32" />
<folding>
<element signature="e#0#32#0" expanded="true" />
</folding>
@ -123,8 +135,8 @@
<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="353">
<caret line="205" column="82" lean-forward="true" selection-start-line="205" selection-start-column="82" selection-end-line="205" selection-end-column="82" />
<state relative-caret-position="-625">
<caret line="100" column="14" selection-start-line="100" selection-start-column="14" selection-end-line="100" selection-end-column="14" />
<folding>
<element signature="e#0#22#0" expanded="true" />
</folding>
@ -132,27 +144,6 @@
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/flutter/packages/flutter/lib/src/material/dialog.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="307">
<caret line="690" column="10" selection-start-line="690" selection-start-column="10" selection-end-line="690" selection-end-column="10" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405">
<caret line="37" column="18" selection-start-line="37" selection-start-column="18" selection-end-line="37" selection-end-column="18" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
@ -165,14 +156,6 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>NOTE</find>
<find>onGeolocationPermissionsShowPrompt</find>
<find>&quot;onGeolocationPermissionsShowPrompt&quot;</find>
<find>databaseEnabled</find>
<find>RequestPermission</find>
<find>geolocation</find>
<find>userInterfaceDirectionPolicy</find>
<find>WKSelectionGranularityDynamic</find>
<find>minimumFontSize</find>
<find>defaultWebpagePreferences</find>
<find>contentBlockers</find>
@ -195,6 +178,14 @@
<find>onJsA</find>
<find>toMap()</find>
<find>.toMap()</find>
<find>onSafeBrowsingHitCallback</find>
<find>onSafeBrowsingHit&quot;</find>
<find>ConsoleMessageLevel</find>
<find>ConsoleMessage</find>
<find>appCa</find>
<find>iOSInAppWebViewUserPreferredContentMode</find>
<find>SafeBrowsingResponse</find>
<find>onSafeBrowsingHit</find>
</findStrings>
<replaceStrings>
<replace>activity.getPreferences(0)</replace>
@ -254,17 +245,17 @@
<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/pubspec.yaml" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/example/ios/Runner/Info.plist" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/lib/src/content_blocker.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
<option value="$PROJECT_DIR$/lib/src/types.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/lib/src/in_app_browser.dart" />
<option value="$PROJECT_DIR$/example/lib/webview_example.screen.dart" />
<option value="$PROJECT_DIR$/lib/src/in_app_webview.dart" />
<option value="$PROJECT_DIR$/example/assets/index.html" />
<option value="$PROJECT_DIR$/lib/src/webview_options.dart" />
<option value="$PROJECT_DIR$/example/lib/inline_example.screen.dart" />
</list>
</option>
@ -328,6 +319,17 @@
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
<item name="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="lib" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_inappbrowser" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_inappbrowser" type="462c0819:PsiDirectoryNode" />
@ -500,8 +502,8 @@
<frame x="0" y="23" width="1920" height="1057" extended-state="6" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.59711075" visible="true" weight="0.15867944" />
<window_info id="Structure" order="1" sideWeight="0.40288925" side_tool="true" visible="true" weight="0.15867944" />
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.59641874" visible="true" weight="0.15867944" />
<window_info id="Structure" order="1" sideWeight="0.40358126" 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 +513,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 active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49307775" visible="true" weight="0.35440415" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49307775" visible="true" weight="0.2476684" />
<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" />
@ -547,9 +549,6 @@
</ignored-roots>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/Flutter.framework/Info.plist">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/example/ios/Flutter/AppFrameworkInfo.plist">
<provider selected="true" editor-type-id="text-editor" />
</entry>
@ -793,70 +792,6 @@
</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="-1456">
<caret line="79" column="2" selection-start-line="79" selection-start-column="2" selection-end-line="86" selection-end-column="91" />
<folding>
<element signature="e#0#17#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="454">
<caret line="39" column="107" selection-start-line="39" selection-start-column="107" selection-end-line="39" selection-end-column="107" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="14" selection-start-line="2" selection-start-column="14" selection-end-line="2" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/webview_example.screen.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="79">
<caret line="88" selection-start-line="88" selection-end-line="88" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="477">
<caret line="212" column="22" selection-start-line="212" selection-start-column="7" selection-end-line="212" selection-end-column="22" />
<folding>
<element signature="e#0#32#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="-727">
<caret line="439" column="66" selection-start-line="439" selection-start-column="58" selection-end-line="439" selection-end-column="66" />
<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="222">
<caret line="370" selection-start-line="370" selection-end-line="370" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405">
@ -867,6 +802,13 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="14" selection-start-line="2" selection-start-column="14" selection-end-line="2" selection-end-column="14" />
</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">
@ -881,10 +823,74 @@
</state>
</provider>
</entry>
<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>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="20" column="62" selection-start-line="20" selection-start-column="62" selection-end-line="20" selection-end-column="62" />
</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="499">
<caret line="446" column="12" selection-start-line="446" selection-start-column="12" selection-end-line="446" selection-end-column="12" />
<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="372">
<caret line="397" column="102" selection-start-line="397" selection-start-column="102" selection-end-line="397" selection-end-column="102" />
<folding>
<element signature="e#0#20#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/src/types.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="261">
<caret line="264" column="32" selection-start-line="264" selection-start-column="32" selection-end-line="264" selection-end-column="32" />
<folding>
<element signature="e#0#32#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="380">
<caret line="462" column="29" selection-start-line="462" selection-start-column="12" selection-end-line="462" selection-end-column="29" />
<folding>
<element signature="e#0#17#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/io/platform.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="67" selection-start-line="67" selection-end-line="67" />
</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="353">
<caret line="205" column="82" lean-forward="true" selection-start-line="205" selection-start-column="82" selection-end-line="205" selection-end-column="82" />
<state relative-caret-position="-625">
<caret line="100" column="14" selection-start-line="100" selection-start-column="14" selection-end-line="100" selection-end-column="14" />
<folding>
<element signature="e#0#22#0" expanded="true" />
</folding>

View File

@ -18,6 +18,7 @@
- Added new iOS WebView options: `applicationNameForUserAgent`, `isFraudulentWebsiteWarningEnabled`, `selectionGranularity`, `dataDetectorTypes`, `preferredContentMode`
- Added `onGeolocationPermissionsShowPrompt` event and `GeolocationPermissionShowPromptResponse` class (available only for Android)
- 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
### BREAKING CHANGES

View File

@ -10,8 +10,12 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppWebView.InAppWebView;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -41,11 +45,19 @@ public class ContentBlockerHandler {
this.ruleList = newRuleList;
}
public WebResourceResponse checkUrl(final InAppWebView webView, String url, ContentBlockerTriggerResourceType responseResourceType) throws URISyntaxException, InterruptedException {
public WebResourceResponse checkUrl(final InAppWebView webView, String url, ContentBlockerTriggerResourceType responseResourceType) throws URISyntaxException, InterruptedException, MalformedURLException {
if (webView.options.contentBlockers == null)
return null;
URI u = new URI(url);
URI u;
try {
u = new URI(url);
} catch (URISyntaxException e) {
String[] urlSplitted = url.split(":");
String scheme = urlSplitted[0];
URL tempUrl = new URL(url.replace(scheme, "https"));
u = new URI(scheme, tempUrl.getUserInfo(), tempUrl.getHost(), tempUrl.getPort(), tempUrl.getPath(), tempUrl.getQuery(), tempUrl.getRef());
}
String host = u.getHost();
int port = u.getPort();
String scheme = u.getScheme();
@ -182,12 +194,12 @@ public class ContentBlockerHandler {
return null;
}
public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException {
public WebResourceResponse checkUrl(final InAppWebView webView, String url) throws URISyntaxException, InterruptedException, MalformedURLException {
ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromUrl(webView, url);
return checkUrl(webView, url, responseResourceType);
}
public WebResourceResponse checkUrl(final InAppWebView webView, String url, String contentType) throws URISyntaxException, InterruptedException {
public WebResourceResponse checkUrl(final InAppWebView webView, String url, String contentType) throws URISyntaxException, InterruptedException, MalformedURLException {
ContentBlockerTriggerResourceType responseResourceType = getResourceTypeFromContentType(contentType);
return checkUrl(webView, url, responseResourceType);
}

View File

@ -3,6 +3,7 @@ package com.pichillilorenzo.flutter_inappbrowser;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.webkit.WebChromeClient;
@ -226,6 +227,12 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
else
result.success(false);
break;
case "getSafeBrowsingPrivacyPolicyUrl":
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
result.success(webView.getSafeBrowsingPrivacyPolicyUrl().toString());
} else
result.success(null);
break;
case "dispose":
dispose();
result.success(true);

View File

@ -447,7 +447,7 @@ public class InAppWebChromeClient extends WebChromeClient {
obj.put("sourceURL", consoleMessage.sourceId());
obj.put("lineNumber", consoleMessage.lineNumber());
obj.put("message", consoleMessage.message());
obj.put("messageLevel", consoleMessage.messageLevel().toString());
obj.put("messageLevel", consoleMessage.messageLevel().ordinal());
getChannel().invokeMethod("onConsoleMessage", obj);
return true;
}

View File

@ -10,6 +10,7 @@ import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler;
import android.webkit.SafeBrowsingResponse;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest;
@ -306,6 +307,58 @@ public class InAppWebViewClient extends WebViewClient {
webView.scale = newScale;
}
@RequiresApi(api = Build.VERSION_CODES.O_MR1)
@Override
public void onSafeBrowsingHit(final WebView view, WebResourceRequest request, int threatType, final SafeBrowsingResponse callback) {
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("url", request.getUrl().toString());
obj.put("threatType", threatType);
getChannel().invokeMethod("onSafeBrowsingHit", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
Map<String, Object> responseMap = (Map<String, Object>) response;
Boolean report = (Boolean) responseMap.get("report");
Integer action = (Integer) responseMap.get("action");
Log.d(LOG_TAG, "\n\nreport: " + report);
Log.d(LOG_TAG, "\n\naction: " + action);
report = report != null ? report : true;
if (action != null) {
switch (action) {
case 0:
callback.backToSafety(report);
return;
case 1:
callback.proceed(report);
return;
case 2:
callback.showInterstitial(report);
return;
}
}
}
callback.showInterstitial(true);
}
@Override
public void error(String s, String s1, Object o) {
Log.e(LOG_TAG, s + ", " + s1);
}
@Override
public void notImplemented() {
callback.showInterstitial(true);
}
});
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

View File

@ -65,6 +65,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
child: InAppWebView(
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
//initialUrl: "https://flutter.dev/",
//initialUrl: "chrome://safe-browsing/match?type=malware",
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: [
@ -88,6 +89,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
appCacheEnabled: true,
domStorageEnabled: true,
geolocationEnabled: true,
safeBrowsingEnabled: true,
//blockNetworkImage: true,
),
iOSInAppWebViewOptions(
@ -97,6 +99,9 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
if (Platform.isAndroid)
webView.startSafeBrowsing();
webView.addJavaScriptHandler('handlerFoo', (args) {
return new Foo(bar: 'bar_value', baz: 'baz_value');
});
@ -142,7 +147,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
sourceURL: ${consoleMessage.sourceURL}
lineNumber: ${consoleMessage.lineNumber}
message: ${consoleMessage.message}
messageLevel: ${consoleMessage.messageLevel}
messageLevel: ${consoleMessage.messageLevel.toValue()}
""");
},
onDownloadStart: (InAppWebViewController controller, String url) async {
@ -210,6 +215,10 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
JsPromptResponseAction action = await createPromptDialog(context, message);
return new JsPromptResponse(handledByClient: true, action: action, value: _textFieldController.text);
},
onSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async {
SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY;
return new SafeBrowsingResponse(report: true, action: action);
},
),
),
),

View File

@ -63,7 +63,7 @@ class MyInappBrowser extends InAppBrowser {
sourceURL: ${consoleMessage.sourceURL}
lineNumber: ${consoleMessage.lineNumber}
message: ${consoleMessage.message}
messageLevel: ${consoleMessage.messageLevel}
messageLevel: ${consoleMessage.messageLevel.toValue()}
""");
}

View File

@ -394,6 +394,18 @@ class InAppBrowser {
}
///Event fires when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only for Android.
Future<SafeBrowsingResponse> onSafeBrowsingHit(String url, SafeBrowsingThreat threatType) {
}
void throwIsAlreadyOpened({String message = ''}) {
if (this.isOpened()) {
throw Exception(['Error: ${ (message.isEmpty) ? '' : message + ' '}The browser is already opened.']);

View File

@ -162,9 +162,20 @@ class InAppWebView extends StatefulWidget {
///If [JsPromptResponse.handledByClient] is `true`, the webview will assume that the client will handle the dialog.
///
///[message] represents the message to be displayed in the alert dialog.
///
///[defaultValue] represents the default value displayed in the prompt dialog.
final onJsPromptCallback onJsPrompt;
///Event fires when the webview notifies that a loading URL has been flagged by Safe Browsing.
///The default behavior is to show an interstitial to the user, with the reporting checkbox visible.
///
///[url] represents the url of the request.
///
///[threatType] represents the reason the resource was caught by Safe Browsing, corresponding to a [SafeBrowsingThreat].
///
///**NOTE**: available only for Android.
final onSafeBrowsingHitCallback onSafeBrowsingHit;
///Initial url that will be loaded.
final String initialUrl;
///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation.
@ -207,6 +218,7 @@ class InAppWebView extends StatefulWidget {
this.onJsAlert,
this.onJsConfirm,
this.onJsPrompt,
this.onSafeBrowsingHit,
this.gestureRecognizers,
}) : super(key: key);
@ -370,13 +382,7 @@ class InAppWebViewController {
String sourceURL = call.arguments["sourceURL"];
int lineNumber = call.arguments["lineNumber"];
String message = call.arguments["message"];
ConsoleMessageLevel messageLevel;
ConsoleMessageLevel.values.forEach((element) {
if ("ConsoleMessageLevel." + call.arguments["messageLevel"] == element.toString()) {
messageLevel = element;
return;
}
});
ConsoleMessageLevel messageLevel = ConsoleMessageLevel.fromValue(call.arguments["messageLevel"]);
if (_widget != null && _widget.onConsoleMessage != null)
_widget.onConsoleMessage(this, ConsoleMessage(sourceURL, lineNumber, message, messageLevel));
else if (_inAppBrowser != null)
@ -454,6 +460,14 @@ class InAppWebViewController {
else if (_inAppBrowser != null)
return (await _inAppBrowser.onJsPrompt(message, defaultValue))?.toMap();
break;
case "onSafeBrowsingHit":
String url = call.arguments["url"];
SafeBrowsingThreat threatType = SafeBrowsingThreat.fromValue(call.arguments["threatType"]);
if (_widget != null && _widget.onJsPrompt != null)
return (await _widget.onSafeBrowsingHit(this, url, threatType))?.toMap();
else if (_inAppBrowser != null)
return (await _inAppBrowser.onSafeBrowsingHit(url, threatType))?.toMap();
break;
case "onCallJsHandler":
String handlerName = call.arguments["handlerName"];
// decode args to json
@ -918,6 +932,17 @@ class InAppWebViewController {
return await _channel.invokeMethod('setSafeBrowsingWhitelist', args);
}
///Returns a URL pointing to the privacy policy for Safe Browsing reporting. This value will never be `null`.
///
///**NOTE**: available only for Android.
Future<String> getSafeBrowsingPrivacyPolicyUrl() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
}
///Dispose/Destroy the WebView.
Future<void> _dispose() async {

View File

@ -18,9 +18,22 @@ typedef Future<dynamic> ListenerCallback(MethodCall call);
///In this case, simply return data that you want to send and it will be automatically json encoded using [jsonEncode] from the `dart:convert` library.
typedef dynamic JavaScriptHandlerCallback(List<dynamic> arguments);
///Enum representing the level of a console message.
enum ConsoleMessageLevel {
DEBUG, ERROR, LOG, TIP, WARNING
///Class representing the level of a console message.
class ConsoleMessageLevel {
final int _value;
const ConsoleMessageLevel._internal(this._value);
static ConsoleMessageLevel fromValue(int value) {
if (value >= 0 && value <= 4)
return ConsoleMessageLevel._internal(value);
return null;
}
toValue() => _value;
static const TIP = const ConsoleMessageLevel._internal(0);
static const LOG = const ConsoleMessageLevel._internal(1);
static const WARNING = const ConsoleMessageLevel._internal(2);
static const ERROR = const ConsoleMessageLevel._internal(3);
static const DEBUG = const ConsoleMessageLevel._internal(4);
}
///Public class representing a resource response of the [InAppBrowser] WebView.
@ -217,6 +230,46 @@ class JsPromptResponse {
}
}
class SafeBrowsingThreat {
final int _value;
const SafeBrowsingThreat._internal(this._value);
static SafeBrowsingThreat fromValue(int value) {
if (value >= 0 && value <= 4)
return SafeBrowsingThreat._internal(value);
return null;
}
toValue() => _value;
static const SAFE_BROWSING_THREAT_UNKNOWN = const SafeBrowsingThreat._internal(0);
static const SAFE_BROWSING_THREAT_MALWARE = const SafeBrowsingThreat._internal(1);
static const SAFE_BROWSING_THREAT_PHISHING = const SafeBrowsingThreat._internal(2);
static const SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = const SafeBrowsingThreat._internal(3);
static const SAFE_BROWSING_THREAT_BILLING = const SafeBrowsingThreat._internal(4);
}
class SafeBrowsingResponseAction {
final int _value;
const SafeBrowsingResponseAction._internal(this._value);
toValue() => _value;
static const BACK_TO_SAFETY = const SafeBrowsingResponseAction._internal(0);
static const PROCEED = const SafeBrowsingResponseAction._internal(1);
static const SHOW_INTERSTITIAL = const SafeBrowsingResponseAction._internal(2);
}
class SafeBrowsingResponse {
bool report;
SafeBrowsingResponseAction action;
SafeBrowsingResponse({this.report = true, this.action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL});
Map<String, dynamic> toMap() {
return {
"report": report,
"action": action?.toValue()
};
}
}
typedef onWebViewCreatedCallback = void Function(InAppWebViewController controller);
typedef onWebViewLoadStartCallback = void Function(InAppWebViewController controller, String url);
typedef onWebViewLoadStopCallback = void Function(InAppWebViewController controller, String url);
@ -232,4 +285,5 @@ typedef onTargetBlankCallback = void Function(InAppWebViewController controller,
typedef onGeolocationPermissionsShowPromptCallback = Future<GeolocationPermissionShowPromptResponse> Function(InAppWebViewController controller, String origin);
typedef onJsAlertCallback = Future<JsAlertResponse> Function(InAppWebViewController controller, String message);
typedef onJsConfirmCallback = Future<JsConfirmResponse> Function(InAppWebViewController controller, String message);
typedef onJsPromptCallback = Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue);
typedef onJsPromptCallback = Future<JsPromptResponse> Function(InAppWebViewController controller, String message, String defaultValue);
typedef onSafeBrowsingHitCallback = Future<SafeBrowsingResponse> Function(InAppWebViewController controller, String url, SafeBrowsingThreat threatType);

View File

@ -127,7 +127,6 @@ class AndroidInAppWebViewOptions implements WebViewOptions, BrowserOptions {
bool safeBrowsingEnabled;
bool transparentBackground;
AndroidInAppWebViewMixedContentMode mixedContentMode;
bool allowContentAccess;
bool allowFileAccess;
bool allowFileAccessFromFileURLs;
@ -258,7 +257,6 @@ class iOSInAppWebViewOptions implements WebViewOptions, BrowserOptions {
bool allowsInlineMediaPlayback;
bool allowsPictureInPictureMediaPlayback;
bool transparentBackground;
String applicationNameForUserAgent;
bool isFraudulentWebsiteWarningEnabled;
iOSInAppWebViewSelectionGranularity selectionGranularity;
@ -337,18 +335,47 @@ 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 {
bool toolbarBottom;
String toolbarBottomBackgroundColor;
bool toolbarBottomTranslucent;
String closeButtonCaption;
String closeButtonColor;
int presentationStyle; //default fullscreen
int transitionStyle; //default crossDissolve
iOSInAppBrowserOptionsPresentationStyle presentationStyle;
iOSInAppBrowserOptionsTransitionStyle transitionStyle;
bool spinner;
iOSInAppBrowserOptions({this.toolbarBottom = true, this.toolbarBottomBackgroundColor = "", this.toolbarBottomTranslucent = true, this.closeButtonCaption = "",
this.closeButtonColor = "", this.presentationStyle = 0, this.transitionStyle = 0, this.spinner = true});
this.closeButtonColor = "", this.presentationStyle = iOSInAppBrowserOptionsPresentationStyle.FULL_SCREEN,
this.transitionStyle = iOSInAppBrowserOptionsTransitionStyle.COVER_VERTICAL, this.spinner = true});
@override
Map<String, dynamic> toMap() {
@ -358,8 +385,8 @@ class iOSInAppBrowserOptions implements BrowserOptions {
"toolbarBottomTranslucent": toolbarBottomTranslucent,
"closeButtonCaption": closeButtonCaption,
"closeButtonColor": closeButtonColor,
"presentationStyle": presentationStyle,
"transitionStyle": transitionStyle,
"presentationStyle": presentationStyle.toValue(),
"transitionStyle": transitionStyle.toValue(),
"spinner": spinner,
};
}
@ -392,28 +419,39 @@ 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 {
bool entersReaderIfAvailable;
bool barCollapsingEnabled;
int dismissButtonStyle; //default done
iOSChromeCustomTabsOptionsDismissButtonStyle dismissButtonStyle;
String preferredBarTintColor;
String preferredControlTintColor;
int presentationStyle; //default fullscreen
int transitionStyle; //default crossDissolve
iOSInAppBrowserOptionsPresentationStyle presentationStyle;
iOSInAppBrowserOptionsTransitionStyle transitionStyle;
iOSChromeCustomTabsOptions({this.entersReaderIfAvailable = false, this.barCollapsingEnabled = false, this.dismissButtonStyle = 0, this.preferredBarTintColor = "",
this.preferredControlTintColor = "", this.presentationStyle = 0, this.transitionStyle = 0});
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});
@override
Map<String, dynamic> toMap() {
return {
"entersReaderIfAvailable": entersReaderIfAvailable,
"barCollapsingEnabled": barCollapsingEnabled,
"dismissButtonStyle": dismissButtonStyle,
"dismissButtonStyle": dismissButtonStyle.toValue(),
"preferredBarTintColor": preferredBarTintColor,
"preferredControlTintColor": preferredControlTintColor,
"presentationStyle": presentationStyle,
"transitionStyle": transitionStyle,
"presentationStyle": presentationStyle.toValue(),
"transitionStyle": transitionStyle.toValue(),
};
}
}