Commit b0224c74 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

Added onPermissionRequest event (available only on Android)

parent 992bf464
This diff is collapsed.
## 2.0.1
- Added `onPermissionRequest` event. This event is fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
## 2.0.0 ## 2.0.0
- Merge "Avoid null pointer exception after webview is disposed" [#116](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/116) (thanks to [robsonfingo](https://github.com/robsonfingo)) - Merge "Avoid null pointer exception after webview is disposed" [#116](https://github.com/pichillilorenzo/flutter_inappbrowser/pull/116) (thanks to [robsonfingo](https://github.com/robsonfingo))
......
...@@ -447,6 +447,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly: ...@@ -447,6 +447,7 @@ Instead, on the `onLoadStop` WebView event, you can use `callHandler` directly:
* `onAjaxProgress`: Event fired as an `XMLHttpRequest` progress. * `onAjaxProgress`: Event fired as an `XMLHttpRequest` progress.
* `shouldInterceptFetchRequest`: Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API). * `shouldInterceptFetchRequest`: Event fired when a request is sent to a server through [Fetch API](https://developer.mozilla.org/it/docs/Web/API/Fetch_API).
* `onNavigationStateChange`: Event fired when the navigation state of the InAppWebView changes. * `onNavigationStateChange`: Event fired when the navigation state of the InAppWebView changes.
* `onPermissionRequest`: Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied (available only on Android).
### `InAppBrowser` class ### `InAppBrowser` class
......
...@@ -16,6 +16,7 @@ import android.webkit.ConsoleMessage; ...@@ -16,6 +16,7 @@ import android.webkit.ConsoleMessage;
import android.webkit.GeolocationPermissions; import android.webkit.GeolocationPermissions;
import android.webkit.JsPromptResult; import android.webkit.JsPromptResult;
import android.webkit.JsResult; import android.webkit.JsResult;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebView; import android.webkit.WebView;
...@@ -31,7 +32,10 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity; ...@@ -31,7 +32,10 @@ import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserActivity;
import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin; import com.pichillilorenzo.flutter_inappbrowser.InAppBrowserFlutterPlugin;
import com.pichillilorenzo.flutter_inappbrowser.R; import com.pichillilorenzo.flutter_inappbrowser.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
...@@ -573,6 +577,53 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR ...@@ -573,6 +577,53 @@ public class InAppWebViewChromeClient extends WebChromeClient implements PluginR
return true; return true;
} }
@Override
public void onPermissionRequest(final PermissionRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Map<String, Object> obj = new HashMap<>();
if (inAppBrowserActivity != null)
obj.put("uuid", inAppBrowserActivity.uuid);
obj.put("origin", request.getOrigin().toString());
obj.put("resources", Arrays.asList(request.getResources()));
getChannel().invokeMethod("onPermissionRequest", obj, new MethodChannel.Result() {
@Override
public void success(Object response) {
if (response != null) {
Map<String, Object> responseMap = (Map<String, Object>) response;
Integer action = (Integer) responseMap.get("action");
List<String> resourceList = (List<String>) responseMap.get("resources");
if (resourceList == null)
resourceList = new ArrayList<String>();
String[] resources = new String[resourceList.size()];
resources = resourceList.toArray(resources);
if (action != null) {
switch (action) {
case 1:
request.grant(resources);
return;
case 0:
default:
request.deny();
return;
}
}
}
request.deny();
}
@Override
public void error(String s, String s1, Object o) {
Log.e(LOG_TAG, s + ", " + s1);
}
@Override
public void notImplemented() {
request.deny();
}
});
}
}
private MethodChannel getChannel() { private MethodChannel getChannel() {
return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel; return (inAppBrowserActivity != null) ? InAppBrowserFlutterPlugin.inAppBrowser.channel : flutterWebView.channel;
} }
......
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" /> <uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that <!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method. calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide In most cases you can leave this as-is, but you if you want to provide
......
...@@ -32,81 +32,81 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> { ...@@ -32,81 +32,81 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
), ),
drawer: myDrawer(context: context), drawer: myDrawer(context: context),
body: Container( body: Container(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
Container( Container(
padding: EdgeInsets.all(20.0), padding: EdgeInsets.all(20.0),
child: Text( child: Text(
"CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"), "CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
), ),
Container( Container(
padding: EdgeInsets.all(10.0), padding: EdgeInsets.all(10.0),
child: progress < 1.0 child: progress < 1.0
? LinearProgressIndicator(value: progress) ? LinearProgressIndicator(value: progress)
: Container()), : Container()),
Expanded( Expanded(
child: Container( child: Container(
margin: const EdgeInsets.all(10.0), margin: const EdgeInsets.all(10.0),
decoration: decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)), BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: InAppWebView( child: InAppWebView(
initialUrl: "https://flutter.dev/", initialUrl: "https://flutter.dev/",
initialHeaders: {}, initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions( initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions( inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true, debuggingEnabled: true,
) )
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
), ),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
onProgressChanged: (InAppWebViewController controller, int progress) {
setState(() {
this.progress = progress / 100;
});
},
), ),
), ),
), ButtonBar(
ButtonBar( alignment: MainAxisAlignment.center,
alignment: MainAxisAlignment.center, children: <Widget>[
children: <Widget>[ RaisedButton(
RaisedButton( child: Icon(Icons.arrow_back),
child: Icon(Icons.arrow_back), onPressed: () {
onPressed: () { if (webView != null) {
if (webView != null) { webView.goBack();
webView.goBack(); }
} },
}, ),
), RaisedButton(
RaisedButton( child: Icon(Icons.arrow_forward),
child: Icon(Icons.arrow_forward), onPressed: () {
onPressed: () { if (webView != null) {
if (webView != null) { webView.goForward();
webView.goForward(); }
} },
}, ),
), RaisedButton(
RaisedButton( child: Icon(Icons.refresh),
child: Icon(Icons.refresh), onPressed: () {
onPressed: () { if (webView != null) {
if (webView != null) { webView.reload();
webView.reload(); }
} },
}, ),
), ],
], ),
), ]))
]))
); );
} }
} }
\ No newline at end of file
...@@ -68,12 +68,12 @@ class _MyAppState extends State<MyApp> { ...@@ -68,12 +68,12 @@ class _MyAppState extends State<MyApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
initialRoute: '/', initialRoute: '/',
routes: { routes: {
'/': (context) => InAppWebViewExampleScreen(), '/': (context) => InAppWebViewExampleScreen(),
'/InAppBrowser': (context) => InAppBrowserExampleScreen(), '/InAppBrowser': (context) => InAppBrowserExampleScreen(),
'/ChromeSafariBrowser': (context) => ChromeSafariBrowserExampleScreen(), '/ChromeSafariBrowser': (context) => ChromeSafariBrowserExampleScreen(),
} }
); );
} }
} }
\ No newline at end of file
...@@ -214,6 +214,15 @@ class InAppWebView extends StatefulWidget { ...@@ -214,6 +214,15 @@ class InAppWebView extends StatefulWidget {
///[url] represents the new url. ///[url] represents the new url.
final void Function(InAppWebViewController controller, String url) onNavigationStateChange; final void Function(InAppWebViewController controller, String url) onNavigationStateChange;
///Event fired when the webview is requesting permission to access the specified resources and the permission currently isn't granted or denied.
///
///[origin] represents the origin of the web page which is trying to access the restricted resources.
///
///[resources] represents the array of resources the web content wants to access.
///
///**NOTE**: available only on Android 23+.
final Future<PermissionRequestResponse> Function(InAppWebViewController controller, String origin, List<String> resources) onPermissionRequest;
///Initial url that will be loaded. ///Initial url that will be loaded.
final String initialUrl; final String initialUrl;
///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation. ///Initial asset file that will be loaded. See [InAppWebView.loadFile()] for explanation.
...@@ -267,6 +276,7 @@ class InAppWebView extends StatefulWidget { ...@@ -267,6 +276,7 @@ class InAppWebView extends StatefulWidget {
this.onAjaxProgress, this.onAjaxProgress,
this.shouldInterceptFetchRequest, this.shouldInterceptFetchRequest,
this.onNavigationStateChange, this.onNavigationStateChange,
this.onPermissionRequest,
this.gestureRecognizers, this.gestureRecognizers,
}) : super(key: key); }) : super(key: key);
...@@ -581,6 +591,14 @@ class InAppWebViewController { ...@@ -581,6 +591,14 @@ class InAppWebViewController {
else if (_inAppBrowser != null) else if (_inAppBrowser != null)
_inAppBrowser.onNavigationStateChange(url); _inAppBrowser.onNavigationStateChange(url);
break; break;
case "onPermissionRequest":
String origin = call.arguments["origin"];
List<String> resources = call.arguments["resources"].cast<String>();
if (_widget != null && _widget.onPermissionRequest != null)
return (await _widget.onPermissionRequest(this, origin, resources))?.toMap();
/*else if (_inAppBrowser != null)
return (await _inAppBrowser.onPermissionRequest(origin, resources))?.toMap();*/
break;
case "onCallJsHandler": case "onCallJsHandler":
String handlerName = call.arguments["handlerName"]; String handlerName = call.arguments["handlerName"];
// decode args to json // decode args to json
......
...@@ -145,9 +145,9 @@ class CustomSchemeResponse { ...@@ -145,9 +145,9 @@ class CustomSchemeResponse {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'content-type': this.contentType, 'content-type': contentType,
'content-encoding': this.contentEnconding, 'content-encoding': contentEnconding,
'data': this.data 'data': data
}; };
} }
} }
...@@ -1586,4 +1586,38 @@ class Cookie { ...@@ -1586,4 +1586,38 @@ class Cookie {
dynamic value; dynamic value;
Cookie({@required this.name, @required this.value}); Cookie({@required this.name, @required this.value});
}
///PermissionRequestResponseAction class used by [PermissionRequestResponse] class.
class PermissionRequestResponseAction {
final int _value;
const PermissionRequestResponseAction._internal(this._value);
int toValue() => _value;
///Denies the request.
static const DENY = const PermissionRequestResponseAction._internal(0);
///Grants origin the permission to access the given resources.
static const GRANT = const PermissionRequestResponseAction._internal(1);
bool operator ==(value) => value == _value;
@override
int get hashCode => _value.hashCode;
}
///PermissionRequestResponse class represents the response used by the [onPermissionRequest] event.
class PermissionRequestResponse {
///Resources granted to be accessed by origin.
List<String> resources;
///Indicate the [PermissionRequestResponseAction] to take in response of a permission request.
PermissionRequestResponseAction action;
PermissionRequestResponse({this.resources = const [], this.action = PermissionRequestResponseAction.DENY});
Map<String, dynamic> toMap() {
return {
"resources": resources,
"action": action?.toValue()
};
}
} }
\ No newline at end of file
name: flutter_inappbrowser name: flutter_inappbrowser
description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window. description: A Flutter plugin that allows you to add an inline webview or open an in-app browser window.
version: 2.0.0 version: 2.0.1
author: Lorenzo Pichilli <pichillilorenzo@gmail.com> author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser homepage: https://github.com/pichillilorenzo/flutter_inappbrowser
......
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