added AndroidWebViewFeature, AndroidServiceWorkerController, AndroidServiceWorkerClient classes
This commit is contained in:
parent
a023d34fd9
commit
37fa32b31e
|
@ -5,12 +5,11 @@
|
||||||
- Added `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options also for iOS (also thanks to [liranhao](https://github.com/liranhao))
|
- Added `allowUniversalAccessFromFileURLs` and `allowFileAccessFromFileURLs` WebView options also for iOS (also thanks to [liranhao](https://github.com/liranhao))
|
||||||
- Added limited cookies support on iOS below 11.0 using JavaScript
|
- Added limited cookies support on iOS below 11.0 using JavaScript
|
||||||
- Added `IOSCookieManager` class and `CookieManager.instance().ios.getAllCookies` iOS-specific method
|
- Added `IOSCookieManager` class and `CookieManager.instance().ios.getAllCookies` iOS-specific method
|
||||||
- Added `UserScript` and `UserScriptInjectionTime` classes
|
- Added `UserScript`, `UserScriptInjectionTime`, `ContentWorld`, `AndroidWebViewFeature`, `AndroidServiceWorkerController`, `AndroidServiceWorkerClient` classes
|
||||||
- Added `initialUserScripts` WebView option
|
- Added `initialUserScripts` WebView option
|
||||||
- Added `addUserScript`, `addUserScripts`, `removeUserScript`, `removeUserScripts`, `removeAllUserScripts` WebView methods
|
- Added `addUserScript`, `addUserScripts`, `removeUserScript`, `removeUserScripts`, `removeAllUserScripts` WebView methods
|
||||||
- Added `isDirectionalLockEnabled`, `mediaType`, `pageZoom`, `limitsNavigationsToAppBoundDomains` iOS-specific webview options
|
- Added `isDirectionalLockEnabled`, `mediaType`, `pageZoom`, `limitsNavigationsToAppBoundDomains` iOS-specific webview options
|
||||||
- Added `handlesURLScheme` iOS-specific webview method
|
- Added `handlesURLScheme` iOS-specific webview method
|
||||||
- Added `ContentWorld` class
|
|
||||||
- Updated integration tests
|
- Updated integration tests
|
||||||
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
|
- Merge "Upgraded appcompat to 1.2.0-rc-02" [#465](https://github.com/pichillilorenzo/flutter_inappwebview/pull/465) (thanks to [andreidiaconu](https://github.com/andreidiaconu))
|
||||||
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
|
- Merge "Added missing field 'headers' which returned by WebResourceResponse.toMap()" [#490](https://github.com/pichillilorenzo/flutter_inappwebview/pull/490) (thanks to [Doflatango](https://github.com/Doflatango))
|
||||||
|
|
|
@ -35,20 +35,16 @@ import android.webkit.CookieManager;
|
||||||
import android.webkit.DownloadListener;
|
import android.webkit.DownloadListener;
|
||||||
import android.webkit.ValueCallback;
|
import android.webkit.ValueCallback;
|
||||||
import android.webkit.WebBackForwardList;
|
import android.webkit.WebBackForwardList;
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.WebHistoryItem;
|
import android.webkit.WebHistoryItem;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebStorage;
|
import android.webkit.WebStorage;
|
||||||
import android.webkit.WebViewClient;
|
|
||||||
import android.widget.HorizontalScrollView;
|
import android.widget.HorizontalScrollView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.Keep;
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.webkit.WebViewCompat;
|
import androidx.webkit.WebViewCompat;
|
||||||
import androidx.webkit.WebViewFeature;
|
import androidx.webkit.WebViewFeature;
|
||||||
import androidx.webkit.WebViewRenderProcessClient;
|
|
||||||
|
|
||||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
|
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlocker;
|
||||||
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
|
import com.pichillilorenzo.flutter_inappwebview.ContentBlocker.ContentBlockerAction;
|
||||||
|
@ -63,9 +59,6 @@ import com.pichillilorenzo.flutter_inappwebview.Util;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateExpiredException;
|
|
||||||
import java.security.cert.CertificateNotYetValidException;
|
|
||||||
import java.security.cert.CertificateParsingException;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -131,10 +124,11 @@ final public class InAppWebView extends InputAwareWebView {
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
static final String contentWorldWrapperJS = "(function() {" +
|
static final String contentWorldWrapperJS = "(function() {" +
|
||||||
" var iframe = document.getElementById('$CONTENT_WORLD_NAME');" +
|
" var iframeId = '" + JavaScriptBridgeInterface.name + "_$CONTENT_WORLD_NAME';" +
|
||||||
|
" var iframe = document.getElementById(iframeId);" +
|
||||||
" if (iframe == null) {" +
|
" if (iframe == null) {" +
|
||||||
" iframe = document.createElement('iframe');" +
|
" iframe = document.createElement('iframe');" +
|
||||||
" iframe.id = '$CONTENT_WORLD_NAME';" +
|
" iframe.id = iframeId;" +
|
||||||
" iframe.style = 'display: none; z-index: 0; position: absolute; width: 0px; height: 0px';" +
|
" iframe.style = 'display: none; z-index: 0; position: absolute; width: 0px; height: 0px';" +
|
||||||
" document.body.append(iframe);" +
|
" document.body.append(iframe);" +
|
||||||
" }" +
|
" }" +
|
||||||
|
|
|
@ -29,6 +29,8 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
public static MyCookieManager myCookieManager;
|
public static MyCookieManager myCookieManager;
|
||||||
public static CredentialDatabaseHandler credentialDatabaseHandler;
|
public static CredentialDatabaseHandler credentialDatabaseHandler;
|
||||||
public static MyWebStorage myWebStorage;
|
public static MyWebStorage myWebStorage;
|
||||||
|
public static ServiceWorkerManager serviceWorkerManager;
|
||||||
|
public static WebViewFeatureManager webViewFeatureManager;
|
||||||
public static ValueCallback<Uri> filePathCallbackLegacy;
|
public static ValueCallback<Uri> filePathCallbackLegacy;
|
||||||
public static ValueCallback<Uri[]> filePathCallback;
|
public static ValueCallback<Uri[]> filePathCallback;
|
||||||
|
|
||||||
|
@ -65,12 +67,17 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
|
|
||||||
platformViewRegistry.registerViewFactory(
|
platformViewRegistry.registerViewFactory(
|
||||||
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(messenger, flutterView));
|
"com.pichillilorenzo/flutter_inappwebview", new FlutterWebViewFactory(messenger, flutterView));
|
||||||
|
|
||||||
inAppWebViewStatic = new InAppWebViewStatic(messenger);
|
inAppWebViewStatic = new InAppWebViewStatic(messenger);
|
||||||
myCookieManager = new MyCookieManager(messenger);
|
myCookieManager = new MyCookieManager(messenger);
|
||||||
myWebStorage = new MyWebStorage(messenger);
|
myWebStorage = new MyWebStorage(messenger);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
serviceWorkerManager = new ServiceWorkerManager(messenger);
|
||||||
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
credentialDatabaseHandler = new CredentialDatabaseHandler(messenger);
|
credentialDatabaseHandler = new CredentialDatabaseHandler(messenger);
|
||||||
}
|
}
|
||||||
|
webViewFeatureManager = new WebViewFeatureManager(messenger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,6 +110,14 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
|
||||||
inAppWebViewStatic.dispose();
|
inAppWebViewStatic.dispose();
|
||||||
inAppWebViewStatic = null;
|
inAppWebViewStatic = null;
|
||||||
}
|
}
|
||||||
|
if (serviceWorkerManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
serviceWorkerManager.dispose();
|
||||||
|
serviceWorkerManager = null;
|
||||||
|
}
|
||||||
|
if (webViewFeatureManager != null) {
|
||||||
|
webViewFeatureManager.dispose();
|
||||||
|
webViewFeatureManager = null;
|
||||||
|
}
|
||||||
filePathCallbackLegacy = null;
|
filePathCallbackLegacy = null;
|
||||||
filePathCallback = null;
|
filePathCallback = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ public abstract class RequestPermissionHandler implements ActivityCompat.OnReque
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||||
Log.d("asdasd", "\n\na asd asd \n\n");
|
|
||||||
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
|
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
|
||||||
List<Runnable> callbacks = actionDictionary.get(requestCode);
|
List<Runnable> callbacks = actionDictionary.get(requestCode);
|
||||||
for (Runnable runnable : callbacks) {
|
for (Runnable runnable : callbacks) {
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package com.pichillilorenzo.flutter_inappwebview;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.webkit.WebResourceRequest;
|
||||||
|
import android.webkit.WebResourceResponse;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.webkit.ServiceWorkerClientCompat;
|
||||||
|
import androidx.webkit.ServiceWorkerControllerCompat;
|
||||||
|
import androidx.webkit.ServiceWorkerWebSettingsCompat;
|
||||||
|
import androidx.webkit.WebViewFeature;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger;
|
||||||
|
import io.flutter.plugin.common.MethodCall;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
|
public class ServiceWorkerManager implements MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
|
static final String LOG_TAG = "ServiceWorkerManager";
|
||||||
|
|
||||||
|
public static MethodChannel channel;
|
||||||
|
@Nullable
|
||||||
|
public static ServiceWorkerControllerCompat serviceWorkerController;
|
||||||
|
|
||||||
|
public ServiceWorkerManager(BinaryMessenger messenger) {
|
||||||
|
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller");
|
||||||
|
channel.setMethodCallHandler(this);
|
||||||
|
if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) {
|
||||||
|
serviceWorkerController = ServiceWorkerControllerCompat.getInstance();
|
||||||
|
serviceWorkerController.setServiceWorkerClient(new ServiceWorkerClientCompat() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public WebResourceResponse shouldInterceptRequest(@NonNull WebResourceRequest request) {
|
||||||
|
final Map<String, Object> obj = new HashMap<>();
|
||||||
|
obj.put("url", request.getUrl().toString());
|
||||||
|
obj.put("method", request.getMethod());
|
||||||
|
obj.put("headers", request.getRequestHeaders());
|
||||||
|
obj.put("isForMainFrame", request.isForMainFrame());
|
||||||
|
obj.put("hasGesture", request.hasGesture());
|
||||||
|
obj.put("isRedirect", request.isRedirect());
|
||||||
|
|
||||||
|
Util.WaitFlutterResult flutterResult;
|
||||||
|
try {
|
||||||
|
flutterResult = Util.invokeMethodAndWait(channel, "shouldInterceptRequest", obj);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flutterResult.error != null) {
|
||||||
|
Log.e(LOG_TAG, flutterResult.error);
|
||||||
|
}
|
||||||
|
else if (flutterResult.result != null) {
|
||||||
|
Map<String, Object> res = (Map<String, Object>) flutterResult.result;
|
||||||
|
String contentType = (String) res.get("contentType");
|
||||||
|
String contentEncoding = (String) res.get("contentEncoding");
|
||||||
|
byte[] data = (byte[]) res.get("data");
|
||||||
|
Map<String, String> responseHeaders = (Map<String, String>) res.get("headers");
|
||||||
|
Integer statusCode = (Integer) res.get("statusCode");
|
||||||
|
String reasonPhrase = (String) res.get("reasonPhrase");
|
||||||
|
|
||||||
|
ByteArrayInputStream inputStream = (data != null) ? new ByteArrayInputStream(data) : null;
|
||||||
|
|
||||||
|
if ((responseHeaders == null && statusCode == null && reasonPhrase == null) || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
return new WebResourceResponse(contentType, contentEncoding, inputStream);
|
||||||
|
} else {
|
||||||
|
return new WebResourceResponse(contentType, contentEncoding, statusCode, reasonPhrase, responseHeaders, inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
serviceWorkerController = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
|
||||||
|
ServiceWorkerWebSettingsCompat serviceWorkerWebSettings = (serviceWorkerController != null) ? serviceWorkerController.getServiceWorkerWebSettings() : null;
|
||||||
|
|
||||||
|
switch (call.method) {
|
||||||
|
case "getAllowContentAccess":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS)) {
|
||||||
|
result.success(serviceWorkerWebSettings.getAllowContentAccess());
|
||||||
|
} else {
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "getAllowFileAccess":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_FILE_ACCESS)) {
|
||||||
|
result.success(serviceWorkerWebSettings.getAllowFileAccess());
|
||||||
|
} else {
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "getBlockNetworkLoads":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS)) {
|
||||||
|
result.success(serviceWorkerWebSettings.getBlockNetworkLoads());
|
||||||
|
} else {
|
||||||
|
result.success(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "getCacheMode":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_CACHE_MODE)) {
|
||||||
|
result.success(serviceWorkerWebSettings.getCacheMode());
|
||||||
|
} else {
|
||||||
|
result.success(null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "setAllowContentAccess":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS)) {
|
||||||
|
Boolean allow = (Boolean) call.argument("allow");
|
||||||
|
serviceWorkerWebSettings.setAllowContentAccess(allow);
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "setAllowFileAccess":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_FILE_ACCESS)) {
|
||||||
|
Boolean allow = (Boolean) call.argument("allow");
|
||||||
|
serviceWorkerWebSettings.setAllowFileAccess(allow);
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "setBlockNetworkLoads":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS)) {
|
||||||
|
Boolean flag = (Boolean) call.argument("flag");
|
||||||
|
serviceWorkerWebSettings.setBlockNetworkLoads(flag);
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
case "setCacheMode":
|
||||||
|
if (serviceWorkerWebSettings != null && WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_CACHE_MODE)) {
|
||||||
|
Integer mode = (Integer) call.argument("mode");
|
||||||
|
serviceWorkerWebSettings.setCacheMode(mode);
|
||||||
|
}
|
||||||
|
result.success(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.notImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.pichillilorenzo.flutter_inappwebview;
|
||||||
|
|
||||||
|
import androidx.webkit.WebViewFeature;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.BinaryMessenger;
|
||||||
|
import io.flutter.plugin.common.MethodCall;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
|
public class WebViewFeatureManager implements MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
|
static final String LOG_TAG = "WebViewFeatureManager";
|
||||||
|
|
||||||
|
public static MethodChannel channel;
|
||||||
|
|
||||||
|
public WebViewFeatureManager(BinaryMessenger messenger) {
|
||||||
|
channel = new MethodChannel(messenger, "com.pichillilorenzo/flutter_inappwebview_android_webviewfeature");
|
||||||
|
channel.setMethodCallHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
|
||||||
|
switch (call.method) {
|
||||||
|
case "isFeatureSupported":
|
||||||
|
String feature = (String) call.argument("feature");
|
||||||
|
result.success(WebViewFeature.isFeatureSupported(feature));
|
||||||
|
default:
|
||||||
|
result.notImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-04 01:10:32.198308","version":"1.26.0-18.0.pre.90"}
|
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"android":[{"name":"device_info","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-2.0.0-nullsafety.2/","dependencies":[]},{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":["device_info"]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/.pub-cache/git/plugins-16f3281b04b0db12e609352b1c9544901392e428/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.27/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.0.1+1/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.4/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":["device_info"]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-02-04 21:51:34.603760","version":"1.26.0-18.0.pre.90"}
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -9,7 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
020EF14E4245221B2C22ACE5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0FC2CF7A6002799890B3102 /* Pods_Runner.framework */; };
|
020EF14E4245221B2C22ACE5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0FC2CF7A6002799890B3102 /* Pods_Runner.framework */; };
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
25A517508F43E58C47090625 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
25A517508F43E58C47090625 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
61FF730023634CA10069C557 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 61FF72FF23634CA10069C557 /* libsqlite3.tbd */; };
|
61FF730023634CA10069C557 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 61FF72FF23634CA10069C557 /* libsqlite3.tbd */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
61FF730023634CA10069C557 /* libsqlite3.tbd in Frameworks */,
|
61FF730023634CA10069C557 /* libsqlite3.tbd in Frameworks */,
|
||||||
25A517508F43E58C47090625 /* BuildFile in Frameworks */,
|
25A517508F43E58C47090625 /* (null) in Frameworks */,
|
||||||
020EF14E4245221B2C22ACE5 /* Pods_Runner.framework in Frameworks */,
|
020EF14E4245221B2C22ACE5 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -81,7 +81,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||||
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
|
||||||
child: InAppWebView(
|
child: InAppWebView(
|
||||||
// contextMenu: contextMenu,
|
// contextMenu: contextMenu,
|
||||||
initialUrl: "https://flutter.dev/",
|
initialUrl: "https://flutter.dev",
|
||||||
// initialFile: "assets/index.html",
|
// initialFile: "assets/index.html",
|
||||||
initialHeaders: {},
|
initialHeaders: {},
|
||||||
initialUserScripts: UnmodifiableListView<UserScript>([
|
initialUserScripts: UnmodifiableListView<UserScript>([
|
||||||
|
@ -91,12 +91,14 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
|
||||||
crossPlatform: InAppWebViewOptions(
|
crossPlatform: InAppWebViewOptions(
|
||||||
useShouldOverrideUrlLoading: false,
|
useShouldOverrideUrlLoading: false,
|
||||||
mediaPlaybackRequiresUserGesture: false,
|
mediaPlaybackRequiresUserGesture: false,
|
||||||
|
clearCache: true
|
||||||
),
|
),
|
||||||
android: AndroidInAppWebViewOptions(
|
android: AndroidInAppWebViewOptions(
|
||||||
useHybridComposition: true,
|
useHybridComposition: true,
|
||||||
),
|
),
|
||||||
ios: IOSInAppWebViewOptions(
|
ios: IOSInAppWebViewOptions(
|
||||||
allowsInlineMediaPlayback: true,
|
allowsInlineMediaPlayback: true,
|
||||||
|
// limitsNavigationsToAppBoundDomains: true // adds Service Worker API on iOS 14.0+
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
onWebViewCreated: (controller) {
|
onWebViewCreated: (controller) {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import 'package:flutter_inappwebview_example/in_app_browser_example.screen.dart'
|
||||||
|
|
||||||
// InAppLocalhostServer localhostServer = new InAppLocalhostServer();
|
// InAppLocalhostServer localhostServer = new InAppLocalhostServer();
|
||||||
|
|
||||||
|
AndroidServiceWorkerController serviceWorkerController = AndroidServiceWorkerController.instance();
|
||||||
|
|
||||||
Future main() async {
|
Future main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
// await Permission.camera.request();
|
// await Permission.camera.request();
|
||||||
|
@ -19,6 +21,16 @@ Future main() async {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST)) {
|
||||||
|
serviceWorkerController.serviceWorkerClient = AndroidServiceWorkerClient(
|
||||||
|
shouldInterceptRequest: (request) async {
|
||||||
|
print(request);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -37,4 +37,6 @@ export 'src/http_auth_credentials_database.dart';
|
||||||
export 'src/web_storage_manager.dart';
|
export 'src/web_storage_manager.dart';
|
||||||
export 'src/context_menu.dart';
|
export 'src/context_menu.dart';
|
||||||
export 'src/web_storage.dart';
|
export 'src/web_storage.dart';
|
||||||
export 'src/X509Certificate/main.dart';
|
export 'src/X509Certificate/main.dart';
|
||||||
|
export 'src/android/service_worker_controller.dart';
|
||||||
|
export 'src/android/webview_feature.dart';
|
|
@ -0,0 +1,179 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'webview_feature.dart';
|
||||||
|
import '../types.dart';
|
||||||
|
|
||||||
|
///Class that represents an Android-specific class that manages Service Workers used by [WebView].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerControllerCompat
|
||||||
|
class AndroidServiceWorkerController {
|
||||||
|
static AndroidServiceWorkerController? _instance;
|
||||||
|
static const MethodChannel _channel = const MethodChannel(
|
||||||
|
'com.pichillilorenzo/flutter_inappwebview_android_serviceworkercontroller');
|
||||||
|
|
||||||
|
AndroidServiceWorkerClient? serviceWorkerClient;
|
||||||
|
|
||||||
|
///Gets the [AndroidServiceWorkerController] shared instance.
|
||||||
|
static AndroidServiceWorkerController instance() {
|
||||||
|
return (_instance != null) ? _instance! : _init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static AndroidServiceWorkerController _init() {
|
||||||
|
_channel.setMethodCallHandler(_handleMethod);
|
||||||
|
_instance = AndroidServiceWorkerController();
|
||||||
|
return _instance!;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<dynamic> _handleMethod(MethodCall call) async {
|
||||||
|
AndroidServiceWorkerController controller = AndroidServiceWorkerController.instance();
|
||||||
|
AndroidServiceWorkerClient? serviceWorkerClient = controller.serviceWorkerClient;
|
||||||
|
|
||||||
|
switch (call.method) {
|
||||||
|
case "shouldInterceptRequest":
|
||||||
|
String url = call.arguments["url"];
|
||||||
|
String method = call.arguments["method"];
|
||||||
|
Map<String, String>? headers =
|
||||||
|
call.arguments["headers"]?.cast<String, String>();
|
||||||
|
bool isForMainFrame = call.arguments["isForMainFrame"];
|
||||||
|
bool hasGesture = call.arguments["hasGesture"];
|
||||||
|
bool isRedirect = call.arguments["isRedirect"];
|
||||||
|
|
||||||
|
var request = new WebResourceRequest(
|
||||||
|
url: url,
|
||||||
|
method: method,
|
||||||
|
headers: headers,
|
||||||
|
isForMainFrame: isForMainFrame,
|
||||||
|
hasGesture: hasGesture,
|
||||||
|
isRedirect: isRedirect);
|
||||||
|
|
||||||
|
if (serviceWorkerClient != null && serviceWorkerClient.shouldInterceptRequest != null) {
|
||||||
|
return (await serviceWorkerClient.shouldInterceptRequest!(request))
|
||||||
|
?.toMap();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw UnimplementedError("Unimplemented ${call.method} method");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Gets whether Service Workers support content URL access.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_CONTENT_ACCESS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getAllowContentAccess()
|
||||||
|
static Future<bool> getAllowContentAccess() async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
return await _channel.invokeMethod('getAllowContentAccess', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Gets whether Service Workers support file access.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_FILE_ACCESS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getAllowFileAccess()
|
||||||
|
static Future<bool> getAllowFileAccess() async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
return await _channel.invokeMethod('getAllowFileAccess', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Gets whether Service Workers are prohibited from loading any resources from the network.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getBlockNetworkLoads()
|
||||||
|
static Future<bool> getBlockNetworkLoads() async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
return await _channel.invokeMethod('getBlockNetworkLoads', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Gets the current setting for overriding the cache mode.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_CACHE_MODE].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#getCacheMode()
|
||||||
|
static Future<AndroidCacheMode?> getCacheMode() async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
return AndroidCacheMode.fromValue(await _channel.invokeMethod('getCacheMode', args));
|
||||||
|
}
|
||||||
|
|
||||||
|
///Enables or disables content URL access from Service Workers.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_CONTENT_ACCESS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setAllowContentAccess(boolean)
|
||||||
|
static Future<void> setAllowContentAccess(bool allow) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("allow", () => allow);
|
||||||
|
await _channel.invokeMethod('setAllowContentAccess', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Enables or disables file access within Service Workers.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_FILE_ACCESS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setAllowFileAccess(boolean)
|
||||||
|
static Future<void> setAllowFileAccess(bool allow) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("allow", () => allow);
|
||||||
|
await _channel.invokeMethod('setAllowFileAccess', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Sets whether Service Workers should not load resources from the network.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setBlockNetworkLoads(boolean)
|
||||||
|
static Future<void> setBlockNetworkLoads(bool flag) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("flag", () => flag);
|
||||||
|
await _channel.invokeMethod('setBlockNetworkLoads', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
///Overrides the way the cache is used.
|
||||||
|
///This method should only be called if [AndroidWebViewFeature.isFeatureSupported] returns `true` for [AndroidWebViewFeature.SERVICE_WORKER_CACHE_MODE].
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerWebSettingsCompat#setCacheMode(int)
|
||||||
|
static Future<void> setCacheMode(AndroidCacheMode mode) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("mode", () => mode.toValue());
|
||||||
|
await _channel.invokeMethod('setCacheMode', args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Class that represents an Android-specific class for clients to capture Service Worker related callbacks.
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/ServiceWorkerClientCompat
|
||||||
|
class AndroidServiceWorkerClient {
|
||||||
|
|
||||||
|
///Notify the host application of a resource request and allow the application to return the data.
|
||||||
|
///If the return value is `null`, the Service Worker will continue to load the resource as usual.
|
||||||
|
///Otherwise, the return response and data will be used.
|
||||||
|
///
|
||||||
|
///This method is called only if [AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST] is supported.
|
||||||
|
///You can check whether that flag is supported using [AndroidWebViewFeature.isFeatureSupported].
|
||||||
|
///
|
||||||
|
///[request] represents an object containing the details of the request.
|
||||||
|
///
|
||||||
|
///**NOTE**: available on Android 24+.
|
||||||
|
final Future<WebResourceResponse?> Function(WebResourceRequest request)?
|
||||||
|
shouldInterceptRequest;
|
||||||
|
|
||||||
|
AndroidServiceWorkerClient({
|
||||||
|
this.shouldInterceptRequest
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
///Class that represents an Android-specific utility class for checking which WebView Support Library features are supported on the device.
|
||||||
|
class AndroidWebViewFeature {
|
||||||
|
static const MethodChannel _channel = const MethodChannel(
|
||||||
|
'com.pichillilorenzo/flutter_inappwebview_android_webviewfeature');
|
||||||
|
|
||||||
|
static Future<dynamic> _handleMethod(MethodCall call) async {}
|
||||||
|
|
||||||
|
final String _value;
|
||||||
|
|
||||||
|
const AndroidWebViewFeature._internal(this._value);
|
||||||
|
|
||||||
|
static final Set<AndroidWebViewFeature> values = [
|
||||||
|
AndroidWebViewFeature.CREATE_WEB_MESSAGE_CHANNEL,
|
||||||
|
AndroidWebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
|
||||||
|
AndroidWebViewFeature.FORCE_DARK,
|
||||||
|
AndroidWebViewFeature.FORCE_DARK_STRATEGY,
|
||||||
|
AndroidWebViewFeature.GET_WEB_CHROME_CLIENT,
|
||||||
|
AndroidWebViewFeature.GET_WEB_VIEW_CLIENT,
|
||||||
|
AndroidWebViewFeature.GET_WEB_VIEW_RENDERER,
|
||||||
|
AndroidWebViewFeature.MULTI_PROCESS,
|
||||||
|
AndroidWebViewFeature.OFF_SCREEN_PRERASTER,
|
||||||
|
AndroidWebViewFeature.POST_WEB_MESSAGE,
|
||||||
|
AndroidWebViewFeature.PROXY_OVERRIDE,
|
||||||
|
AndroidWebViewFeature.RECEIVE_HTTP_ERROR,
|
||||||
|
AndroidWebViewFeature.RECEIVE_WEB_RESOURCE_ERROR,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_ALLOWLIST,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_ENABLE,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_HIT,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
|
||||||
|
AndroidWebViewFeature.SAFE_BROWSING_WHITELIST,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_BASIC_USAGE,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_CACHE_MODE,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_FILE_ACCESS,
|
||||||
|
AndroidWebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST,
|
||||||
|
AndroidWebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS,
|
||||||
|
AndroidWebViewFeature.START_SAFE_BROWSING,
|
||||||
|
AndroidWebViewFeature.TRACING_CONTROLLER_BASIC_USAGE,
|
||||||
|
AndroidWebViewFeature.VISUAL_STATE_CALLBACK,
|
||||||
|
AndroidWebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE,
|
||||||
|
AndroidWebViewFeature.WEB_MESSAGE_LISTENER,
|
||||||
|
AndroidWebViewFeature.WEB_MESSAGE_PORT_CLOSE,
|
||||||
|
AndroidWebViewFeature.WEB_MESSAGE_PORT_POST_MESSAGE,
|
||||||
|
AndroidWebViewFeature.WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK,
|
||||||
|
AndroidWebViewFeature.WEB_RESOURCE_ERROR_GET_CODE,
|
||||||
|
AndroidWebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
|
||||||
|
AndroidWebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
|
||||||
|
AndroidWebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
|
||||||
|
AndroidWebViewFeature.WEB_VIEW_RENDERER_TERMINATE,
|
||||||
|
].toSet();
|
||||||
|
|
||||||
|
static AndroidWebViewFeature? fromValue(String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
try {
|
||||||
|
return AndroidWebViewFeature.values.firstWhere(
|
||||||
|
(element) => element.toValue() == value);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String toValue() => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _value;
|
||||||
|
|
||||||
|
///
|
||||||
|
static const CREATE_WEB_MESSAGE_CHANNEL = const AndroidWebViewFeature._internal("CREATE_WEB_MESSAGE_CHANNEL");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const DISABLED_ACTION_MODE_MENU_ITEMS = const AndroidWebViewFeature._internal("DISABLED_ACTION_MODE_MENU_ITEMS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const FORCE_DARK = const AndroidWebViewFeature._internal("FORCE_DARK");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const FORCE_DARK_STRATEGY = const AndroidWebViewFeature._internal("FORCE_DARK_STRATEGY");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const GET_WEB_CHROME_CLIENT = const AndroidWebViewFeature._internal("GET_WEB_CHROME_CLIENT");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const GET_WEB_VIEW_CLIENT = const AndroidWebViewFeature._internal("GET_WEB_VIEW_CLIENT");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const GET_WEB_VIEW_RENDERER = const AndroidWebViewFeature._internal("GET_WEB_VIEW_RENDERER");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const MULTI_PROCESS = const AndroidWebViewFeature._internal("MULTI_PROCESS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const OFF_SCREEN_PRERASTER = const AndroidWebViewFeature._internal("OFF_SCREEN_PRERASTER");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const POST_WEB_MESSAGE = const AndroidWebViewFeature._internal("POST_WEB_MESSAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const PROXY_OVERRIDE = const AndroidWebViewFeature._internal("PROXY_OVERRIDE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const RECEIVE_HTTP_ERROR = const AndroidWebViewFeature._internal("RECEIVE_HTTP_ERROR");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const RECEIVE_WEB_RESOURCE_ERROR = const AndroidWebViewFeature._internal("RECEIVE_WEB_RESOURCE_ERROR");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_ALLOWLIST = const AndroidWebViewFeature._internal("SAFE_BROWSING_ALLOWLIST");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_ENABLE = const AndroidWebViewFeature._internal("SAFE_BROWSING_ENABLE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_HIT = const AndroidWebViewFeature._internal("SAFE_BROWSING_HIT");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_PRIVACY_POLICY_URL = const AndroidWebViewFeature._internal("SAFE_BROWSING_PRIVACY_POLICY_URL");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY = const AndroidWebViewFeature._internal("SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_RESPONSE_PROCEED = const AndroidWebViewFeature._internal("SAFE_BROWSING_RESPONSE_PROCEED");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL = const AndroidWebViewFeature._internal("SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SAFE_BROWSING_WHITELIST = const AndroidWebViewFeature._internal("SAFE_BROWSING_WHITELIST");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_BASIC_USAGE = const AndroidWebViewFeature._internal("SERVICE_WORKER_BASIC_USAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_BLOCK_NETWORK_LOADS = const AndroidWebViewFeature._internal("SERVICE_WORKER_BLOCK_NETWORK_LOADS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_CACHE_MODE = const AndroidWebViewFeature._internal("SERVICE_WORKER_CACHE_MODE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_CONTENT_ACCESS = const AndroidWebViewFeature._internal("SERVICE_WORKER_CONTENT_ACCESS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_FILE_ACCESS = const AndroidWebViewFeature._internal("SERVICE_WORKER_FILE_ACCESS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST = const AndroidWebViewFeature._internal("SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const SHOULD_OVERRIDE_WITH_REDIRECTS = const AndroidWebViewFeature._internal("SHOULD_OVERRIDE_WITH_REDIRECTS");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const START_SAFE_BROWSING = const AndroidWebViewFeature._internal("START_SAFE_BROWSING");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const TRACING_CONTROLLER_BASIC_USAGE = const AndroidWebViewFeature._internal("TRACING_CONTROLLER_BASIC_USAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const VISUAL_STATE_CALLBACK = const AndroidWebViewFeature._internal("VISUAL_STATE_CALLBACK");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_MESSAGE_CALLBACK_ON_MESSAGE = const AndroidWebViewFeature._internal("WEB_MESSAGE_CALLBACK_ON_MESSAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_MESSAGE_LISTENER = const AndroidWebViewFeature._internal("WEB_MESSAGE_LISTENER");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_MESSAGE_PORT_CLOSE = const AndroidWebViewFeature._internal("WEB_MESSAGE_PORT_CLOSE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_MESSAGE_PORT_POST_MESSAGE = const AndroidWebViewFeature._internal("WEB_MESSAGE_PORT_POST_MESSAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK = const AndroidWebViewFeature._internal("WEB_MESSAGE_PORT_SET_MESSAGE_CALLBACK");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_RESOURCE_ERROR_GET_CODE = const AndroidWebViewFeature._internal("WEB_RESOURCE_ERROR_GET_CODE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_RESOURCE_ERROR_GET_DESCRIPTION = const AndroidWebViewFeature._internal("WEB_RESOURCE_ERROR_GET_DESCRIPTION");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_RESOURCE_REQUEST_IS_REDIRECT = const AndroidWebViewFeature._internal("WEB_RESOURCE_REQUEST_IS_REDIRECT");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE = const AndroidWebViewFeature._internal("WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE");
|
||||||
|
|
||||||
|
///
|
||||||
|
static const WEB_VIEW_RENDERER_TERMINATE = const AndroidWebViewFeature._internal("WEB_VIEW_RENDERER_TERMINATE");
|
||||||
|
|
||||||
|
bool operator ==(value) => value == _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => _value.hashCode;
|
||||||
|
|
||||||
|
///Return whether a feature is supported at run-time. On devices running Android version `Build.VERSION_CODES.LOLLIPOP` and higher,
|
||||||
|
///this will check whether a feature is supported, depending on the combination of the desired feature, the Android version of device,
|
||||||
|
///and the WebView APK on the device. If running on a device with a lower API level, this will always return `false`.
|
||||||
|
///
|
||||||
|
///**Official Android API**: https://developer.android.com/reference/androidx/webkit/WebViewFeature#isFeatureSupported(java.lang.String)
|
||||||
|
static Future<bool> isFeatureSupported(AndroidWebViewFeature feature) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("feature", () => feature.toValue());
|
||||||
|
return await _channel.invokeMethod('isFeatureSupported', args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -929,6 +929,7 @@ class InAppWebViewController {
|
||||||
default:
|
default:
|
||||||
throw UnimplementedError("Unimplemented ${call.method} method");
|
throw UnimplementedError("Unimplemented ${call.method} method");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Gets the URL for the current page.
|
///Gets the URL for the current page.
|
||||||
|
|
|
@ -4601,7 +4601,7 @@ class UserScript {
|
||||||
///
|
///
|
||||||
///**NOTE for iOS 14.0+**: this class represents the native [WKContentWorld](https://developer.apple.com/documentation/webkit/wkcontentworld) class.
|
///**NOTE for iOS 14.0+**: this class represents the native [WKContentWorld](https://developer.apple.com/documentation/webkit/wkcontentworld) class.
|
||||||
///
|
///
|
||||||
///**NOTE for Android**: it will create and append an `<iframe>` HTML element with `id` equals to [name] to the webpage's content that contains only the scripts
|
///**NOTE for Android**: it will create and append an `<iframe>` HTML element with `id` equals to `flutter_inappwebview_[name]` to the webpage's content that contains only the scripts
|
||||||
///in order to define a new scope of execution for JavaScript code. Unfortunately, there isn't any other way to do it.
|
///in order to define a new scope of execution for JavaScript code. Unfortunately, there isn't any other way to do it.
|
||||||
///For any [ContentWorld], except [ContentWorld.page], if you need to access to the `window` or `document` global Object,
|
///For any [ContentWorld], except [ContentWorld.page], if you need to access to the `window` or `document` global Object,
|
||||||
///you need to use `window.top` and `window.top.document` because the code runs inside an `<iframe>`.
|
///you need to use `window.top` and `window.top.document` because the code runs inside an `<iframe>`.
|
||||||
|
@ -4620,4 +4620,4 @@ class ContentWorld {
|
||||||
///Be careful when manipulating variables in this content world.
|
///Be careful when manipulating variables in this content world.
|
||||||
///If you modify a variable with the same name as one the webpage uses, you may unintentionally disrupt the normal operation of that page.
|
///If you modify a variable with the same name as one the webpage uses, you may unintentionally disrupt the normal operation of that page.
|
||||||
static ContentWorld page = ContentWorld.world(name: "page");
|
static ContentWorld page = ContentWorld.world(name: "page");
|
||||||
}
|
}
|
Loading…
Reference in New Issue