Commit 2811fce4 authored by Lorenzo Pichilli's avatar Lorenzo Pichilli

updated webview options classes, fixed debuggingEnabled, added...

updated webview options classes, fixed debuggingEnabled, added getTRexRunnerHtml and getTRexRunnerCss methods
parent 299042f8
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
\ No newline at end of file
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="example/lib/main.dart" type="FlutterRunConfigurationType" factoryName="Flutter" singleton="false">
<option name="additionalArgs" value="--debug" />
<option name="filePath" value="$PROJECT_DIR$/example/lib/main.dart" />
<method v="2" />
</configuration>
......
This diff is collapsed.
......@@ -27,6 +27,7 @@
- Added `onReceivedServerTrustAuthRequest` and `onReceivedClientCertRequest` events to manage SSL requests
- Added `onFindResultReceived` event, `findAllAsync`, `findNext` and `clearMatches` methods
- Added `getHtml` method
- Fun: added `getTRexRunnerHtml` and `getTRexRunnerCss` methods to get html (with javascript) and css to recreate the Chromium's t-rex runner game
### BREAKING CHANGES
- Deleted `WebResourceRequest` class
......
......@@ -118,7 +118,7 @@ public class ContentBlockerHandler {
if (!trigger.ifTopUrl.isEmpty()) {
boolean matchFound = false;
for (String topUrl : trigger.ifTopUrl) {
if (webViewUrl[0].equals(topUrl)) {
if (webViewUrl[0].startsWith(topUrl)) {
matchFound = true;
break;
}
......@@ -128,7 +128,7 @@ public class ContentBlockerHandler {
}
if (!trigger.unlessTopUrl.isEmpty()) {
for (String topUrl : trigger.unlessTopUrl)
if (webViewUrl[0].equals(topUrl))
if (webViewUrl[0].startsWith(topUrl))
return null;
}
......
......@@ -387,6 +387,9 @@ final public class InAppWebView extends InputAwareWebView {
if (newOptionsMap.get("javaScriptEnabled") != null && options.javaScriptEnabled != newOptions.javaScriptEnabled)
settings.setJavaScriptEnabled(newOptions.javaScriptEnabled);
if (newOptionsMap.get("debuggingEnabled") != null && options.debuggingEnabled != newOptions.debuggingEnabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
setWebContentsDebuggingEnabled(newOptions.debuggingEnabled);
if (newOptionsMap.get("javaScriptCanOpenWindowsAutomatically") != null && options.javaScriptCanOpenWindowsAutomatically != newOptions.javaScriptCanOpenWindowsAutomatically)
settings.setJavaScriptCanOpenWindowsAutomatically(newOptions.javaScriptCanOpenWindowsAutomatically);
......
......@@ -639,18 +639,18 @@ public class InAppWebViewClient extends WebViewClient {
Log.e(LOG_TAG, flutterResult.error);
}
else if (flutterResult.result != null) {
Map<String, String> res = (Map<String, String>) flutterResult.result;
Map<String, Object> res = (Map<String, Object>) flutterResult.result;
WebResourceResponse response = null;
try {
response = webView.contentBlockerHandler.checkUrl(webView, url, res.get("content-type"));
response = webView.contentBlockerHandler.checkUrl(webView, url, res.get("content-type").toString());
} catch (Exception e) {
e.printStackTrace();
Log.e(LOG_TAG, e.getMessage());
}
if (response != null)
return response;
byte[] data = Base64.decode(res.get("base64data"), Base64.DEFAULT);
return new WebResourceResponse(res.get("content-type"), res.get("content-encoding"), new ByteArrayInputStream(data));
byte[] data = (byte[]) res.get("data");
return new WebResourceResponse(res.get("content-type").toString(), res.get("content-encoding").toString(), new ByteArrayInputStream(data));
}
}
......
......@@ -36,6 +36,11 @@
</p>
</main>
<!--<form method="POST" action="http://192.168.1.20:8082/test-post">
<input type="text" name="name" placeholder="name" value="Lorenzo">
<input type="submit" value="SEND">
</form>-->
<footer class="mastfoot mt-auto">
<div class="inner">
<p>Cover template for <a target="_blank" href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
......
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
platform :ios, '8.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
......
......@@ -267,7 +267,8 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/WKWebViewWithURLProtocol/WKWebViewWithURLProtocol.framework",
"${BUILT_PRODUCTS_DIR}/flutter_downloader/flutter_downloader.framework",
"${BUILT_PRODUCTS_DIR}/flutter_inappbrowser/flutter_inappbrowser.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
......@@ -275,6 +276,7 @@
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WKWebViewWithURLProtocol.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_downloader.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappbrowser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
......@@ -296,7 +298,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
/* End PBXShellScriptBuildPhase section */
......
......@@ -36,10 +36,12 @@ class _ChromeSafariExampleScreenState extends State<ChromeSafariExampleScreen> {
return new Center(
child: new RaisedButton(
onPressed: () async {
await widget.browser.open("https://flutter.dev/", options: [
AndroidChromeCustomTabsOptions(addShareButton: false),
iOSSafariOptions(barCollapsingEnabled: true)
]);
await widget.browser.open("https://flutter.dev/",
options: ChromeSafariBrowserClassOptions(
androidChromeCustomTabsOptions: AndroidChromeCustomTabsOptions(addShareButton: false),
iosSafariOptions: IosSafariOptions(barCollapsingEnabled: true)
)
);
},
child: Text("Open Chrome Safari Browser")),
);
......
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
......@@ -89,33 +90,34 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
//initialUrl: "https://192.168.1.20:4433/",
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: [
InAppWebViewOptions(
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
//clearCache: true,
useShouldOverrideUrlLoading: true,
useOnTargetBlank: true,
//useOnLoadResource: true,
useOnDownloadStart: true,
preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP,
//preferredContentMode: InAppWebViewUserPreferredContentMode.DESKTOP,
resourceCustomSchemes: ["my-special-custom-scheme"],
/*contentBlockers: [
ContentBlocker(
ContentBlockerTrigger(".*",
resourceType: [ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET],
ifTopUrl: ["https://getbootstrap.com/"]),
ContentBlockerAction(ContentBlockerActionType.BLOCK)
)
]*/
),
AndroidInAppWebViewOptions(
contentBlockers: [
ContentBlocker(
ContentBlockerTrigger(".*",
resourceType: [ContentBlockerTriggerResourceType.IMAGE, ContentBlockerTriggerResourceType.STYLE_SHEET],
ifTopUrl: ["https://getbootstrap.com/"]),
ContentBlockerAction(ContentBlockerActionType.BLOCK)
)
]
),
androidInAppWebViewOptions: AndroidInAppWebViewOptions(
databaseEnabled: true,
appCacheEnabled: true,
domStorageEnabled: true,
geolocationEnabled: true,
safeBrowsingEnabled: true,
//safeBrowsingEnabled: true,
//blockNetworkImage: true,
),
],
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
......@@ -148,6 +150,28 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
},
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("""
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no">
<style>${tRexCss}</style>
</head>
<body>
${tRexHtml}
<p>
URL ${url} failed to load.
</p>
<p>
Error: ${code}, ${message}
</p>
</body>
</html>
""");
},
onProgressChanged:
(InAppWebViewController controller, int progress) {
......@@ -159,7 +183,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
print("override $url");
controller.loadUrl(url);
},
onLoadResource: (InAppWebViewController controller, WebResourceResponse response) {
onLoadResource: (InAppWebViewController controller, LoadedResource response) {
print("Resource type: '"+response.initiatorType + "' started at: " +
response.startTime.toString() +
"ms ---> duration: " +
......@@ -187,8 +211,7 @@ class _InlineExampleScreenState extends State<InlineExampleScreen> {
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 asBase64 = base64.encode(bytes.buffer.asUint8List());
var response = new CustomSchemeResponse(asBase64, "image/svg+xml", contentEnconding: "utf-8");
var response = new CustomSchemeResponse(bytes.buffer.asUint8List(), "image/svg+xml", contentEnconding: "utf-8");
return response;
}
return null;
......
......@@ -400,7 +400,7 @@ class _MyAppState extends State<MyApp> {
initialHeaders: {
},
initialOptions: [],
initialOptions: InAppWebViewWidgetOptions(),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
......
......@@ -47,7 +47,7 @@ class MyInappBrowser extends InAppBrowser {
}
@override
void onLoadResource(WebResourceResponse response) {
void onLoadResource(LoadedResource response) {
print("Started at: " +
response.startTime.toString() +
"ms ---> duration: " +
......@@ -121,12 +121,14 @@ class _WebviewExampleScreenState extends State<WebviewExampleScreen> {
widget.browser.openFile(
"assets/index.html",
//url: "https://www.google.com/",
options: [
InAppWebViewOptions(
options: InAppBrowserClassOptions(
inAppWebViewWidgetOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
useOnLoadResource: true,
)
)
]
)
);
},
child: Text("Open Webview Browser")),
......
......@@ -20,13 +20,13 @@ class CustomeSchemeHandler : NSObject, WKURLSchemeHandler {
}
else if (result as? NSObject) == FlutterMethodNotImplemented {}
else {
let json: [String: String]
let json: [String: Any]
if let r = result {
json = r as! [String: String]
let urlResponse = URLResponse(url: url, mimeType: json["content-type"], expectedContentLength: -1, textEncodingName: json["content-encoding"])
let data = Data(base64Encoded: json["base64data"]!, options: .ignoreUnknownCharacters)
json = r as! [String: Any]
let urlResponse = URLResponse(url: url, mimeType: json["content-type"] as! String, expectedContentLength: -1, textEncodingName: json["content-encoding"] as! String)
let data = json["data"] as! FlutterStandardTypedData
urlSchemeTask.didReceive(urlResponse)
urlSchemeTask.didReceive(data!)
urlSchemeTask.didReceive(data.data)
urlSchemeTask.didFinish()
}
}
......
......@@ -14,9 +14,10 @@ public class FlutterWebViewController: NSObject, FlutterPlatformView {
var webView: InAppWebView?
var viewId: Int64 = 0
var channel: FlutterMethodChannel?
init(registrar: FlutterPluginRegistrar, withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: NSDictionary) {
super.init()
self.registrar = registrar
self.viewId = viewId
......
......@@ -8,6 +8,7 @@
import Flutter
import Foundation
import WebKit
import WKWebViewWithURLProtocol
func currentTimeInMilliSeconds() -> Int64 {
let currentDate = Date()
......@@ -242,6 +243,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi
static var credentialsProposed: [URLCredential] = []
init(frame: CGRect, configuration: WKWebViewConfiguration, IABController: InAppBrowserWebViewController?, IAWController: FlutterWebViewController?) {
super.init(frame: frame, configuration: configuration)
self.IABController = IABController
self.IAWController = IAWController
......
......@@ -47,6 +47,7 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
public init(with registrar: FlutterPluginRegistrar) {
super.init()
self.registrar = registrar
self.channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
registrar.addMethodCallDelegate(self, channel: channel!)
......
......@@ -17,7 +17,7 @@ A new Flutter plugin.
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = '8.0'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0'
s.dependency "WKWebViewWithURLProtocol"
end
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart';
import 'types.dart';
import 'channel_manager.dart';
......@@ -70,19 +70,29 @@ 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<ChromeSafariBrowserOptions> options = const [], Map<String, String> headersFallback = const {}, List<BrowserOptions> optionsFallback = const []}) async {
Future<void> open(String url, {ChromeSafariBrowserClassOptions options, Map<String, String> headersFallback = const {}, InAppBrowserClassOptions optionsFallback}) async {
assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap());
});
if (Platform.isAndroid)
optionsMap.addAll(options.androidChromeCustomTabsOptions?.toMap() ?? {});
else if (Platform.isIOS)
optionsMap.addAll(options.iosSafariOptions?.toMap() ?? {});
Map<String, dynamic> optionsFallbackMap = {};
optionsFallback.forEach((webViewOption) {
optionsFallbackMap.addAll(webViewOption.toMap());
});
if (optionsFallback != null) {
optionsFallbackMap.addAll(optionsFallback.inAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsFallbackMap.addAll(optionsFallback.androidInAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsFallbackMap.addAll(optionsFallback.iosInAppBrowserOptions?.toMap() ?? {});
optionsFallbackMap.addAll(optionsFallback.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
......
......@@ -10,11 +10,26 @@ class ContentBlocker {
"action": action.toMap()
};
}
static ContentBlocker fromMap(Map<dynamic, Map<dynamic, dynamic>> map) {
return ContentBlocker(
ContentBlockerTrigger.fromMap(
Map<String, dynamic>.from(map["trigger"])
),
ContentBlockerAction.fromMap(
Map<String, dynamic>.from(map["action"])
)
);
}
}
class ContentBlockerTriggerResourceType {
final String _value;
const ContentBlockerTriggerResourceType._internal(this._value);
static ContentBlockerTriggerResourceType fromValue(String value) {
return (["document", "image", "LINK", "style-sheet", "script", "font",
"media", "svg-document", "raw"].contains(value)) ? ContentBlockerTriggerResourceType._internal(value) : null;
}
toValue() => _value;
static const DOCUMENT = const ContentBlockerTriggerResourceType._internal('document');
......@@ -30,6 +45,9 @@ class ContentBlockerTriggerResourceType {
class ContentBlockerTriggerLoadType {
final String _value;
const ContentBlockerTriggerLoadType._internal(this._value);
static ContentBlockerTriggerLoadType fromValue(String value) {
return (["first-party", "third-party"].contains(value)) ? ContentBlockerTriggerLoadType._internal(value) : null;
}
toValue() => _value;
static const FIRST_PARTY = const ContentBlockerTriggerLoadType._internal('first-party');
......@@ -90,11 +108,40 @@ class ContentBlockerTrigger {
return map;
}
static ContentBlockerTrigger fromMap(Map<String, dynamic> map) {
List<ContentBlockerTriggerResourceType> resourceType = [];
List<ContentBlockerTriggerLoadType> loadType = [];
List<String> resourceTypeStringList = List<String>.from(map["resource-type"] ?? []);
resourceTypeStringList.forEach((type) {
resourceType.add(ContentBlockerTriggerResourceType.fromValue(type));
});
List<String> loadTypeStringList = List<String>.from(map["load-type"] ?? []);
loadTypeStringList.forEach((type) {
loadType.add(ContentBlockerTriggerLoadType.fromValue(type));
});
return ContentBlockerTrigger(
map["url-filter"],
urlFilterIsCaseSensitive: map["url-filter-is-case-sensitive"],
ifDomain: List<String>.from(map["if-domain"] ?? []),
unlessDomain: List<String>.from(map["unless-domain"] ?? []),
resourceType: resourceType,
loadType: loadType,
ifTopUrl: List<String>.from(map["if-top-url"] ?? []),
unlessTopUrl: List<String>.from(map["unless-top-url"] ?? [])
);
}
}
class ContentBlockerActionType {
final String _value;
const ContentBlockerActionType._internal(this._value);
static ContentBlockerActionType fromValue(String value) {
return (["block", "css-display-none", "make-https"].contains(value)) ? ContentBlockerActionType._internal(value) : null;
}
toValue() => _value;
static const BLOCK = const ContentBlockerActionType._internal('block');
......@@ -127,4 +174,11 @@ class ContentBlockerAction {
return map;
}
static ContentBlockerAction fromMap(Map<String, dynamic> map) {
return ContentBlockerAction(
ContentBlockerActionType.fromValue(map["type"]),
selector: map["selector"]
);
}
}
\ No newline at end of file
import 'dart:async';
import 'dart:collection';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_inappbrowser/src/webview_options.dart';
......@@ -102,14 +103,22 @@ class InAppBrowser {
/// - __allowsInlineMediaPlayback__: Set to `true` to allow HTML5 media playback to appear inline within the screen layout, using browser-supplied controls rather than native controls. For this to work, add the `webkit-playsinline` attribute to any `<video>` elements. The default value is `false`.
/// - __allowsPictureInPictureMediaPlayback__: Set to `true` to allow HTML5 videos play picture-in-picture. The default value is `true`.
/// - __spinner__: Set to `false` to hide the spinner when the WebView is loading a page. The default value is `true`.
Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, List<BrowserOptions> options = const []}) async {
Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async {
assert(url != null && url.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $url!');
Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap());
});
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
......@@ -140,7 +149,7 @@ class InAppBrowser {
/// uses-material-design: true
///
/// assets:
/// - assets/index.html
/// - assets/t-rex.html
/// - assets/css/
/// - assets/images/
///
......@@ -149,17 +158,25 @@ class InAppBrowser {
///Example of a `main.dart` file:
///```dart
///...
///inAppBrowser.openFile("assets/index.html");
///inAppBrowser.openFile("assets/t-rex.html");
///...
///```
Future<void> openFile(String assetFilePath, {Map<String, String> headers = const {}, List<BrowserOptions> options = const []}) async {
Future<void> openFile(String assetFilePath, {Map<String, String> headers = const {}, InAppBrowserClassOptions options}) async {
assert(assetFilePath != null && assetFilePath.isNotEmpty);
this.throwIsAlreadyOpened(message: 'Cannot open $assetFilePath!');
Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap());
});
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
......@@ -176,13 +193,21 @@ class InAppBrowser {
///Opens a new [InAppBrowser] instance with [data] as a content, using [baseUrl] as the base URL for it.
///The [mimeType] parameter specifies the format of the data.
///The [encoding] parameter specifies the encoding of the data.
Future<void> openData(String data, {String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", List<BrowserOptions> options = const []}) async {
Future<void> openData(String data, {String mimeType = "text/html", String encoding = "utf8", String baseUrl = "about:blank", InAppBrowserClassOptions options}) async {
assert(data != null);
Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap());
});
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
......@@ -246,13 +271,21 @@ class InAppBrowser {
}
///Sets the [InAppBrowser] options with the new [options] and evaluates them.
Future<void> setOptions(List<BrowserOptions> options) async {
Future<void> setOptions(InAppBrowserClassOptions options) async {
this.throwIsNotOpened();
Map<String, dynamic> optionsMap = {};
options.forEach((webViewOption) {
optionsMap.addAll(webViewOption.toMap());
});
optionsMap.addAll(options.inAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid) {
optionsMap.addAll(options.androidInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.androidInAppWebViewOptions?.toMap() ?? {});
}
else if (Platform.isIOS) {
optionsMap.addAll(options.iosInAppBrowserOptions?.toMap() ?? {});
optionsMap.addAll(options.inAppWebViewWidgetOptions?.iosInAppWebViewOptions?.toMap() ?? {});
}
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
......@@ -262,15 +295,29 @@ class InAppBrowser {
}
///Gets the current [InAppBrowser] options as a `Map`. Returns `null` if the options are not setted yet.
Future<Map<String, dynamic>> getOptions() async {
Future<InAppBrowserClassOptions> getOptions() async {
this.throwIsNotOpened();
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('optionsType', () => "InAppBrowserOptions");
InAppBrowserClassOptions inAppBrowserClassOptions = InAppBrowserClassOptions();
Map<dynamic, dynamic> options = await ChannelManager.channel.invokeMethod('getOptions', args);
if (options != null)
if (options != null) {
options = options.cast<String, dynamic>();
return options;
inAppBrowserClassOptions.inAppBrowserOptions = InAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid) {
inAppBrowserClassOptions.androidInAppBrowserOptions = AndroidInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
}
else if (Platform.isIOS) {
inAppBrowserClassOptions.iosInAppBrowserOptions = IosInAppBrowserOptions.fromMap(options);
inAppBrowserClassOptions.inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
}
}
return inAppBrowserClassOptions;
}
///Returns `true` if the [InAppBrowser] instance is opened, otherwise `false`.
......@@ -323,7 +370,7 @@ class InAppBrowser {
///Event fires when the [InAppBrowser] webview loads a resource.
///
///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
void onLoadResource(WebResourceResponse response) {
void onLoadResource(LoadedResource resource) {
}
......
......@@ -45,7 +45,7 @@ class InAppLocalhostServer {
var body = List<int>();
var path = request.requestedUri.path;
path = (path.startsWith('/')) ? path.substring(1) : path;
path += (path.endsWith('/')) ? 'index.html' : '';
path += (path.endsWith('/')) ? 't-rex.html' : '';
try {
body = (await rootBundle.load(path))
......
......@@ -112,7 +112,7 @@ class InAppWebView extends StatefulWidget {
///**NOTE**: In order to be able to listen this event, you need to set `useOnLoadResource` option to `true`.
///
///**NOTE only for Android**: to be able to listen this event, you need also the enable javascript.
final void Function(InAppWebViewController controller, WebResourceResponse response) onLoadResource;
final void Function(InAppWebViewController controller, LoadedResource resource) onLoadResource;
///Event fires when the [InAppWebView] scrolls.
///
......@@ -207,7 +207,7 @@ class InAppWebView extends StatefulWidget {
///Initial headers that will be used.
final Map<String, String> initialHeaders;
///Initial options that will be used.
final List<WebViewOptions> initialOptions;
final InAppWebViewWidgetOptions initialOptions;
/// `gestureRecognizers` specifies which gestures should be consumed by the web view.
/// It is possible for other gesture recognizers to be competing with the web view on pointer
/// events, e.g if the web view is inside a [ListView] the [ListView] will want to handle
......@@ -223,7 +223,7 @@ class InAppWebView extends StatefulWidget {
this.initialFile,
this.initialData,
this.initialHeaders = const {},
this.initialOptions = const [],
this.initialOptions,
this.onWebViewCreated,
this.onLoadStart,
this.onLoadStop,
......@@ -259,10 +259,11 @@ class _InAppWebViewState extends State<InAppWebView> {
@override
Widget build(BuildContext context) {
Map<String, dynamic> initialOptions = {};
widget.initialOptions.forEach((webViewOption) {
if ((Platform.isAndroid && webViewOption is AndroidOptions) || (Platform.isIOS && webViewOption is iOSOptions))
initialOptions.addAll(webViewOption.toMap());
});
initialOptions.addAll(widget.initialOptions.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid)
initialOptions.addAll(widget.initialOptions.androidInAppWebViewOptions?.toMap() ?? {});
else if (Platform.isIOS)
initialOptions.addAll(widget.initialOptions.iosInAppWebViewOptions?.toMap() ?? {});
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
......@@ -404,7 +405,7 @@ class InAppWebViewController {
double startTime = call.arguments["startTime"];
double duration = call.arguments["duration"];
var response = new WebResourceResponse(initiatorType, url, startTime, duration);
var response = new LoadedResource(initiatorType, url, startTime, duration);
if (_widget != null && _widget.onLoadResource != null)
_widget.onLoadResource(this, response);
......@@ -606,8 +607,8 @@ class InAppWebViewController {
///- downloading it using an `HttpClient` through the WebView's current url.
Future<String> getHtml() async {
var html = "";
Map<String, dynamic> options = await getOptions();
if (options != null && options["javaScriptEnabled"] == true) {
InAppWebViewWidgetOptions options = await getOptions();
if (options != null && options.inAppWebViewOptions.javaScriptEnabled == true) {
html = await injectScriptCode("window.document.getElementsByTagName('html')[0].outerHTML;");
if (html.isNotEmpty)
return html;
......@@ -803,7 +804,7 @@ class InAppWebViewController {
/// uses-material-design: true
///
/// assets:
/// - assets/index.html
/// - assets/t-rex.html
/// - assets/css/
/// - assets/images/
///
......@@ -812,7 +813,7 @@ class InAppWebViewController {
///Example of a `main.dart` file:
///```dart
///...
///inAppBrowser.loadFile("assets/index.html");
///inAppBrowser.loadFile("assets/t-rex.html");
///...
///```
Future<void> loadFile(String assetFilePath, {Map<String, String> headers = const {}}) async {
......@@ -1042,27 +1043,44 @@ class InAppWebViewController {
}
///Sets the [InAppWebView] options with the new [options] and evaluates them.
Future<void> setOptions(Map<String, dynamic> options) async {
Future<void> setOptions(InAppWebViewWidgetOptions options) async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
args.putIfAbsent('options', () => options);
Map<String, dynamic> optionsMap = {};
optionsMap.addAll(options.inAppWebViewOptions?.toMap() ?? {});
if (Platform.isAndroid)
optionsMap.addAll(options.androidInAppWebViewOptions?.toMap() ?? {});
else if (Platform.isIOS)
optionsMap.addAll(options.iosInAppWebViewOptions?.toMap() ?? {});
args.putIfAbsent('options', () => optionsMap);
await _channel.invokeMethod('setOptions', args);
}
///Gets the current [InAppWebView] options. Returns `null` if the options are not setted yet.
Future<Map<String, dynamic>> getOptions() async {
///Gets the current [InAppWebView] options. Returns the options with `null` value if they are not set yet.
Future<InAppWebViewWidgetOptions> getOptions() async {
Map<String, dynamic> args = <String, dynamic>{};
if (_inAppBrowserUuid != null && _inAppBrowser != null) {
_inAppBrowser.throwIsNotOpened();
args.putIfAbsent('uuid', () => _inAppBrowserUuid);
}
InAppWebViewWidgetOptions inAppWebViewWidgetOptions = InAppWebViewWidgetOptions();
Map<dynamic, dynamic> options = await _channel.invokeMethod('getOptions', args);
if (options != null)
if (options != null) {
options = options.cast<String, dynamic>();
return options;
inAppWebViewWidgetOptions.inAppWebViewOptions = InAppWebViewOptions.fromMap(options);
if (Platform.isAndroid)
inAppWebViewWidgetOptions.androidInAppWebViewOptions = AndroidInAppWebViewOptions.fromMap(options);
else if (Platform.isIOS)
inAppWebViewWidgetOptions.iosInAppWebViewOptions = IosInAppWebViewOptions.fromMap(options);
}
return inAppWebViewWidgetOptions;
}
///Gets the WebHistory for this WebView. This contains the back/forward list for use in querying each item in the history stack.
......@@ -1230,4 +1248,14 @@ class InAppWebViewController {
}
await _channel.invokeMethod('clearMatches', args);
}
///Gets the html (with javascript) of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerCss()].
Future<String> getTRexRunnerHtml() async {
return await rootBundle.loadString("packages/flutter_inappbrowser/t_rex_runner/t-rex.html");
}
///Gets the css of the Chromium's t-rex runner game. Used in combination with [getTRexRunnerHtml()].
Future<String> getTRexRunnerCss() async {
return await rootBundle.loadString("packages/flutter_inappbrowser/t_rex_runner/t-rex.css");
}
}
This diff is collapsed.
This diff is collapsed.
#main-frame-error {
box-sizing: border-box;
padding: 0 10%;
font-size: 1em;
line-height: 1.55;
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
width: 100%;
}
#main-content {
font-size: 1em;
line-height: 1.55;
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
width: 100%;
}
#t-rex-icon {
font-size: 1em;
line-height: 1.55;
background-repeat: no-repeat;
background-size: 100%;
height: 72px;
margin: 0 0 40px;
width: 72px;
display: inline-block;
content: -webkit-image-set(
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAQMAAABvIyEEAAAABlBMVEUAAABTU1OoaSf/AAAAAXRSTlMAQObYZgAAAGxJREFUeF7tyMEJwkAQRuFf5ipMKxYQiJ3Z2nSwrWwBA0+DQZcdxEOueaePp9+dQZFB7GpUcURSVU66yVNFj6LFICatThZB6r/ko/pbRpUgilY0Cbw5sNmb9txGXUKyuH7eV25x39DtJXUNPQGJtWFV+BT/QAAAAABJRU5ErkJggg==)
1x,
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQBAMAAAAVaP+LAAAAGFBMVEUAAABTU1NNTU1TU1NPT09SUlJSUlJTU1O8B7DEAAAAB3RSTlMAoArVKvVgBuEdKgAAAJ1JREFUeF7t1TEOwyAMQNG0Q6/UE+RMXD9d/tC6womIFSL9P+MnAYOXeTIzMzMzMzMzaz8J9Ri6HoITmuHXhISE8nEh9yxDh55aCEUoTGbbQwjqHwIkRAEiIaG0+0AA9VBMaE89Rogeoww936MQrWdBr4GN/z0IAdQ6nQ/FIpRXDwHcA+JIJcQowQAlFUA0MfQpXLlVQfkzR4igS6ENjknm/wiaGhsAAAAASUVORK5CYII=)
2x
);
position: relative;
visibility: hidden;
}
#offline-resources {
display: none;
}
#main-frame-error > .runner-container {
height: 150px;
max-width: 600px;
overflow: hidden;
position: absolute;
top: 35px;
width: 44px;
}
#main-frame-error > .controller {
background: rgba(247, 247, 247, 0.1);
height: 100vh;
left: 0;
position: absolute;
top: 0;
width: 100vw;
z-index: 9;
}
#main-frame-error .hidden {
display: none;
}
This diff is collapsed.
......@@ -3,6 +3,7 @@
const express = require('express')
var https = require('https')
const auth = require('basic-auth')
const app = express()
const appHttps = express()
const appAuthBasic = express()
const fs = require('fs')
......@@ -78,6 +79,40 @@ appAuthBasic.get("/", (req, res) => {
</body>
</html>
`);
res.end()
})
appAuthBasic.listen(8081)
\ No newline at end of file
appAuthBasic.listen(8081)
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.get("/", (req, res) => {
res.send(`
<html>
<head>
</head>
<body>
<p>HELLO</p>
</body>
</html>
`);
res.end()
})
app.post("/test-post", (req, res) => {
res.send(`
<html>
<head>
</head>
<body>
<p>HELLO ${req.body.name}!</p>
</body>
</html>
`);
res.end()
})
app.listen(8082)
\ No newline at end of file
......@@ -24,6 +24,9 @@ flutter:
androidPackage: com.pichillilorenzo.flutter_inappbrowser
pluginClass: InAppBrowserFlutterPlugin
assets:
- packages/flutter_inappbrowser/t_rex_runner/t-rex.html
- packages/flutter_inappbrowser/t_rex_runner/t-rex.css
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
......
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