Commit 68ff79c7 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

added HttpAuthCredentialDatabase class, clearCache method, onReceivedHttpAuthRequest event

parent fed99ec0
This diff is collapsed.
......@@ -20,13 +20,16 @@
- Added `startSafeBrowsing`, `setSafeBrowsingWhitelist` and `getSafeBrowsingPrivacyPolicyUrl` methods (available only for Android)
- Added `onSafeBrowsingHit` event (available only for Android)
- Added `onJsAlert`, `onJsConfirm` and `onJsPrompt` events to manage javascript popup dialogs
- Fixed `InputConnection` error on Android
- Added `onReceivedHttpAuthRequest` event
- Added `clearCache()` method
- Added `HttpAuthCredentialDatabase` class
### BREAKING CHANGES
- Deleted `WebResourceRequest` class
- Updated `WebResourceResponse` class
- Updated `ConsoleMessageLevel` class
- Updated `onLoadResource` event
- Updated `CookieManager` class
- WebView options are now available with the new corresponding classes: `InAppWebViewOptions`, `AndroidInAppWebViewOptions`, `iOSInAppWebViewOptions`, `InAppBrowserOptions`, `AndroidInAppBrowserOptions`, `iOSInAppBrowserOptions`, `AndroidChromeCustomTabsOptions` and `iOSChromeCustomTabsOptions`
## 1.2.1
......
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import java.util.HashMap;
import java.util.Map;
public class Credential {
public Long id;
public String username;
public String password;
public Long protectionSpaceId;
public Credential (Long id, String username, String password, Long protectionSpaceId) {
this.id = id;
this.username = username;
this.password = password;
this.protectionSpaceId = protectionSpaceId;
}
public Map<String, Object> toMap() {
Map<String, Object> credentialMap = new HashMap<>();
credentialMap.put("username", username);
credentialMap.put("password", password);
return credentialMap;
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.provider.BaseColumns;
public class CredentialContract {
private CredentialContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "credential";
public static final String COLUMN_NAME_USERNAME = "username";
public static final String COLUMN_NAME_PASSWORD = "password";
public static final String COLUMN_NAME_PROTECTION_SPACE_ID = "protection_space_id";
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.ContentValues;
import android.database.Cursor;
import java.util.ArrayList;
import java.util.List;
public class CredentialDao {
CredentialDatabaseHelper credentialDatabaseHelper;
String[] projection = {
CredentialContract.FeedEntry._ID,
CredentialContract.FeedEntry.COLUMN_NAME_USERNAME,
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD,
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID
};
public CredentialDao(CredentialDatabaseHelper credentialDatabaseHelper) {
this.credentialDatabaseHelper = credentialDatabaseHelper;
}
public List<Credential> getAllByProtectionSpaceId(Long protectionSpaceId) {
String selection = CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] selectionArgs = {protectionSpaceId.toString()};
Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query(
CredentialContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
List<Credential> credentials = new ArrayList<>();
while (cursor.moveToNext()) {
Long id = cursor.getLong(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry._ID));
String username = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME));
String password = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD));
credentials.add(new Credential(id, username, password, protectionSpaceId));
}
cursor.close();
return credentials;
}
public Credential find(String username, String password, Long protectionSpaceId) {
String selection = CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + " = ? AND " +
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + " = ? AND " +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] selectionArgs = {username, password, protectionSpaceId.toString()};
Cursor cursor = credentialDatabaseHelper.getReadableDatabase().query(
CredentialContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
Credential credential = null;
if (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry._ID));
String rowUsername = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME));
String rowPassword = cursor.getString(cursor.getColumnIndexOrThrow(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD));
credential = new Credential(rowId, rowUsername, rowPassword, protectionSpaceId);
}
cursor.close();
return credential;
}
public long insert(Credential credential) {
ContentValues credentialValues = new ContentValues();
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME, credential.username);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, credential.password);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID, credential.protectionSpaceId);
return credentialDatabaseHelper.getWritableDatabase().insert(CredentialContract.FeedEntry.TABLE_NAME, null, credentialValues);
}
public long update(Credential credential) {
ContentValues credentialValues = new ContentValues();
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_USERNAME, credential.username);
credentialValues.put(CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD, credential.password);
String whereClause = CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " = ?";
String[] whereArgs = {credential.protectionSpaceId.toString()};
return credentialDatabaseHelper.getWritableDatabase().update(CredentialContract.FeedEntry.TABLE_NAME, credentialValues, whereClause, whereArgs);
}
public long delete(Credential credential) {
String whereClause = CredentialContract.FeedEntry._ID + " = ?";
String[] whereArgs = {credential.id.toString()};
return credentialDatabaseHelper.getWritableDatabase().delete(CredentialContract.FeedEntry.TABLE_NAME, whereClause, whereArgs);
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.Context;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class CredentialDatabase {
private static CredentialDatabase instance;
static final String LOG_TAG = "CredentialDatabase";
// If you change the database schema, you must increment the database version.
public static final int DATABASE_VERSION = 2;
public static final String DATABASE_NAME = "CredentialDatabase.db";
public ProtectionSpaceDao protectionSpaceDao;
public CredentialDao credentialDao;
public CredentialDatabaseHelper db;
private CredentialDatabase() {}
private CredentialDatabase(CredentialDatabaseHelper db, ProtectionSpaceDao protectionSpaceDao, CredentialDao credentialDao) {
this.db = db;
this.protectionSpaceDao = protectionSpaceDao;
this.credentialDao = credentialDao;
}
public static CredentialDatabase getInstance(Context context) {
if (instance != null)
return instance;
CredentialDatabaseHelper db = new CredentialDatabaseHelper(context);
instance = new CredentialDatabase(db, new ProtectionSpaceDao(db), new CredentialDao(db));
return instance;
}
public List<Credential> getHttpAuthCredentials(String host, String protocol, String realm, Integer port) {
List<Credential> credentialList = new ArrayList<>();
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
credentialList = credentialDao.getAllByProtectionSpaceId(protectionSpace.id);
}
return credentialList;
}
public void clearAllAuthCredentials() {
db.clearAllTables(db.getWritableDatabase());
}
public void removeHttpAuthCredentials(String host, String protocol, String realm, Integer port) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
protectionSpaceDao.delete(protectionSpace);
}
}
public void removeHttpAuthCredential(String host, String protocol, String realm, Integer port, String username, String password) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
if (protectionSpace != null) {
credentialDao.find(username, password, protectionSpace.id);
}
}
public void setHttpAuthCredential(String host, String protocol, String realm, Integer port, String username, String password) {
ProtectionSpace protectionSpace = protectionSpaceDao.find(host, protocol, realm, port);
Long protectionSpaceId;
if (protectionSpace == null) {
protectionSpaceId = protectionSpaceDao.insert(new ProtectionSpace(null, host, protocol, realm, port));
} else {
protectionSpaceId = protectionSpace.id;
}
Credential credential = credentialDao.find(username, password, protectionSpaceId);
if (credential != null) {
boolean needUpdate = false;
if (!credential.username.equals(username)) {
credential.username = username;
needUpdate = true;
}
if (!credential.password.equals(password)) {
credential.password = password;
needUpdate = true;
}
if (needUpdate)
credentialDao.update(credential);
} else {
credential = new Credential(null, username, password, protectionSpaceId);
credential.id = credentialDao.insert(credential);
}
}
}
\ No newline at end of file
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class CredentialDatabaseHelper extends SQLiteOpenHelper {
private static final String SQL_CREATE_PROTECTION_SPACE_TABLE =
"CREATE TABLE " + ProtectionSpaceContract.FeedEntry.TABLE_NAME + " (" +
ProtectionSpaceContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + " TEXT NOT NULL," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + " TEXT," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + " TEXT," +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT + " INTEGER," +
"UNIQUE(" + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + ", " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + ", " +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + ", " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT +
")" +
");";
private static final String SQL_CREATE_CREDENTIAL_TABLE =
"CREATE TABLE " + CredentialContract.FeedEntry.TABLE_NAME + " (" +
CredentialContract.FeedEntry._ID + " INTEGER PRIMARY KEY," +
CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + " TEXT NOT NULL," +
CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + " TEXT NOT NULL," +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + " INTEGER NOT NULL," +
"UNIQUE(" + CredentialContract.FeedEntry.COLUMN_NAME_USERNAME + ", " + CredentialContract.FeedEntry.COLUMN_NAME_PASSWORD + ", " +
CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID +
")," +
"FOREIGN KEY (" + CredentialContract.FeedEntry.COLUMN_NAME_PROTECTION_SPACE_ID + ") REFERENCES " +
ProtectionSpaceContract.FeedEntry.TABLE_NAME + " (" + ProtectionSpaceContract.FeedEntry._ID + ") ON DELETE CASCADE" +
");";
private static final String SQL_DELETE_PROTECTION_SPACE_TABLE =
"DROP TABLE IF EXISTS " + ProtectionSpaceContract.FeedEntry.TABLE_NAME;
private static final String SQL_DELETE_CREDENTIAL_TABLE =
"DROP TABLE IF EXISTS " + CredentialContract.FeedEntry.TABLE_NAME;
public CredentialDatabaseHelper(Context context) {
super(context, CredentialDatabase.DATABASE_NAME, null, CredentialDatabase.DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_CREATE_CREDENTIAL_TABLE);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// This database is only a cache for online data, so its upgrade policy is
// to simply to discard the data and start over
db.execSQL(SQL_DELETE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_DELETE_CREDENTIAL_TABLE);
onCreate(db);
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
public void clearAllTables(SQLiteDatabase db) {
db.execSQL(SQL_DELETE_PROTECTION_SPACE_TABLE);
db.execSQL(SQL_DELETE_CREDENTIAL_TABLE);
onCreate(db);
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import java.util.HashMap;
import java.util.Map;
public class ProtectionSpace {
public Long id;
public String host;
public String procotol;
public String realm;
public Integer port;
public ProtectionSpace (Long id, String host, String protocol, String realm, Integer port) {
this.id = id;
this.host = host;
this.procotol = protocol;
this.realm = realm;
this.port = port;
}
public Map<String, Object> toMap() {
Map<String, Object> protectionSpaceMap = new HashMap<>();
protectionSpaceMap.put("host", host);
protectionSpaceMap.put("protocol", procotol);
protectionSpaceMap.put("realm", realm);
protectionSpaceMap.put("port", port);
return protectionSpaceMap;
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.provider.BaseColumns;
public class ProtectionSpaceContract {
private ProtectionSpaceContract() {}
/* Inner class that defines the table contents */
public static class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "protection_space";
public static final String COLUMN_NAME_HOST = "host";
public static final String COLUMN_NAME_PROTOCOL = "protocol";
public static final String COLUMN_NAME_REALM = "realm";
public static final String COLUMN_NAME_PORT = "port";
}
}
package com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;
public class ProtectionSpaceDao {
CredentialDatabaseHelper credentialDatabaseHelper;
String[] projection = {
ProtectionSpaceContract.FeedEntry._ID,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM,
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT
};
public ProtectionSpaceDao(CredentialDatabaseHelper credentialDatabaseHelper) {
this.credentialDatabaseHelper = credentialDatabaseHelper;
}
public List<ProtectionSpace> getAll() {
SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase();
Cursor cursor = readableDatabase.query(
ProtectionSpaceContract.FeedEntry.TABLE_NAME,
projection,
null,
null,
null,
null,
null
);
List<ProtectionSpace> protectionSpaces = new ArrayList<>();
while (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry._ID));
String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST));
String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL));
String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM));
Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT));
protectionSpaces.add(new ProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort));
}
cursor.close();
return protectionSpaces;
}
public ProtectionSpace find(String host, String protocol, String realm, Integer port) {
SQLiteDatabase readableDatabase = credentialDatabaseHelper.getReadableDatabase();
String selection = ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST + " = ? AND " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL + " = ? AND " +
ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM + " = ? AND " + ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT + " = ?";
String[] selectionArgs = {host, protocol, realm, port.toString()};
Cursor cursor = readableDatabase.query(
ProtectionSpaceContract.FeedEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
ProtectionSpace protectionSpace = null;
if (cursor.moveToNext()) {
Long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry._ID));
String rowHost = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST));
String rowProtocol = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL));
String rowRealm = cursor.getString(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM));
Integer rowPort = cursor.getInt(cursor.getColumnIndexOrThrow(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT));
protectionSpace = new ProtectionSpace(rowId, rowHost, rowProtocol, rowRealm, rowPort);
}
cursor.close();
return protectionSpace;
}
public long insert(ProtectionSpace protectionSpace) {
ContentValues protectionSpaceValues = new ContentValues();
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_HOST, protectionSpace.host);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PROTOCOL, protectionSpace.procotol);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_REALM, protectionSpace.realm);
protectionSpaceValues.put(ProtectionSpaceContract.FeedEntry.COLUMN_NAME_PORT, protectionSpace.port);
return credentialDatabaseHelper.getWritableDatabase().insert(ProtectionSpaceContract.FeedEntry.TABLE_NAME, null, protectionSpaceValues);
};
public long delete(ProtectionSpace protectionSpace) {
String whereClause = ProtectionSpaceContract.FeedEntry._ID + " = ?";
String[] whereArgs = {protectionSpace.id.toString()};
return credentialDatabaseHelper.getWritableDatabase().delete(ProtectionSpaceContract.FeedEntry.TABLE_NAME, whereClause, whereArgs);
}
}
\ No newline at end of file
package com.pichillilorenzo.flutter_inappbrowser;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.Credential;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.CredentialDatabase;
import com.pichillilorenzo.flutter_inappbrowser.CredentialDatabase.ProtectionSpace;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
@RequiresApi(api = Build.VERSION_CODES.O)
public class CredentialDatabaseHandler implements MethodChannel.MethodCallHandler {
static final String LOG_TAG = "CredentialDatabaseHandler";
public static PluginRegistry.Registrar registrar;
public static MethodChannel channel;
public static CredentialDatabase credentialDatabase;
public CredentialDatabaseHandler(PluginRegistry.Registrar r) {
registrar = r;
channel = new MethodChannel(registrar.messenger(), "com.pichillilorenzo/flutter_inappbrowser_credential_database");
channel.setMethodCallHandler(this);
credentialDatabase = CredentialDatabase.getInstance(registrar.context());
}
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
switch (call.method) {
case "getAllAuthCredentials":
{
List<Map<String, Object>> allCredentials = new ArrayList<>();
List<ProtectionSpace> protectionSpaces = credentialDatabase.protectionSpaceDao.getAll();
for (ProtectionSpace protectionSpace : protectionSpaces) {
List<Map<String, Object>> credentials = new ArrayList<>();
for (Credential credential : credentialDatabase.credentialDao.getAllByProtectionSpaceId(protectionSpace.id)) {
credentials.add(credential.toMap());
}
Map<String, Object> obj = new HashMap<>();
obj.put("protectionSpace", protectionSpace.toMap());
obj.put("credentials", credentials);
allCredentials.add(obj);
}
result.success(allCredentials);
}
break;
case "getHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
List<Map<String, Object>> credentials = new ArrayList<>();
for (Credential credential : credentialDatabase.getHttpAuthCredentials(host, protocol, realm, port)) {
credentials.add(credential.toMap());
}
result.success(credentials);
}
break;
case "setHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.setHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
}
break;
case "removeHttpAuthCredential":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
String username = (String) call.argument("username");
String password = (String) call.argument("password");
credentialDatabase.removeHttpAuthCredential(host, protocol, realm, port, username, password);
result.success(true);
}
break;
case "removeHttpAuthCredentials":
{
String host = (String) call.argument("host");
String protocol = (String) call.argument("protocol");
String realm = (String) call.argument("realm");
Integer port = (Integer) call.argument("port");
credentialDatabase.removeHttpAuthCredentials(host, protocol, realm, port);
result.success(true);
}
break;
case "clearAllAuthCredentials":
credentialDatabase.clearAllAuthCredentials();
result.success(true);
break;
default:
result.notImplemented();
}
}
}
......@@ -245,6 +245,11 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
} else
result.success(null);
break;
case "clearCache":
if (webView != null)
webView.clearAllCache();
result.success(true);
break;
case "dispose":
dispose();
result.success(true);
......
......@@ -474,4 +474,9 @@ public class InAppBrowserActivity extends AppCompatActivity {
else
result.success(false);
}
public void clearCache() {
if (webView != null)
webView.clearAllCache();
}
}
......@@ -22,10 +22,10 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Parcelable;
import android.provider.Browser;
import android.net.Uri;
......@@ -45,7 +45,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
......@@ -82,6 +81,9 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
instance = new InAppBrowserFlutterPlugin(registrar);
new MyCookieManager(registrar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
new CredentialDatabaseHandler(registrar);
}
registrar
.platformViewRegistry()
......@@ -305,6 +307,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
case "setSafeBrowsingWhitelist":
setSafeBrowsingWhitelist(uuid, (List<String>) call.argument("hosts"), result);
break;
case "clearCache":
clearCache(uuid);
result.success(true);
break;
default:
result.notImplemented();
}
......@@ -687,4 +693,10 @@ public class InAppBrowserFlutterPlugin implements MethodCallHandler {
inAppBrowserActivity.setSafeBrowsingWhitelist(hosts, result);
result.success(false);
}
public void clearCache(String uuid) {
InAppBrowserActivity inAppBrowserActivity = webViewActivities.get(uuid);
if (inAppBrowserActivity != null)
inAppBrowserActivity.clearCache();
}
}
package com.pichillilorenzo.flutter_inappbrowser.InAppWebView;
import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
......@@ -9,9 +7,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.webkit.ConsoleMessage;
......@@ -31,8 +26,6 @@ import com.pichillilorenzo.flutter_inappbrowser.FlutterWebView;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.R;
import com.pichillilorenzo.flutter_inappbrowser.RequestPermissionHandler;
import com.pichillilorenzo.flutter_inappbrowser.Util;
import java.util.HashMap;
import java.util.Map;
......
......@@ -19,6 +19,8 @@ public class Util {
static final String LOG_TAG = "Util";
public static final String ANDROID_ASSET_URL = "file:///android_asset/";
private Util() {}
public static String getUrlAsset(PluginRegistry.Registrar registrar, String assetFilePath) throws IOException {
String key = registrar.lookupKeyForAsset(assetFilePath);
AssetManager mg = registrar.activeContext().getResources().getAssets();
......
......@@ -40,7 +40,7 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> {
onPressed: () async {
await widget.browser.open("https://flutter.dev/", options: [
AndroidChromeCustomTabsOptions(addShareButton: false),
iOSChromeCustomTabsOptions(barCollapsingEnabled: true)
iOSSafariOptions(barCollapsingEnabled: true)
]);
},
child: Text("Open Chrome Safari Browser")),
......
......@@ -46,6 +46,24 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
@override
Widget build(BuildContext context) {
// HttpAuthCredentialDatabase.instance().clearAllAuthCredentials();
//
// HttpAuthCredentialDatabase.instance().getHttpAuthCredentials(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081)).then((credentials) {
// for (var credential in credentials )
// print("\n\nCREDENTIAL: ${credential.username} ${credential.password}\n\n");
// });
// HttpAuthCredentialDatabase.instance().getAllAuthCredentials().then((result) {
// for (var r in result) {
// ProtectionSpace protectionSpace = r["protectionSpace"];
// print("\n\nProtectionSpace: ${protectionSpace.protocol} ${protectionSpace.host}:");
// List<HttpAuthCredential> credentials = r["credentials"];
// for (var credential in credentials)
// print("\tCREDENTIAL: ${credential.username} ${credential.password}");
// }
// });
// HttpAuthCredentialDatabase.instance().setHttpAuthCredential(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081), HttpAuthCredential(username: "user 1", password: "password 1"));
// HttpAuthCredentialDatabase.instance().setHttpAuthCredential(ProtectionSpace(host: "192.168.1.20", protocol: "http", realm: "Node", port: 8081), HttpAuthCredential(username: "user 2", password: "password 2"));
return Container(
child: Column(children: <Widget>[
Container(
......@@ -66,11 +84,13 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
//initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1",
//initialUrl: "https://flutter.dev/",
//initialUrl: "chrome://safe-browsing/match?type=malware",
//initialUrl: "http://192.168.1.20:8081/",
//initialUrl: "https://192.168.1.20:4433/authenticate",
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: [
InAppWebViewOptions(
clearCache: true,
//clearCache: true,
useShouldOverrideUrlLoading: true,
useOnTargetBlank: true,
//useOnLoadResource: true,
......@@ -152,12 +172,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
""");
},
onDownloadStart: (InAppWebViewController controller, String url) async {
/*final taskId = await FlutterDownloader.enqueue(
url: url,
savedDir: await _findLocalPath(),
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);*/
// final taskId = await FlutterDownloader.enqueue(
// url: url,
// savedDir: await _findLocalPath(),
// showNotification: true, // show download progress in status bar (for Android)
// openFileFromNotification: true, // click on notification to open downloaded file (for Android)
// );
},
onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async {
if (scheme == "my-special-custom-scheme") {
......@@ -220,6 +240,12 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
SafeBrowsingResponseAction action = SafeBrowsingResponseAction.BACK_TO_SAFETY;
return new SafeBrowsingResponse(report: true, action: action);
},
onReceivedHttpAuthRequest: (InAppWebViewController controller, HttpAuthChallenge challenge) async {
print("HTTP AUTH REQUEST: " + challenge.protectionSpace.host + ", realm: " + challenge.protectionSpace.realm +
", previous failure count: " + challenge.previousFailureCount.toString());
return new HttpAuthResponse(username: "USERNAME", password: "PASSWORD", action: HttpAuthResponseAction.USE_SAVED_HTTP_AUTH_CREDENTIALS, permanentPersistence: true);
},
),
),
),
......
//
// CredentialDatabase.swift
// flutter_inappbrowser
//
// Created by Lorenzo Pichilli on 29/10/2019.
//
import Foundation
class CredentialDatabase: NSObject, FlutterPlugin {
static var registrar: FlutterPluginRegistrar?
static var channel: FlutterMethodChannel?
static var credentialStore: URLCredentialStorage?
static func register(with registrar: FlutterPluginRegistrar) {
}
init(registrar: FlutterPluginRegistrar) {
super.init()
CredentialDatabase.registrar = registrar
CredentialDatabase.credentialStore = URLCredentialStorage.shared
CredentialDatabase.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser_credential_database", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: CredentialDatabase.channel!)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
let arguments = call.arguments as? NSDictionary
switch call.method {
case "getAllAuthCredentials":
var allCredentials: [[String: Any?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
let protectionSpaceDict = [
"host": protectionSpace.host,
"protocol": protectionSpace.protocol,
"realm": protectionSpace.realm,
"port": protectionSpace.port
] as [String : Any?]
var crendentials: [[String: String?]] = []
for c in credentials {
let credential: [String: String?] = [
"username": c.value.user,
"password": c.value.password,
]
crendentials.append(credential)
}
let dict = [
"protectionSpace": protectionSpaceDict,
"credentials": crendentials
] as [String : Any]
allCredentials.append(dict)
}
result(allCredentials)
break
case "getHttpAuthCredentials":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
var crendentials: [[String: String?]] = []
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
let credential: [String: String?] = [
"username": c.value.user,
"password": c.value.password,
]
crendentials.append(credential)
}
break
}
}
result(crendentials)
break
case "setHttpAuthCredential":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
let username = arguments!["username"] as! String
let password = arguments!["password"] as! String
let credential = URLCredential(user: username, password: password, persistence: .permanent)
CredentialDatabase.credentialStore!.set(credential, for: URLProtectionSpace(host: host, port: urlPort, protocol: urlProtocol, realm: realm, authenticationMethod: NSURLAuthenticationMethodHTTPBasic))
result(true)
break
case "removeHttpAuthCredential":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
let username = arguments!["username"] as! String
let password = arguments!["password"] as! String
var credential: URLCredential? = nil;
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
for c in credentials {
if c.value.user == username, c.value.password == password {
credential = c.value
protectionSpaceCredential = protectionSpace
break
}
}
}
if credential != nil {
break
}
}
if let c = credential, let protectionSpace = protectionSpaceCredential {
CredentialDatabase.credentialStore!.remove(c, for: protectionSpace)
}
result(true)
break
case "removeHttpAuthCredentials":
let host = arguments!["host"] as! String
let urlProtocol = arguments!["protocol"] as? String
let urlPort = arguments!["port"] as? Int ?? 0
var realm = arguments!["realm"] as? String;
if let r = realm, r.isEmpty {
realm = nil
}
var credentialsToRemove: [URLCredential] = [];
var protectionSpaceCredential: URLProtectionSpace? = nil
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
if protectionSpace.host == host && protectionSpace.realm == realm &&
protectionSpace.protocol == urlProtocol && protectionSpace.port == urlPort {
protectionSpaceCredential = protectionSpace
for c in credentials {
credentialsToRemove.append(c.value)
}
}
}
if let protectionSpace = protectionSpaceCredential {
for credential in credentialsToRemove {
CredentialDatabase.credentialStore!.remove(credential, for: protectionSpace)
}
}
result(true)
break
case "clearAllAuthCredentials":
for (protectionSpace, credentials) in CredentialDatabase.credentialStore!.allCredentials {
for credential in credentials {
CredentialDatabase.credentialStore!.remove(credential.value, for: protectionSpace)
}
}
result(true)
break
default:
result(FlutterMethodNotImplemented)
break
}
}
}
......@@ -259,6 +259,12 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
case "getCopyBackForwardList":
result((webView != nil) ? webView!.getCopyBackForwardList() : nil)
break
case "clearCache":
if webView != nil {
webView!.clearCache()
}
result(true)
break
case "dispose":
dispose()
result(true)
......
This diff is collapsed.
......@@ -52,17 +52,17 @@ class MyCookieManager: NSObject, FlutterPlugin {
let name = arguments!["name"] as! String
let domain = arguments!["domain"] as! String
let path = arguments!["path"] as! String
MyCookieManager.deleteCookie(url: url, name: name, domain: domain, path: path, result: result);
MyCookieManager.deleteCookie(url: url, name: name, domain: domain, path: path, result: result)
break;
case "deleteCookies":
let url = arguments!["url"] as! String
let domain = arguments!["domain"] as! String
let path = arguments!["path"] as! String
MyCookieManager.deleteCookies(url: url, domain: domain, path: path, result: result);
MyCookieManager.deleteCookies(url: url, domain: domain, path: path, result: result)
break;
case "deleteAllCookies":
MyCookieManager.deleteAllCookies(result: result);
break;
MyCookieManager.deleteAllCookies(result: result)
break
default:
result(FlutterMethodNotImplemented)
break
......
......@@ -61,6 +61,8 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
} else {
// Fallback on earlier versions
}
CredentialDatabase(registrar: registrar)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
......@@ -237,6 +239,10 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
case "getCopyBackForwardList":
result(self.getCopyBackForwardList(uuid: uuid))
break
case "clearCache":
self.clearCache(uuid: uuid)
result(true)
break
default:
result(FlutterMethodNotImplemented)
break
......@@ -746,6 +752,12 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
return nil
}
func clearCache(uuid: String) {
if let webViewController = self.webViewControllers[uuid] {
webViewController!.webView.clearCache()
}
}
}
// Helper function inserted by Swift 4.2 migrator.
......
......@@ -30,3 +30,4 @@ export 'src/chrome_safari_browser.dart';
export 'src/in_app_localhost_server.dart';
export 'src/webview_options.dart';
export 'src/content_blocker.dart';
export 'src/http_auth_credentials_database.dart';
......@@ -70,7 +70,7 @@ class ChromeSafariBrowser {
///- __preferredControlTintColor__: Set the custom color of the control buttons on the navigation bar and the toolbar.
///- __presentationStyle__: Set the custom modal presentation style when presenting the WebView. The default value is `0 //fullscreen`. See [UIModalPresentationStyle](https://developer.apple.com/documentation/uikit/uimodalpresentationstyle) for all the available styles.
///- __transitionStyle__: Set to the custom transition style when presenting the WebView. The default value is `0 //crossDissolve`. See [UIModalTransitionStyle](https://developer.apple.com/documentation/uikit/uimodaltransitionStyle) for all the available styles.
Future<void> open(String url, {List<ChromeCustomTabsOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async {
Future<void> open(String url, {List<ChromeSafariBrowserOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async {
assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
......
......@@ -4,32 +4,34 @@ import 'package:flutter/services.dart';
///
///**NOTE for iOS**: available from iOS 11.0+.
class CookieManager {
static bool _initialized = false;
static CookieManager _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_cookiemanager');
static void _init () {
_channel.setMethodCallHandler(handleMethod);
_initialized = true;
static CookieManager instance() {
return (_instance != null) ? _instance : _init();
}
static Future<dynamic> handleMethod(MethodCall call) async {
static CookieManager _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = new CookieManager();
return _instance;
}
static Future<dynamic> _handleMethod(MethodCall call) async {
}
///Sets a cookie for the given [url]. Any existing cookie with the same [host], [path] and [name] will be replaced with the new cookie. The cookie being set will be ignored if it is expired.
///
///The default value of [path] is `"/"`.
///If [domain] is `null`, its default value will be the domain name of [url].
static Future<void> setCookie(String url, String name, String value,
Future<void> setCookie(String url, String name, String value,
{ String domain,
String path = "/",
int expiresDate,
int maxAge,
bool isSecure }) async {
if (!_initialized)
_init();
if (domain == null)
domain = getDomainName(url);
domain = _getDomainName(url);
assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty);
......@@ -51,10 +53,7 @@ class CookieManager {
}
///Gets all the cookies for the given [url].
static Future<List<Map<String, dynamic>>> getCookies(String url) async {
if (!_initialized)
_init();
Future<List<Map<String, dynamic>>> getCookies(String url) async {
assert(url != null && url.isNotEmpty);
Map<String, dynamic> args = <String, dynamic>{};
......@@ -69,10 +68,7 @@ class CookieManager {
}
///Gets a cookie by its [name] for the given [url].
static Future<Map<String, dynamic>> getCookie(String url, String name) async {
if (!_initialized)
_init();
Future<Map<String, dynamic>> getCookie(String url, String name) async {
assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty);
......@@ -92,12 +88,9 @@ class CookieManager {
///
///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url].
static Future<void> deleteCookie(String url, String name, {String domain = "", String path = "/"}) async {
if (!_initialized)
_init();
Future<void> deleteCookie(String url, String name, {String domain = "", String path = "/"}) async {
if (domain == null || domain.isEmpty)
domain = getDomainName(url);
domain = _getDomainName(url);
assert(url != null && url.isNotEmpty);
assert(name != null && name.isNotEmpty);
......@@ -116,12 +109,9 @@ class CookieManager {
///
///The default value of [path] is `"/"`.
///If [domain] is `null` or empty, its default value will be the domain name of [url].
static Future<void> deleteCookies(String url, {String domain = "", String path = "/"}) async {
if (!_initialized)
_init();
Future<void> deleteCookies(String url, {String domain = "", String path = "/"}) async {
if (domain == null || domain.isEmpty)
domain = getDomainName(url);
domain = _getDomainName(url);
assert(url != null && url.isNotEmpty);
assert(domain != null && url.isNotEmpty);
......@@ -135,15 +125,12 @@ class CookieManager {
}
///Removes all cookies.
static Future<void> deleteAllCookies() async {
if (!_initialized)
_init();
Future<void> deleteAllCookies() async {
Map<String, dynamic> args = <String, dynamic>{};
await _channel.invokeMethod('deleteAllCookies', args);
}
static String getDomainName(String url) {
String _getDomainName(String url) {
Uri uri = Uri.parse(url);
String domain = uri.host;
if (domain == null)
......
import 'types.dart';
import 'package:flutter/services.dart';
///
class HttpAuthCredentialDatabase {
static HttpAuthCredentialDatabase _instance;
static const MethodChannel _channel = const MethodChannel('com.pichillilorenzo/flutter_inappbrowser_credential_database');
///
static HttpAuthCredentialDatabase instance() {
return (_instance != null) ? _instance : _init();
}
static HttpAuthCredentialDatabase _init() {
_channel.setMethodCallHandler(_handleMethod);
_instance = new HttpAuthCredentialDatabase();
return _instance;
}
static Future<dynamic> _handleMethod(MethodCall call) async {
}
///
Future<List<Map<String, dynamic>>> getAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
List<dynamic> allCredentials = await _channel.invokeMethod('getAllAuthCredentials', args);
List<Map<String, dynamic>> result = [];
for (Map<dynamic, dynamic> map in allCredentials) {
Map<dynamic, dynamic> protectionSpace = map["protectionSpace"];
List<dynamic> credentials = map["credentials"];
result.add({
"protectionSpace": ProtectionSpace(host: protectionSpace["host"], protocol: protectionSpace["protocol"], realm: protectionSpace["realm"], port: protectionSpace["port"]),
"credentials": credentials.map((credential) => HttpAuthCredential(username: credential["username"], password: credential["password"])).toList()
});
}
return result;
}
///
Future<List<HttpAuthCredential>> getHttpAuthCredentials(ProtectionSpace protectionSpace) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
List<dynamic> credentialList = await _channel.invokeMethod('getHttpAuthCredentials', args);
List<HttpAuthCredential> credentials = [];
for (Map<dynamic, dynamic> credential in credentialList) {
credentials.add(HttpAuthCredential(username: credential["username"], password: credential["password"]));
}
return credentials;
}
///
Future<void> setHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
args.putIfAbsent("username", () => credential.username);
args.putIfAbsent("password", () => credential.password);
await _channel.invokeMethod('setHttpAuthCredential', args);
}
///
Future<void> removeHttpAuthCredential(ProtectionSpace protectionSpace, HttpAuthCredential credential) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
args.putIfAbsent("username", () => credential.username);
args.putIfAbsent("password", () => credential.password);
await _channel.invokeMethod('removeHttpAuthCredential', args);
}
///
Future<void> removeHttpAuthCredentials(ProtectionSpace protectionSpace) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("host", () => protectionSpace.host);
args.putIfAbsent("protocol", () => protectionSpace.protocol);
args.putIfAbsent("realm", () => protectionSpace.realm);
args.putIfAbsent("port", () => protectionSpace.port);
await _channel.invokeMethod('removeHttpAuthCredentials', args);
}
///
Future<void> clearAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
await _channel.invokeMethod('clearAllAuthCredentials', args);
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import 'dart:collection';
import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart';
import 'http_auth_credentials_database.dart';
import 'types.dart';
import 'channel_manager.dart';
import 'in_app_webview.dart' show InAppWebViewController;
......@@ -408,10 +409,8 @@ class InAppBrowser {
///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request.
///
///[host] represents the host requiring authentication.
///
///[realm] represents the realm for which authentication is required
Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, String realm) {
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
Future<HttpAuthResponse> onReceivedHttpAuthRequest(String url, HttpAuthChallenge challenge) {
}
......
......@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/gestures.dart';
import 'http_auth_credentials_database.dart';
import 'types.dart';
import 'in_app_browser.dart';
import 'channel_manager.dart';
......@@ -178,9 +179,7 @@ class InAppWebView extends StatefulWidget {
///Event fires when a WebView received an HTTP authentication request. The default behavior is to cancel the request.
///
///[host] represents the host requiring authentication.
///
///[realm] represents the realm for which authentication is required
///[challenge] contains data about host, port, protocol, realm, etc. as specified in the auth challenge.
final onReceivedHttpAuthRequestCallback onReceivedHttpAuthRequest;
///Initial url that will be loaded.
......@@ -251,7 +250,8 @@ class _InAppWebViewState extends State<InAppWebView> {
Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {};
widget.initialOptions.forEach((webViewOption) {
initialOptions.addAll(webViewOption.toMap());
if ((Platform.isAndroid && webViewOption is AndroidOptions) || (Platform.isIOS && webViewOption is iOSOptions))
initialOptions.addAll(webViewOption.toMap());
});
if (defaultTargetPlatform == TargetPlatform.android) {
......@@ -478,11 +478,16 @@ class InAppWebViewController {
break;
case "onReceivedHttpAuthRequest":
String host = call.arguments["host"];
String protocol = call.arguments["protocol"];
String realm = call.arguments["realm"];
int port = call.arguments["port"];
int previousFailureCount = call.arguments["previousFailureCount"];
var protectionSpace = ProtectionSpace(host: host, protocol: protocol, realm: realm, port: port);
var challenge = HttpAuthChallenge(previousFailureCount: previousFailureCount, protectionSpace: protectionSpace);
if (_widget != null && _widget.onReceivedHttpAuthRequest != null)
return (await _widget.onReceivedHttpAuthRequest(this, host, realm))?.toMap();
return (await _widget.onReceivedHttpAuthRequest(this, challenge))?.toMap();
else if (_inAppBrowser != null)
return (await _inAppBrowser.onReceivedHttpAuthRequest(host, realm))?.toMap();
return (await _inAppBrowser.onReceivedHttpAuthRequest(host, challenge))?.toMap();
break;
case "onCallJsHandler":
String handlerName = call.arguments["handlerName"];
......@@ -960,6 +965,16 @@ class InAppWebViewController {
return await _channel.invokeMethod('getSafeBrowsingPrivacyPolicyUrl', args);
}
///Clear all the webview's cache
Future<void> clearCache() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
await _channel.invokeMethod('clearCache', args);
}
///Dispose/Destroy the WebView.
Future<void> _dispose() async {
await _channel.invokeMethod('dispose');
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment