import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_inappbrowser/flutter_inappbrowser.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:path_provider/path_provider.dart'; import 'package:flutter/services.dart' show rootBundle; class InAppWebViewExampleScreen extends StatefulWidget { @override _InAppWebViewExampleScreenState createState() => new _InAppWebViewExampleScreenState(); } class Foo { String bar; String baz; Foo({this.bar, this.baz}); Map toJson() { return {'bar': this.bar, 'baz': this.baz}; } } class _InAppWebViewExampleScreenState extends State { InAppWebViewController webView; String url = ""; double progress = 0; CookieManager cookieManager = CookieManager.instance(); TextEditingController _textFieldController = TextEditingController(); @override void initState() { super.initState(); } @override void dispose() { super.dispose(); _textFieldController.dispose(); } @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 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 Scaffold( appBar: AppBar( title: Text( "InAppWebView", )), drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ DrawerHeader( child: Text('flutter_inappbrowser example'), decoration: BoxDecoration( color: Colors.blue, ), ), ListTile( title: Text('InAppBrowser'), onTap: () { Navigator.pushReplacementNamed(context, '/InAppBrowser'); }, ), ListTile( title: Text('ChromeSafariBrowser'), onTap: () { Navigator.pushReplacementNamed(context, '/ChromeSafariBrowser'); }, ), ListTile( title: Text('InAppWebView'), onTap: () { Navigator.pushReplacementNamed(context, '/'); }, ), ], ), ), body: Container( child: Column(children: [ Container( padding: EdgeInsets.all(20.0), child: Text( "CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"), ), Container( padding: EdgeInsets.all(10.0), child: progress < 1.0 ? LinearProgressIndicator(value: progress) : Container()), Expanded( child: Container( margin: const EdgeInsets.all(10.0), decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)), child: InAppWebView( //initialUrl: "https://www.youtube.com/embed/M7lc1UVf-VE?playsinline=1", //initialUrl: "https://github.com", //initialUrl: "chrome://safe-browsing/match?type=malware", //initialUrl: "http://192.168.1.20:8081/", //initialUrl: "https://192.168.1.20:4433/", //initialFile: "assets/index.html", initialUrl: "https://flutter.dev/", initialHeaders: {}, initialOptions: InAppWebViewWidgetOptions( inAppWebViewOptions: InAppWebViewOptions( //disableVerticalScroll: false, //disableHorizontalScroll: false, debuggingEnabled: true, clearCache: true, //useShouldOverrideUrlLoading: true, useOnTargetBlank: true, useOnLoadResource: true, //useOnDownloadStart: true, //useShouldInterceptAjaxRequest: true, //useShouldInterceptFetchRequest: true, //preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP, resourceCustomSchemes: [ "my-special-custom-scheme" ], contentBlockers: [ ContentBlocker( trigger: ContentBlockerTrigger( urlFilter: ".*", resourceType: [ ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET ], ifTopUrl: [ "https://flutter.dev/" ]), action: ContentBlockerAction( type: ContentBlockerActionType.BLOCK)) ]), androidInAppWebViewOptions: AndroidInAppWebViewOptions( databaseEnabled: true, domStorageEnabled: true, geolocationEnabled: true, safeBrowsingEnabled: true, //blockNetworkImage: true, ), ), onWebViewCreated: (InAppWebViewController controller) { webView = controller; if (Platform.isAndroid) webView.startSafeBrowsing(); webView.addJavaScriptHandler( handlerName: 'handlerFoo', callback: (args) { return new Foo(bar: 'bar_value', baz: 'baz_value'); }); webView.addJavaScriptHandler( handlerName: 'handlerFooWithArgs', callback: (args) { print(args); return [ args[0] + 5, !args[1], args[2][0], args[3]['foo'] ]; }); }, onLoadStart: (InAppWebViewController controller, String url) { print("started $url"); setState(() { this.url = url; }); }, onLoadStop: (InAppWebViewController controller, String url) async { print("stopped $url"); if (Platform.isAndroid) { controller.clearSslPreferences(); controller.clearClientCertPreferences(); } //controller.findAllAsync(find: "InAppWebView"); //controller.findAllAsync(find: "InAppWebViewInitialFileTest"); print(await controller.getFavicons()); print(await CookieManager.instance().getCookies(url: url)); //await CookieManager.instance().setCookie(url: url, name: "myCookie", value: "myValue"); //print(await CookieManager.instance().getCookies(url: url)); //await Future.delayed(const Duration(milliseconds: 2000)); //controller.scrollTo(x: 0, y: 500); //await Future.delayed(const Duration(milliseconds: 2000)); //controller.scrollBy(x: 0, y: 150); }, onScrollChanged: (InAppWebViewController controller, int x, int y) { //print("\nSCROLLED\n"); }, onLoadError: (InAppWebViewController controller, String url, int code, String message) async { print("error $url: $code, $message"); var tRexHtml = await controller.getTRexRunnerHtml(); var tRexCss = await controller.getTRexRunnerCss(); controller.loadData(data: """ $tRexHtml

URL $url failed to load.

Error: $code, $message

"""); }, onLoadHttpError: (InAppWebViewController controller, String url, int statusCode, String description) async { print("HTTP error $url: $statusCode, $description"); }, onProgressChanged: (InAppWebViewController controller, int progress) { setState(() { this.progress = progress / 100; }); }, shouldOverrideUrlLoading: (InAppWebViewController controller, String url) { print("override $url"); controller.loadUrl(url: url); }, onLoadResource: (InAppWebViewController controller, LoadedResource response) { print("Resource type: '" + response.initiatorType + "' started at: " + response.startTime.toString() + "ms ---> duration: " + response.duration.toString() + "ms " + response.url); }, onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) { print(""" console output: message: ${consoleMessage.message} messageLevel: ${consoleMessage.messageLevel.toString()} """); }, 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) // ); }, onLoadResourceCustomScheme: (InAppWebViewController controller, String scheme, String url) async { if (scheme == "my-special-custom-scheme") { var bytes = await rootBundle.load("assets/" + url.replaceFirst("my-special-custom-scheme://", "", 0)); var response = new CustomSchemeResponse( data: bytes.buffer.asUint8List(), contentType: "image/svg+xml", contentEnconding: "utf-8"); return response; } return null; }, onTargetBlank: (InAppWebViewController controller, String url) { print("target _blank: " + url); controller.loadUrl(url: url); }, onGeolocationPermissionsShowPrompt: (InAppWebViewController controller, String origin) async { GeolocationPermissionShowPromptResponse response; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text("Permission Geolocation API"), content: Text("Can we use Geolocation API?"), actions: [ FlatButton( child: Text("Close"), onPressed: () { response = new GeolocationPermissionShowPromptResponse( origin: origin, allow: false, retain: false); Navigator.of(context).pop(); }, ), FlatButton( child: Text("Accept"), onPressed: () { response = new GeolocationPermissionShowPromptResponse( origin: origin, allow: true, retain: true); Navigator.of(context).pop(); }, ), ], ); }, ); return response; }, onJsAlert: (InAppWebViewController controller, String message) async { JsAlertResponseAction action = await createAlertDialog(context, message); return new JsAlertResponse( handledByClient: true, action: action); }, onJsConfirm: (InAppWebViewController controller, String message) async { JsConfirmResponseAction action = await createConfirmDialog(context, message); return new JsConfirmResponse( handledByClient: true, action: action); }, onJsPrompt: (InAppWebViewController controller, String message, String defaultValue) async { _textFieldController.text = defaultValue; JsPromptResponseAction action = await createPromptDialog(context, message); return new JsPromptResponse( handledByClient: true, action: action, value: _textFieldController.text); }, onSafeBrowsingHit: (InAppWebViewController controller, String url, SafeBrowsingThreat threatType) async { SafeBrowsingResponseAction action = SafeBrowsingResponseAction.SHOW_INTERSTITIAL; 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 .PROCEED, permanentPersistence: true); }, onReceivedServerTrustAuthRequest: (InAppWebViewController controller, ServerTrustChallenge challenge) async { print( "SERVER TRUST AUTH REQUEST: ${challenge.protectionSpace.host}, SSL ERROR CODE: ${challenge.error.toString()}, MESSAGE: ${challenge.message}"); return new ServerTrustAuthResponse( action: ServerTrustAuthResponseAction.PROCEED); }, onReceivedClientCertRequest: (InAppWebViewController controller, ClientCertChallenge challenge) async { print( "CLIENT CERT REQUEST: ${challenge.protectionSpace.host}"); return new ClientCertResponse( certificatePath: "assets/certificate.pfx", certificatePassword: "", androidKeyStoreType: "PKCS12", action: ClientCertResponseAction.PROCEED); }, onFindResultReceived: (InAppWebViewController controller, int activeMatchOrdinal, int numberOfMatches, bool isDoneCounting) async { print( "Current highlighted: $activeMatchOrdinal, Number of matches found: $numberOfMatches, find operation completed: $isDoneCounting"); }, shouldInterceptAjaxRequest: (InAppWebViewController controller, AjaxRequest ajaxRequest) async { print( "AJAX REQUEST: ${ajaxRequest.method} - ${ajaxRequest.url}, DATA: ${ajaxRequest.data}, headers: ${ajaxRequest.headers}"); if (ajaxRequest.url == "http://192.168.1.20:8082/test-ajax-post") { ajaxRequest.responseType = 'json'; ajaxRequest.data = "firstname=Lorenzo&lastname=Pichilli"; } // ajaxRequest.method = "GET"; // ajaxRequest.url = "http://192.168.1.20:8082/test-download-file"; // ajaxRequest.headers = { // "Custom-Header": "Custom-Value" // }; // return ajaxRequest; return ajaxRequest; }, onAjaxReadyStateChange: (InAppWebViewController controller, AjaxRequest ajaxRequest) async { print( "AJAX READY STATE CHANGE: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.status}, ${ajaxRequest.readyState}, ${ajaxRequest.responseType}, ${ajaxRequest.responseText}, ${ajaxRequest.response}, ${ajaxRequest.responseHeaders}"); return AjaxRequestAction.PROCEED; }, onAjaxProgress: (InAppWebViewController controller, AjaxRequest ajaxRequest) async { print( "AJAX EVENT: ${ajaxRequest.method} - ${ajaxRequest.url}, ${ajaxRequest.event.type}, LOADED: ${ajaxRequest.event.loaded}, ${ajaxRequest.responseHeaders}"); return AjaxRequestAction.PROCEED; }, shouldInterceptFetchRequest: (InAppWebViewController controller, FetchRequest fetchRequest) async { print( "FETCH REQUEST: ${fetchRequest.method} - ${fetchRequest.url}, headers: ${fetchRequest.headers}"); fetchRequest.action = FetchRequestAction.ABORT; print(fetchRequest.body); return fetchRequest; }, onNavigationStateChange: (InAppWebViewController controller, String url) async { print("NAVIGATION STATE CHANGE: $url"); setState(() { this.url = url; }); }, ), ), ), ButtonBar( alignment: MainAxisAlignment.center, children: [ RaisedButton( child: Icon(Icons.arrow_back), onPressed: () { if (webView != null) { webView.goBack(); } }, ), RaisedButton( child: Icon(Icons.arrow_forward), onPressed: () { if (webView != null) { webView.goForward(); } }, ), RaisedButton( child: Icon(Icons.refresh), onPressed: () { if (webView != null) { webView.reload(); } }, ), ], ), ]))); } Future createAlertDialog( BuildContext context, String message) async { JsAlertResponseAction action; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( content: Text(message), actions: [ FlatButton( child: Text("Ok"), onPressed: () { action = JsAlertResponseAction.CONFIRM; Navigator.of(context).pop(); }, ), ], ); }, ); return action; } Future createConfirmDialog( BuildContext context, String message) async { JsConfirmResponseAction action; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( content: Text(message), actions: [ FlatButton( child: Text("Cancel"), onPressed: () { action = JsConfirmResponseAction.CANCEL; Navigator.of(context).pop(); }, ), FlatButton( child: Text("Ok"), onPressed: () { action = JsConfirmResponseAction.CONFIRM; Navigator.of(context).pop(); }, ), ], ); }, ); return action; } Future createPromptDialog( BuildContext context, String message) async { JsPromptResponseAction action; await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text(message), content: TextField( controller: _textFieldController, ), actions: [ FlatButton( child: Text("Cancel"), onPressed: () { action = JsPromptResponseAction.CANCEL; Navigator.of(context).pop(); }, ), FlatButton( child: Text("Ok"), onPressed: () { action = JsPromptResponseAction.CONFIRM; Navigator.of(context).pop(); }, ), ], ); }, ); return action; } Future _findLocalPath() async { final directory = Platform.isAndroid ? await getExternalStorageDirectory() : await getApplicationDocumentsDirectory(); return directory.path; } }