fixed iOS nil exception on URLRequest url property, update some iOS classes to use ChannelDelegate class and Disposable protocol, added some more null checks on Android

This commit is contained in:
Lorenzo Pichilli 2022-05-05 20:19:16 +02:00
parent 92abeea57f
commit 88e89bd102
42 changed files with 393 additions and 351 deletions

View File

@ -13,6 +13,7 @@ import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
public class FlutterWebViewFactory extends PlatformViewFactory {
public static final String VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview";
private final InAppWebViewFlutterPlugin plugin;
public FlutterWebViewFactory(final InAppWebViewFlutterPlugin plugin) {

View File

@ -87,7 +87,7 @@ public class InAppWebViewFlutterPlugin implements FlutterPlugin, ActivityAware {
chromeSafariBrowserManager = new ChromeSafariBrowserManager(this);
flutterWebViewFactory = new FlutterWebViewFactory(this);
platformViewRegistry.registerViewFactory(
"com.pichillilorenzo/flutter_inappwebview", flutterWebViewFactory);
FlutterWebViewFactory.VIEW_TYPE_ID, flutterWebViewFactory);
platformUtil = new PlatformUtil(this);
inAppWebViewStatic = new InAppWebViewStatic(this);

View File

@ -12,7 +12,6 @@ import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.lang.reflect.Method;
import java.util.HashMap;
@ -24,7 +23,7 @@ import java.util.Set;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class InAppWebViewStatic extends ChannelDelegateImpl implements Disposable {
public class InAppWebViewStatic extends ChannelDelegateImpl {
protected static final String LOG_TAG = "InAppWebViewStatic";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_static";

View File

@ -9,7 +9,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -23,10 +22,10 @@ import java.util.TimeZone;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class MyCookieManager extends ChannelDelegateImpl implements Disposable {
public class MyCookieManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "MyCookieManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_cookiemanager";
@Nullable
public static CookieManager cookieManager;
@Nullable
public InAppWebViewFlutterPlugin plugin;
@ -305,5 +304,6 @@ public class MyCookieManager extends ChannelDelegateImpl implements Disposable {
public void dispose() {
super.dispose();
plugin = null;
cookieManager = null;
}
}

View File

@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.util.ArrayList;
import java.util.HashMap;
@ -17,10 +16,11 @@ import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
public class MyWebStorage extends ChannelDelegateImpl {
protected static final String LOG_TAG = "MyWebStorage";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_webstoragemanager";
@Nullable
public static WebStorage webStorageManager;
@Nullable
public InAppWebViewFlutterPlugin plugin;
@ -38,15 +38,23 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
getOrigins(result);
break;
case "deleteAllData":
webStorageManager.deleteAllData();
result.success(true);
if (webStorageManager == null) {
webStorageManager.deleteAllData();
result.success(true);
} else {
result.success(false);
}
break;
case "deleteOrigin":
{
String origin = (String) call.argument("origin");
webStorageManager.deleteOrigin(origin);
if (webStorageManager == null) {
String origin = (String) call.argument("origin");
webStorageManager.deleteOrigin(origin);
result.success(true);
} else {
result.success(false);
}
}
result.success(true);
break;
case "getQuotaForOrigin":
{
@ -57,7 +65,7 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
case "getUsageForOrigin":
{
String origin = (String) call.argument("origin");
getUsageForOrigin(origin, result);
getUsageForOrigin(origin, result);
}
break;
default:
@ -66,6 +74,10 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
}
public void getOrigins(final MethodChannel.Result result) {
if (webStorageManager == null) {
result.success(new ArrayList<>());
return;
}
webStorageManager.getOrigins(new ValueCallback<Map>() {
@Override
public void onReceiveValue(Map value) {
@ -86,6 +98,10 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
}
public void getQuotaForOrigin(String origin, final MethodChannel.Result result) {
if (webStorageManager == null) {
result.success(0);
return;
}
webStorageManager.getQuotaForOrigin(origin, new ValueCallback<Long>() {
@Override
public void onReceiveValue(Long value) {
@ -95,6 +111,10 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
}
public void getUsageForOrigin(String origin, final MethodChannel.Result result) {
if (webStorageManager == null) {
result.success(0);
return;
}
webStorageManager.getUsageForOrigin(origin, new ValueCallback<Long>() {
@Override
public void onReceiveValue(Long value) {
@ -107,5 +127,6 @@ public class MyWebStorage extends ChannelDelegateImpl implements Disposable {
public void dispose() {
super.dispose();
plugin = null;
webStorageManager = null;
}
}

View File

@ -6,7 +6,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -16,7 +15,7 @@ import java.util.TimeZone;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class PlatformUtil extends ChannelDelegateImpl implements Disposable {
public class PlatformUtil extends ChannelDelegateImpl {
protected static final String LOG_TAG = "PlatformUtil";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_platformutil";

View File

@ -1,46 +0,0 @@
package com.pichillilorenzo.flutter_inappwebview;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class RequestPermissionHandler implements ActivityCompat.OnRequestPermissionsResultCallback {
private static Map<Integer, List<Runnable>> actionDictionary = new HashMap<>();
public static void checkAndRun(Activity activity, String permission, int requestCode, Runnable runnable) {
int permissionCheck = ContextCompat.checkSelfPermission(activity.getApplicationContext(), permission);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (actionDictionary.containsKey(requestCode))
actionDictionary.get(requestCode).add(runnable);
else
actionDictionary.put(requestCode, Arrays.asList(runnable));
ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode);
}
else
runnable.run();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
List<Runnable> callbacks = actionDictionary.get(requestCode);
for (Runnable runnable : callbacks) {
runnable.run();
callbacks.remove(runnable);
}
}
}
}

View File

@ -5,12 +5,11 @@ import androidx.annotation.Nullable;
import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class WebViewFeatureManager extends ChannelDelegateImpl implements Disposable {
public class WebViewFeatureManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "WebViewFeatureManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_webviewfeature";

View File

@ -9,7 +9,6 @@ import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.Util;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.io.Serializable;
import java.util.HashMap;
@ -20,7 +19,7 @@ import java.util.UUID;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class ChromeSafariBrowserManager extends ChannelDelegateImpl implements Disposable {
public class ChromeSafariBrowserManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "ChromeBrowserManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_chromesafaribrowser";

View File

@ -9,7 +9,6 @@ import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import com.pichillilorenzo.flutter_inappwebview.types.URLCredential;
import com.pichillilorenzo.flutter_inappwebview.types.URLProtectionSpace;
@ -22,10 +21,11 @@ import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
@RequiresApi(api = Build.VERSION_CODES.O)
public class CredentialDatabaseHandler extends ChannelDelegateImpl implements Disposable {
public class CredentialDatabaseHandler extends ChannelDelegateImpl {
protected static final String LOG_TAG = "CredentialDatabaseHandler";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_credential_database";
@Nullable
public static CredentialDatabase credentialDatabase;
@Nullable
public InAppWebViewFlutterPlugin plugin;
@ -42,80 +42,97 @@ public class CredentialDatabaseHandler extends ChannelDelegateImpl implements Di
case "getAllAuthCredentials":
{
List<Map<String, Object>> allCredentials = new ArrayList<>();
List<URLProtectionSpace> protectionSpaces = credentialDatabase.protectionSpaceDao.getAll();
for (URLProtectionSpace protectionSpace : protectionSpaces) {
List<Map<String, Object>> credentials = new ArrayList<>();
for (URLCredential credential : credentialDatabase.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId())) {
credentials.add(credential.toMap());
if (credentialDatabase != null) {
List<URLProtectionSpace> protectionSpaces = credentialDatabase.protectionSpaceDao.getAll();
for (URLProtectionSpace protectionSpace : protectionSpaces) {
List<Map<String, Object>> credentials = new ArrayList<>();
for (URLCredential credential : credentialDatabase.credentialDao.getAllByProtectionSpaceId(protectionSpace.getId())) {
credentials.add(credential.toMap());
}
Map<String, Object> obj = new HashMap<>();
obj.put("protectionSpace", protectionSpace.toMap());
obj.put("credentials", credentials);
allCredentials.add(obj);
}
Map<String, Object> obj = new HashMap<>();
obj.put("protectionSpace", protectionSpace.toMap());
obj.put("credentials", credentials);
allCredentials.add(obj);
}
result.success(allCredentials);
}
break;
case "getHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
List<Map<String, Object>> credentials = new ArrayList<>();
for (URLCredential credential : credentialDatabase.getHttpAuthCredentials(host, protocol, realm, port)) {
credentials.add(credential.toMap());
if (credentialDatabase != null) {
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
for (URLCredential credential : credentialDatabase.getHttpAuthCredentials(host, protocol, realm, port)) {
credentials.add(credential.toMap());
}
}
result.success(credentials);
}
break;
case "setHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
if (credentialDatabase != null) {
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.setHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
credentialDatabase.setHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
} else {
result.success(false);
}
}
break;
case "removeHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
if (credentialDatabase != null) {
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
} else {
result.success(false);
}
}
break;
case "removeHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
if (credentialDatabase != null) {
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port);
result.success(true);
credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port);
result.success(true);
} else {
result.success(false);
}
}
break;
case "clearAllAuthCredentials":
credentialDatabase.clearAllAuthCredentials();
if (plugin != null && plugin.applicationContext != null) {
WebViewDatabase.getInstance(plugin.applicationContext).clearHttpAuthUsernamePassword();
if (credentialDatabase != null) {
credentialDatabase.clearAllAuthCredentials();
if (plugin != null && plugin.applicationContext != null) {
WebViewDatabase.getInstance(plugin.applicationContext).clearHttpAuthUsernamePassword();
}
result.success(true);
} else {
result.success(false);
}
result.success(true);
break;
default:
result.notImplemented();
@ -126,5 +143,6 @@ public class CredentialDatabaseHandler extends ChannelDelegateImpl implements Di
public void dispose() {
super.dispose();
plugin = null;
credentialDatabase = null;
}
}

View File

@ -27,7 +27,6 @@ import androidx.annotation.NonNull;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.webview.in_app_webview.FlutterWebView;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.util.Collection;
import java.util.HashMap;
@ -37,7 +36,7 @@ import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
public class HeadlessInAppWebViewManager extends ChannelDelegateImpl implements Disposable {
public class HeadlessInAppWebViewManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "HeadlessInAppWebViewManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview";

View File

@ -37,7 +37,6 @@ import androidx.annotation.Nullable;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import java.io.Serializable;
import java.util.ArrayList;
@ -53,7 +52,7 @@ import io.flutter.plugin.common.MethodChannel.Result;
/**
* InAppBrowserManager
*/
public class InAppBrowserManager extends ChannelDelegateImpl implements Disposable {
public class InAppBrowserManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "InAppBrowserManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappbrowser";

View File

@ -8,7 +8,6 @@ import androidx.webkit.WebViewFeature;
import com.pichillilorenzo.flutter_inappwebview.InAppWebViewFlutterPlugin;
import com.pichillilorenzo.flutter_inappwebview.types.ChannelDelegateImpl;
import com.pichillilorenzo.flutter_inappwebview.types.Disposable;
import com.pichillilorenzo.flutter_inappwebview.types.ProxyRuleExt;
import java.util.HashMap;
@ -17,7 +16,7 @@ import java.util.concurrent.Executor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
public class ProxyManager extends ChannelDelegateImpl implements Disposable {
public class ProxyManager extends ChannelDelegateImpl {
protected static final String LOG_TAG = "ProxyManager";
public static final String METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_proxycontroller";

View File

@ -4,8 +4,7 @@ import androidx.annotation.Nullable;
import io.flutter.plugin.common.MethodChannel;
public interface IChannelDelegate extends MethodChannel.MethodCallHandler {
public interface IChannelDelegate extends MethodChannel.MethodCallHandler, Disposable {
@Nullable
MethodChannel getChannel();
void dispose();
}

View File

@ -1,6 +1,5 @@
package com.pichillilorenzo.flutter_inappwebview.types;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Arrays;
@ -8,7 +7,7 @@ import java.util.HashMap;
import java.util.Map;
public class URLRequest {
@NonNull
@Nullable
private String url;
@Nullable
private String method;
@ -17,7 +16,7 @@ public class URLRequest {
@Nullable
private Map<String, String> headers;
public URLRequest(@NonNull String url, @Nullable String method, @Nullable byte[] body, @Nullable Map<String, String> headers) {
public URLRequest(@Nullable String url, @Nullable String method, @Nullable byte[] body, @Nullable Map<String, String> headers) {
this.url = url;
this.method = method;
this.body = body;
@ -30,10 +29,12 @@ public class URLRequest {
return null;
}
String url = (String) map.get("url");
if (url == null) {
url = "about:blank";
}
String method = (String) map.get("method");
byte[] body = (byte[]) map.get("body");
Map<String, String> headers = (Map<String, String>) map.get("headers");
assert url != null;
return new URLRequest(url, method, body, headers);
}
@ -55,12 +56,12 @@ public class URLRequest {
return urlRequestMap;
}
@NonNull
@Nullable
public String getUrl() {
return url;
}
public void setUrl(@NonNull String url) {
public void setUrl(@Nullable String url) {
this.url = url;
}
@ -98,7 +99,7 @@ public class URLRequest {
URLRequest that = (URLRequest) o;
if (!url.equals(that.url)) return false;
if (url != null ? !url.equals(that.url) : that.url != null) return false;
if (method != null ? !method.equals(that.method) : that.method != null) return false;
if (!Arrays.equals(body, that.body)) return false;
return headers != null ? headers.equals(that.headers) : that.headers == null;
@ -106,7 +107,7 @@ public class URLRequest {
@Override
public int hashCode() {
int result = url.hashCode();
int result = url != null ? url.hashCode() : 0;
result = 31 * result + (method != null ? method.hashCode() : 0);
result = 31 * result + Arrays.hashCode(body);
result = 31 * result + (headers != null ? headers.hashCode() : 0);

View File

@ -3,11 +3,12 @@
export "FLUTTER_ROOT=/Users/lorenzopichilli/fvm/versions/2.10.4"
export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ=="
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"
export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json"

View File

@ -7,26 +7,18 @@
import Foundation
class CredentialDatabase: NSObject, FlutterPlugin {
class CredentialDatabase: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_credential_database"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var credentialStore: URLCredentialStorage?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: CredentialDatabase.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
CredentialDatabase.registrar = registrar
CredentialDatabase.credentialStore = URLCredentialStorage.shared
CredentialDatabase.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_credential_database", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: CredentialDatabase.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "getAllAuthCredentials":
@ -196,9 +188,8 @@ class CredentialDatabase: NSObject, FlutterPlugin {
}
}
public func dispose() {
CredentialDatabase.channel?.setMethodCallHandler(nil)
CredentialDatabase.channel = nil
public override func dispose() {
super.dispose()
CredentialDatabase.registrar = nil
CredentialDatabase.credentialStore = nil
}

View File

@ -7,47 +7,22 @@
import Foundation
public class HeadlessInAppWebView : FlutterMethodCallDelegate {
public class HeadlessInAppWebView : Disposable {
static let METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_headless_inappwebview_"
var id: String
var channel: FlutterMethodChannel?
var channelDelegate: HeadlessWebViewChannelDelegate?
var flutterWebView: FlutterWebViewController?
public init(id: String, flutterWebView: FlutterWebViewController) {
self.id = id
super.init()
self.flutterWebView = flutterWebView
self.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_headless_inappwebview_" + id,
let channel = FlutterMethodChannel(name: HeadlessInAppWebView.METHOD_CHANNEL_NAME_PREFIX + id,
binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
self.channel?.setMethodCallHandler(self.handle)
}
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "dispose":
dispose()
result(true)
break
case "setSize":
let sizeMap = arguments!["size"] as? [String: Any?]
if let size = Size2D.fromMap(map: sizeMap) {
setSize(size: size)
}
result(true)
break
case "getSize":
result(getSize()?.toMap())
break
default:
result(FlutterMethodNotImplemented)
break
}
self.channelDelegate = HeadlessWebViewChannelDelegate(headlessWebView: self, channel: channel)
}
public func onWebViewCreated() {
let arguments: [String: Any?] = [:]
channel?.invokeMethod("onWebViewCreated", arguments: arguments)
channelDelegate?.onWebViewCreated();
}
public func prepare(params: NSDictionary) {
@ -87,8 +62,8 @@ public class HeadlessInAppWebView : FlutterMethodCallDelegate {
}
public func dispose() {
channel?.setMethodCallHandler(nil)
channel = nil
channelDelegate?.dispose()
channelDelegate = nil
HeadlessInAppWebViewManager.webViews[id] = nil
flutterWebView = nil
}

View File

@ -13,23 +13,17 @@ import WebKit
import Foundation
import AVFoundation
public class HeadlessInAppWebViewManager: NSObject, FlutterPlugin {
public class HeadlessInAppWebViewManager: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_headless_inappwebview"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var webViews: [String: HeadlessInAppWebView?] = [:]
public static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: HeadlessInAppWebViewManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
HeadlessInAppWebViewManager.registrar = registrar
HeadlessInAppWebViewManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_headless_inappwebview", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: HeadlessInAppWebViewManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
let id: String = arguments!["id"] as! String
@ -58,9 +52,8 @@ public class HeadlessInAppWebViewManager: NSObject, FlutterPlugin {
flutterWebView.makeInitialLoad(params: params as NSDictionary)
}
public func dispose() {
HeadlessInAppWebViewManager.channel?.setMethodCallHandler(nil)
HeadlessInAppWebViewManager.channel = nil
public override func dispose() {
super.dispose()
HeadlessInAppWebViewManager.registrar = nil
let headlessWebViews = HeadlessInAppWebViewManager.webViews.values
headlessWebViews.forEach { (headlessWebView: HeadlessInAppWebView?) in

View File

@ -0,0 +1,59 @@
//
// HeadlessWebViewChannelDelegate.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 05/05/22.
//
import Foundation
public class HeadlessWebViewChannelDelegate : ChannelDelegate {
private var headlessWebView: HeadlessInAppWebView?
public init(headlessWebView: HeadlessInAppWebView, channel: FlutterMethodChannel) {
super.init(channel: channel)
self.headlessWebView = headlessWebView
}
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "dispose":
if let headlessWebView = headlessWebView {
headlessWebView.dispose()
result(true)
} else {
result(false)
}
break
case "setSize":
if let headlessWebView = headlessWebView {
let sizeMap = arguments!["size"] as? [String: Any?]
if let size = Size2D.fromMap(map: sizeMap) {
headlessWebView.setSize(size: size)
}
result(true)
} else {
result(false)
}
break
case "getSize":
result(headlessWebView?.getSize()?.toMap())
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public func onWebViewCreated() {
let arguments: [String: Any?] = [:]
channel?.invokeMethod("onWebViewCreated", arguments: arguments)
}
public override func dispose() {
super.dispose()
headlessWebView = nil
}
}

View File

@ -11,28 +11,21 @@ import WebKit
import Foundation
import AVFoundation
let WEBVIEW_STORYBOARD = "WebView"
let WEBVIEW_STORYBOARD_CONTROLLER_ID = "viewController"
let NAV_STORYBOARD_CONTROLLER_ID = "navController"
public class InAppBrowserManager: NSObject, FlutterPlugin {
public class InAppBrowserManager: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappbrowser"
static let WEBVIEW_STORYBOARD = "WebView"
static let WEBVIEW_STORYBOARD_CONTROLLER_ID = "viewController"
static let NAV_STORYBOARD_CONTROLLER_ID = "navController"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
private var previousStatusBarStyle = -1
public static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: InAppBrowserManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
InAppBrowserManager.registrar = registrar
InAppBrowserManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: InAppBrowserManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
@ -100,8 +93,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
}
public func presentViewController(webViewController: InAppBrowserWebViewController) {
let storyboard = UIStoryboard(name: WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppWebViewFlutterPlugin.self))
let navController = storyboard.instantiateViewController(withIdentifier: NAV_STORYBOARD_CONTROLLER_ID) as! InAppBrowserNavigationController
let storyboard = UIStoryboard(name: InAppBrowserManager.WEBVIEW_STORYBOARD, bundle: Bundle(for: InAppWebViewFlutterPlugin.self))
let navController = storyboard.instantiateViewController(withIdentifier: InAppBrowserManager.NAV_STORYBOARD_CONTROLLER_ID) as! InAppBrowserNavigationController
webViewController.edgesForExtendedLayout = []
navController.pushViewController(webViewController, animated: false)
webViewController.prepareNavigationControllerBeforeViewWillAppear()
@ -141,9 +134,8 @@ public class InAppBrowserManager: NSObject, FlutterPlugin {
result(true)
}
public func dispose() {
InAppBrowserManager.channel?.setMethodCallHandler(nil)
InAppBrowserManager.channel = nil
public override func dispose() {
super.dispose()
InAppBrowserManager.registrar = nil
}
}

View File

@ -65,11 +65,9 @@ public class InAppBrowserWebViewController: UIViewController, InAppBrowserDelega
methodCallDelegate = InAppWebViewMethodHandler(webView: webView!)
channel!.setMethodCallHandler(LeakAvoider(delegate: methodCallDelegate!).handle)
let pullToRefreshLayoutChannel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + id,
binaryMessenger: SwiftFlutterPlugin.instance!.registrar!.messenger())
let pullToRefreshSettings = PullToRefreshSettings()
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
let pullToRefreshControl = PullToRefreshControl(channel: pullToRefreshLayoutChannel, settings: pullToRefreshSettings)
let pullToRefreshControl = PullToRefreshControl(registrar: SwiftFlutterPlugin.instance!.registrar!, id: id, settings: pullToRefreshSettings)
webView.pullToRefreshControl = pullToRefreshControl
pullToRefreshControl.delegate = webView
pullToRefreshControl.prepare()

View File

@ -10,7 +10,7 @@ import Foundation
import WebKit
@available(iOS 11.0, *)
class CustomeSchemeHandler : NSObject, WKURLSchemeHandler {
class CustomSchemeHandler : NSObject, WKURLSchemeHandler {
var schemeHandlers: [Int:WKURLSchemeTask] = [:]
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {

View File

@ -63,11 +63,9 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
methodCallDelegate = InAppWebViewMethodHandler(webView: webView!)
channel!.setMethodCallHandler(LeakAvoider(delegate: methodCallDelegate!).handle)
let pullToRefreshLayoutChannel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_" + String(describing: viewId),
binaryMessenger: registrar.messenger())
let pullToRefreshSettings = PullToRefreshSettings()
let _ = pullToRefreshSettings.parse(settings: pullToRefreshInitialSettings)
let pullToRefreshControl = PullToRefreshControl(channel: pullToRefreshLayoutChannel, settings: pullToRefreshSettings)
let pullToRefreshControl = PullToRefreshControl(registrar: registrar, id: viewId, settings: pullToRefreshSettings)
webView!.pullToRefreshControl = pullToRefreshControl
pullToRefreshControl.delegate = webView!
pullToRefreshControl.prepare()

View File

@ -9,6 +9,7 @@ import Flutter
import Foundation
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
static let VIEW_TYPE_ID = "com.pichillilorenzo/flutter_inappwebview"
private var registrar: FlutterPluginRegistrar?
init(registrar: FlutterPluginRegistrar?) {

View File

@ -565,7 +565,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
if #available(iOS 11.0, *) {
for scheme in settings.resourceCustomSchemes {
configuration.setURLSchemeHandler(CustomeSchemeHandler(), forURLScheme: scheme)
configuration.setURLSchemeHandler(CustomSchemeHandler(), forURLScheme: scheme)
}
if settings.sharedCookiesEnabled {
// More info to sending cookies with WKWebView

View File

@ -8,24 +8,18 @@
import Foundation
import WebKit
class InAppWebViewStatic: NSObject, FlutterPlugin {
class InAppWebViewStatic: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_static"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var webViewForUserAgent: WKWebView?
static var defaultUserAgent: String?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: InAppWebViewStatic.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
InAppWebViewStatic.registrar = registrar
InAppWebViewStatic.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_static", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: InAppWebViewStatic.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
@ -73,9 +67,8 @@ class InAppWebViewStatic: NSObject, FlutterPlugin {
}
}
public func dispose() {
InAppWebViewStatic.channel?.setMethodCallHandler(nil)
InAppWebViewStatic.channel = nil
public override func dispose() {
super.dispose()
InAppWebViewStatic.registrar = nil
InAppWebViewStatic.webViewForUserAgent = nil
InAppWebViewStatic.defaultUserAgent = nil

View File

@ -9,26 +9,18 @@ import Foundation
import WebKit
@available(iOS 11.0, *)
class MyCookieManager: NSObject, FlutterPlugin {
class MyCookieManager: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_cookiemanager"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var httpCookieStore: WKHTTPCookieStore?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: MyCookieManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
MyCookieManager.registrar = registrar
MyCookieManager.httpCookieStore = WKWebsiteDataStore.default().httpCookieStore
MyCookieManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_cookiemanager", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: MyCookieManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "setCookie":
@ -298,9 +290,8 @@ class MyCookieManager: NSObject, FlutterPlugin {
})
}
public func dispose() {
MyCookieManager.channel?.setMethodCallHandler(nil)
MyCookieManager.channel = nil
public override func dispose() {
super.dispose()
MyCookieManager.registrar = nil
MyCookieManager.httpCookieStore = nil
}

View File

@ -9,26 +9,18 @@ import Foundation
import WebKit
@available(iOS 9.0, *)
class MyWebStorageManager: NSObject, FlutterPlugin {
class MyWebStorageManager: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_webstoragemanager"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var websiteDataStore: WKWebsiteDataStore?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: MyWebStorageManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
MyWebStorageManager.registrar = registrar
MyWebStorageManager.websiteDataStore = WKWebsiteDataStore.default()
MyWebStorageManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_webstoragemanager", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: MyWebStorageManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "fetchDataRecords":
@ -108,9 +100,8 @@ class MyWebStorageManager: NSObject, FlutterPlugin {
}
}
public func dispose() {
MyWebStorageManager.channel?.setMethodCallHandler(nil)
MyWebStorageManager.channel = nil
public override func dispose() {
super.dispose()
MyWebStorageManager.registrar = nil
MyWebStorageManager.websiteDataStore = nil
}

View File

@ -7,22 +7,16 @@
import Foundation
class PlatformUtil: NSObject, FlutterPlugin {
class PlatformUtil: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_inappwebview_platformutil"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: PlatformUtil.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
InAppWebViewStatic.registrar = registrar
InAppWebViewStatic.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappwebview_platformutil", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: InAppWebViewStatic.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
@ -61,9 +55,8 @@ class PlatformUtil: NSObject, FlutterPlugin {
return formatter.string(from: PlatformUtil.getDateFromMilliseconds(date: date))
}
public func dispose() {
PlatformUtil.channel?.setMethodCallHandler(nil)
PlatformUtil.channel = nil
public override func dispose() {
super.dispose()
PlatformUtil.registrar = nil
}
}

View File

@ -0,0 +1,90 @@
//
// PullToRefreshChannelDelegate.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 05/05/22.
//
import Foundation
public class PullToRefreshChannelDelegate : ChannelDelegate {
private var pullToRefreshControl: PullToRefreshControl?
public init(pullToRefreshControl: PullToRefreshControl , channel: FlutterMethodChannel) {
super.init(channel: channel)
self.pullToRefreshControl = pullToRefreshControl
}
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "setEnabled":
if let pullToRefreshView = pullToRefreshControl {
let enabled = arguments!["enabled"] as! Bool
if enabled {
pullToRefreshView.delegate?.enablePullToRefresh()
} else {
pullToRefreshView.delegate?.disablePullToRefresh()
}
result(true)
} else {
result(false)
}
break
case "setRefreshing":
if let pullToRefreshView = pullToRefreshControl {
let refreshing = arguments!["refreshing"] as! Bool
if refreshing {
pullToRefreshView.beginRefreshing()
} else {
pullToRefreshView.endRefreshing()
}
result(true)
} else {
result(false)
}
break
case "setColor":
if let pullToRefreshView = pullToRefreshControl {
let color = arguments!["color"] as! String
pullToRefreshView.tintColor = UIColor(hexString: color)
result(true)
} else {
result(false)
}
break
case "setBackgroundColor":
if let pullToRefreshView = pullToRefreshControl {
let color = arguments!["color"] as! String
pullToRefreshView.backgroundColor = UIColor(hexString: color)
result(true)
} else {
result(false)
}
break
case "setStyledTitle":
if let pullToRefreshView = pullToRefreshControl {
let attributedTitleMap = arguments!["attributedTitle"] as! [String: Any?]
pullToRefreshView.attributedTitle = NSAttributedString.fromMap(map: attributedTitleMap)
result(true)
} else {
result(false)
}
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public func onRefresh() {
let arguments: [String: Any?] = [:]
channel?.invokeMethod("onRefresh", arguments: arguments)
}
public override func dispose() {
super.dispose()
pullToRefreshControl = nil
}
}

View File

@ -8,29 +8,26 @@
import Foundation
import Flutter
public class PullToRefreshControl : UIRefreshControl, FlutterPlugin {
var channel: FlutterMethodChannel?
public class PullToRefreshControl : UIRefreshControl, Disposable {
static var METHOD_CHANNEL_NAME_PREFIX = "com.pichillilorenzo/flutter_inappwebview_pull_to_refresh_";
var channelDelegate: PullToRefreshChannelDelegate?
var settings: PullToRefreshSettings?
var shouldCallOnRefresh = false
var delegate: PullToRefreshDelegate?
public init(channel: FlutterMethodChannel?, settings: PullToRefreshSettings?) {
public init(registrar: FlutterPluginRegistrar, id: Any, settings: PullToRefreshSettings?) {
super.init()
self.channel = channel
self.settings = settings
let channel = FlutterMethodChannel(name: PullToRefreshControl.METHOD_CHANNEL_NAME_PREFIX + String(describing: id),
binaryMessenger: registrar.messenger())
self.channelDelegate = PullToRefreshChannelDelegate(pullToRefreshControl: self, channel: channel)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
public static func register(with registrar: FlutterPluginRegistrar) {
}
public func prepare() {
self.channel?.setMethodCallHandler(self.handle)
if let options = settings {
if options.enabled {
delegate?.enablePullToRefresh()
@ -48,53 +45,9 @@ public class PullToRefreshControl : UIRefreshControl, FlutterPlugin {
addTarget(self, action: #selector(updateShouldCallOnRefresh), for: .valueChanged)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "setEnabled":
let enabled = arguments!["enabled"] as! Bool
if enabled {
delegate?.enablePullToRefresh()
} else {
delegate?.disablePullToRefresh()
}
result(true)
break
case "setRefreshing":
let refreshing = arguments!["refreshing"] as! Bool
if refreshing {
self.beginRefreshing()
} else {
self.endRefreshing()
}
result(true)
break
case "setColor":
let color = arguments!["color"] as! String
tintColor = UIColor(hexString: color)
result(true)
break
case "setBackgroundColor":
let color = arguments!["color"] as! String
backgroundColor = UIColor(hexString: color)
result(true)
break
case "setStyledTitle":
let attributedTitleMap = arguments!["attributedTitle"] as! [String: Any?]
attributedTitle = NSAttributedString.fromMap(map: attributedTitleMap)
result(true)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
public func onRefresh() {
shouldCallOnRefresh = false
let arguments: [String: Any?] = [:]
self.channel?.invokeMethod("onRefresh", arguments: arguments)
channelDelegate?.onRefresh()
}
@objc public func updateShouldCallOnRefresh() {
@ -102,7 +55,8 @@ public class PullToRefreshControl : UIRefreshControl, FlutterPlugin {
}
public func dispose() {
channel?.setMethodCallHandler(nil)
channelDelegate?.dispose()
channelDelegate = nil
removeTarget(self, action: #selector(updateShouldCallOnRefresh), for: .valueChanged)
delegate = nil
}

View File

@ -12,22 +12,16 @@ import Foundation
import AVFoundation
import SafariServices
public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
public class ChromeSafariBrowserManager: ChannelDelegate {
static let METHOD_CHANNEL_NAME = "com.pichillilorenzo/flutter_chromesafaribrowser"
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
public static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
super.init(channel: FlutterMethodChannel(name: ChromeSafariBrowserManager.METHOD_CHANNEL_NAME, binaryMessenger: registrar.messenger()))
ChromeSafariBrowserManager.registrar = registrar
ChromeSafariBrowserManager.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_chromesafaribrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: ChromeSafariBrowserManager.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
@ -92,9 +86,8 @@ public class ChromeSafariBrowserManager: NSObject, FlutterPlugin {
result(FlutterError.init(code: "ChromeSafariBrowserManager", message: "SafariViewController is not available!", details: nil))
}
public func dispose() {
ChromeSafariBrowserManager.channel?.setMethodCallHandler(nil)
ChromeSafariBrowserManager.channel = nil
public override func dispose() {
super.dispose()
ChromeSafariBrowserManager.registrar = nil
}
}

View File

@ -42,7 +42,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
super.init()
self.registrar = registrar
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: "com.pichillilorenzo/flutter_inappwebview")
registrar.register(FlutterWebViewFactory(registrar: registrar) as FlutterPlatformViewFactory, withId: FlutterWebViewFactory.VIEW_TYPE_ID)
platformUtil = PlatformUtil(registrar: registrar)
inAppBrowserManager = InAppBrowserManager(registrar: registrar)

View File

@ -0,0 +1,27 @@
//
// ChannelDelegate.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 04/05/22.
//
import Foundation
public class ChannelDelegate : FlutterMethodCallDelegate, Disposable {
var channel: FlutterMethodChannel?
public init(channel: FlutterMethodChannel) {
super.init()
self.channel = channel
self.channel?.setMethodCallHandler(handle)
}
public override func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
}
public func dispose() {
channel?.setMethodCallHandler(nil)
channel = nil
}
}

View File

@ -0,0 +1,12 @@
//
// Disposable.swift
// flutter_inappwebview
//
// Created by Lorenzo Pichilli on 04/05/22.
//
import Foundation
public protocol Disposable {
func dispose() -> Void
}

View File

@ -9,8 +9,11 @@ import Foundation
extension URLRequest {
public init(fromPluginMap: [String:Any?]) {
let url = fromPluginMap["url"] as! String
self.init(url: URL(string: url)!)
if let urlString = fromPluginMap["url"] as? String, let url = URL(string: urlString) {
self.init(url: url)
} else {
self.init(url: URL(string: "about:blank")!)
}
if let method = fromPluginMap["method"] as? String {
httpMethod = method

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment version="2048" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>

View File

@ -4,7 +4,7 @@ import 'url_request_network_service_type.dart';
///A URL load request that is independent of protocol or URL scheme.
class URLRequest {
///The URL of the request.
///The URL of the request. Setting this to `null` will load `about:blank`.
Uri? url;
///The HTTP request method.