updated onLoadResource method, InAppBrowser.open url parameter has the default value: 'about:blank'

This commit is contained in:
pichillilorenzo 2018-10-13 03:16:08 +02:00
parent d696ed1e68
commit b4e3e73bce
8 changed files with 252 additions and 124 deletions

View File

@ -16,18 +16,13 @@
<component name="ChangeListManager">
<list default="true" id="9b41f7a2-a71e-4923-91fb-249d7815b3e7" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/android/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowserWebViewClient.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" beforeDir="false" afterPath="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/WebViewActivity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/project.pbxproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/ios/Runner/WebView.storyboard" beforeDir="false" afterPath="$PROJECT_DIR$/example/ios/Runner/WebView.storyboard" afterDir="false" />
<change beforePath="$PROJECT_DIR$/example/lib/main.dart" beforeDir="false" afterPath="$PROJECT_DIR$/example/lib/main.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserOptions.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/InAppBrowserWebViewController.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/MyURLProtocol.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/MyURLProtocol.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" beforeDir="false" afterPath="$PROJECT_DIR$/ios/Classes/SwiftFlutterPlugin.swift" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" beforeDir="false" afterPath="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pubspec.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pubspec.yaml" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" />
@ -44,11 +39,14 @@
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="flutter_inappbrowser.dart" pinned="false" current-in-tab="true">
<file leaf-file-name="flutter_inappbrowser.dart" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="358">
<caret line="262" column="75" selection-start-line="262" selection-start-column="75" selection-end-line="262" selection-end-column="75" />
<state relative-caret-position="315">
<caret line="246" column="71" selection-start-line="246" selection-start-column="71" selection-end-line="246" selection-end-column="71" />
<folding>
<element signature="e#814#834#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
@ -97,11 +95,11 @@
</provider>
</entry>
</file>
<file leaf-file-name="main.dart" pinned="false" current-in-tab="false">
<file leaf-file-name="main.dart" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="200">
<caret line="74" column="60" selection-start-line="74" selection-start-column="54" selection-end-line="74" selection-end-column="60" />
<state relative-caret-position="537">
<caret line="140" column="44" selection-start-line="140" selection-start-column="44" selection-end-line="140" selection-end-column="64" />
</state>
</provider>
</entry>
@ -182,12 +180,12 @@
<option value="$PROJECT_DIR$/android/src/main/java/com/pichillilorenzo/flutter_inappbrowser/InAppBrowser.java" />
<option value="$PROJECT_DIR$/ios/flutter_inappbrowser.podspec" />
<option value="$PROJECT_DIR$/example/ios/Podfile" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/android/build.gradle" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
<option value="$PROJECT_DIR$/lib/flutter_inappbrowser.dart" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
<option value="$PROJECT_DIR$/example/lib/main.dart" />
</list>
</option>
</component>
@ -203,8 +201,19 @@
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="PackagesPane" />
<pane id="AndroidView" />
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="ProjectPane">
<subPane>
<expand>
@ -232,17 +241,6 @@
</subPane>
<option name="show-excluded-files" value="false" />
</pane>
<pane id="Scope">
<subPane subId="Project Files">
<expand>
<path>
<item name="Root" type="cbb8eebc:String" user="Root" />
<item name="flutter_inappbrowser" type="cbb8eebc:String" user="flutter_inappbrowser" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
@ -403,15 +401,16 @@
<layout>
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.2370452" />
<window_info anchor="right" id="Palette&#9;" order="3" />
<window_info id="Image Layers" order="2" />
<window_info id="Build Variants" order="2" side_tool="true" />
<window_info anchor="right" id="Capture Analysis" order="3" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.50316054" side_tool="true" weight="0.32083333" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.3290735" />
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49683943" visible="true" weight="0.39801544" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5035553" side_tool="true" weight="0.25689086" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.32855567" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49644473" weight="0.39801544" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.4973545" weight="0.25689086" />
<window_info active="true" anchor="bottom" id="Terminal" order="10" sideWeight="0.49644473" visible="true" weight="0.25689086" />
<window_info anchor="right" id="Flutter Outline" order="3" weight="0.32922077" />
<window_info anchor="bottom" id="Logcat" order="11" />
<window_info id="Captures" order="2" weight="0.32936507" />
@ -424,7 +423,6 @@
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="right" id="Flutter Inspector" order="3" weight="0.32987013" />
<window_info anchor="bottom" id="Messages" order="12" visible="true" weight="0.2370452" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="right" id="Assistant" order="4" visible="true" weight="0.32987013" />
@ -439,7 +437,6 @@
<window_info id="Designer" order="4" />
<window_info anchor="bottom" id="Dart Analysis" order="14" weight="0.3290735" />
<window_info id="Build Variants" order="2" side_tool="true" />
<window_info id="Image Layers" order="5" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.4973545" weight="0.32161874" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
@ -451,21 +448,22 @@
<window_info anchor="bottom" id="Android Profiler" order="7" show_stripe_button="false" />
<window_info anchor="right" id="Commander" order="0" weight="0.4" />
<window_info anchor="bottom" id="Event Log" order="8" sideWeight="0.5026455" side_tool="true" weight="0.31735888" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.18376623" />
<window_info anchor="right" id="Device File Explorer" order="4" side_tool="true" />
<window_info anchor="right" id="Flutter Outline" order="3" weight="0.32936507" />
<window_info anchor="bottom" id="Logcat" order="11" />
<window_info anchor="bottom" id="Dependency Viewer" order="13" weight="0.32800853" />
<window_info anchor="bottom" id="Version Control" order="9" />
<window_info anchor="bottom" id="Terminal" order="10" sideWeight="0.4973545" visible="true" weight="0.27888888" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.18376623" />
<window_info anchor="bottom" id="Messages" order="12" weight="0.23777778" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info id="Image Layers" order="5" />
<window_info anchor="right" id="Palette&#9;" order="5" />
<window_info anchor="right" id="Theme Preview" order="7" />
<window_info id="Structure" order="1" weight="0.24969475" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="Find" order="1" weight="0.3290735" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
</layout-to-restore>
@ -667,13 +665,6 @@
<state relative-caret-position="-10645" />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="14" selection-start-line="2" selection-start-column="14" selection-end-line="2" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/ios/flutter_inappbrowser.podspec">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="240">
@ -682,6 +673,11 @@
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider editor-type-id="text-editor">
<state relative-caret-position="247">
<caret line="19" column="15" selection-start-line="19" selection-start-column="3" selection-end-line="19" selection-end-column="15" />
</state>
</provider>
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="2820">
@ -692,13 +688,13 @@
</second_editor>
</state>
</provider>
<provider editor-type-id="text-editor">
<state relative-caret-position="247">
<caret line="19" column="15" selection-start-line="19" selection-start-column="3" selection-end-line="19" selection-end-column="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="69" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="73" />
</state>
</provider>
<provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
<state split_layout="SPLIT">
<first_editor />
@ -707,11 +703,6 @@
</second_editor>
</state>
</provider>
<provider editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="69" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="73" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/android/settings.gradle">
<provider selected="true" editor-type-id="text-editor">
@ -730,13 +721,6 @@
<state />
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/android/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="262">
<caret line="34" column="5" selection-start-line="34" selection-start-column="5" selection-end-line="34" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/flutter/bin/cache/pkg/sky_engine/lib/core/string.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="173">
@ -744,17 +728,34 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<entry file="file://$PROJECT_DIR$/android/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="200">
<caret line="74" column="60" selection-start-line="74" selection-start-column="54" selection-end-line="74" selection-end-column="60" />
<state relative-caret-position="262">
<caret line="34" column="5" selection-start-line="34" selection-start-column="5" selection-end-line="34" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="30">
<caret line="2" column="14" selection-start-line="2" selection-start-column="14" selection-end-line="2" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/flutter_inappbrowser.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="358">
<caret line="262" column="75" selection-start-line="262" selection-start-column="75" selection-end-line="262" selection-end-column="75" />
<state relative-caret-position="315">
<caret line="246" column="71" selection-start-line="246" selection-start-column="71" selection-end-line="246" selection-end-column="71" />
<folding>
<element signature="e#814#834#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/example/lib/main.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="537">
<caret line="140" column="44" selection-start-line="140" selection-start-column="44" selection-end-line="140" selection-end-column="64" />
</state>
</provider>
</entry>

View File

@ -1,37 +1,28 @@
package com.pichillilorenzo.flutter_inappbrowser;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler;
import android.webkit.MimeTypeMap;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@ -278,28 +269,55 @@ public class InAppBrowserWebViewClient extends WebViewClient {
Request mRequest = new Request.Builder().url(url).build();
try {
long loadingTime = System.currentTimeMillis();
Response response = activity.httpClient.newCall(mRequest).execute();
loadingTime = System.currentTimeMillis() - loadingTime;
String reasonPhrase = response.message();
if (reasonPhrase.equals("")) {
reasonPhrase = statusCodeMapping.get(response.code());
Log.d(LOG_TAG, reasonPhrase);
}
reasonPhrase = (reasonPhrase.equals("") || reasonPhrase == null) ? "OK" : reasonPhrase;
Map<String, String> headers = new HashMap<String, String>();
Map<String, String> headersResponse = new HashMap<String, String>();
for (Map.Entry<String, List<String>> entry : response.headers().toMultimap().entrySet()) {
String value = "";
for (String val: entry.getValue()) {
value += (value == "") ? val : "; " + val;
}
headers.put(entry.getKey().toLowerCase(), value);
headersResponse.put(entry.getKey().toLowerCase(), value);
}
Map<String, String> headersRequest = new HashMap<String, String>();
for (Map.Entry<String, List<String>> entry : mRequest.headers().toMultimap().entrySet()) {
String value = "";
for (String val: entry.getValue()) {
value += (value == "") ? val : "; " + val;
}
headersRequest.put(entry.getKey().toLowerCase(), value);
}
Map<String, Object> obj = new HashMap<>();
Map<String, Object> res = new HashMap<>();
Map<String, Object> req = new HashMap<>();
obj.put("uuid", activity.uuid);
obj.put("url", url);
obj.put("statusCode", response.code());
obj.put("headers", headers);
byte[] dataBytes = response.body().bytes();
InputStream dataStream = new ByteArrayInputStream(dataBytes);
res.put("url", url);
res.put("statusCode", response.code());
res.put("headers", headersResponse);
res.put("loadingTime", loadingTime);
res.put("data", dataBytes);
req.put("url", url);
req.put("headers", headersRequest);
req.put("method", mRequest.method());
obj.put("response", res);
obj.put("request", req);
InAppBrowserFlutterPlugin.channel.invokeMethod("onLoadResource", obj);
@ -308,8 +326,8 @@ public class InAppBrowserWebViewClient extends WebViewClient {
response.header("content-encoding"),
response.code(),
reasonPhrase,
headers,
response.body().byteStream()
headersResponse,
dataStream
);
} catch (IOException e) {
e.printStackTrace();

View File

@ -72,10 +72,10 @@ class MyInAppBrowser extends InAppBrowser {
}
@override
void onLoadResource(String url, int statusCode, Map<String, String> headers) {
print("\n\n resource: $url\n\n");
print(statusCode);
print(headers);
void onLoadResource(WebResourceResponse response, WebResourceRequest request) {
print(response.loadingTime.toString() + "ms " + response.url);
if (response.headers["content-length"] != null)
print(response.headers["content-length"] + " length");
}
@override
@ -138,7 +138,7 @@ class _MyAppState extends State<MyApp> {
body: new Center(
child: new RaisedButton(onPressed: () {
//chromeSafariBrowser.open("https://flutter.io/");
inAppBrowserFallback.open("https://flutter.io/", options: {
inAppBrowserFallback.open(url: "https://flutter.io/", options: {
//"hidden": true,
//"toolbarTopFixedTitle": "Fixed title",
//"useShouldOverrideUrlLoading": true

View File

@ -131,13 +131,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
override func viewDidLoad() {
super.viewDidLoad()
URLProtocol.wk_registerScheme("http")
URLProtocol.wk_registerScheme("https")
MyURLProtocol.URLProtocolDelegate = self
URLProtocol.registerClass(MyURLProtocol.self)
MyURLProtocol.wkWebViewDelegateMap[uuid] = self
webView.uiDelegate = self
webView.navigationDelegate = self
@ -303,8 +298,21 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
if ((browserOptions?.userAgent)! != "") {
if #available(iOS 9.0, *) {
self.webView.customUserAgent = (browserOptions?.userAgent)!
} else {
// Fallback on earlier versions
}
}
// set uuid in the User-Agent in order to know which webview is making internal requests and
// to send the onLoadResource event to the correct webview
if #available(iOS 9.0, *) {
if (self.webView.customUserAgent != nil) {
self.webView.customUserAgent = self.webView.customUserAgent! + " WKWebView/" + self.uuid
}
else {
self.webView.evaluateJavaScript("navigator.userAgent") { [weak webView] (result, error) in
if let webView = self.webView, let userAgent = result as? String {
webView.customUserAgent = userAgent + " WKWebView/" + self.uuid
}
}
}
}
@ -491,7 +499,6 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
func webView(_ webView: WKWebView,
decidePolicyFor navigationResponse: WKNavigationResponse,
decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
//dump((navigationResponse.response as! HTTPURLResponse))
//print(navigationResponse.response.mimeType)
//print(navigationResponse.response.url)
@ -569,8 +576,8 @@ class InAppBrowserWebViewController: UIViewController, WKUIDelegate, WKNavigatio
navigationDelegate?.onLoadError(uuid: self.uuid, webView: webView, error: error)
}
func didReceiveResponse(_ response: URLResponse, from request: URLRequest?) {
navigationDelegate?.onLoadResource(uuid: self.uuid, webView: webView, response: response)
func didReceiveResponse(_ response: URLResponse, fromRequest request: URLRequest?, withData data: Data, loadingTime time: Int) {
navigationDelegate?.onLoadResource(uuid: self.uuid, webView: webView, response: response, fromRequest: request, withData: data, loadingTime: time)
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

View File

@ -6,29 +6,47 @@
//
import Foundation
import WebKit
func currentTimeInMilliSeconds() -> Int {
let currentDate = Date()
let since1970 = currentDate.timeIntervalSince1970
return Int(since1970 * 1000)
}
class MyURLProtocol: URLProtocol {
struct Constants {
static let RequestHandledKey = "URLProtocolRequestHandled"
}
// struct Constants {
// static let RequestHandledKey = "URLProtocolRequestHandled"
// }
var wkWebViewUuid: String?
var session: URLSession?
var sessionTask: URLSessionDataTask?
static var URLProtocolDelegate: MyURLProtocolDelegate?
var response: URLResponse?
var data: Data?
static var wkWebViewDelegateMap: [String: MyURLProtocolDelegate] = [:]
var loadingTime: Int = 0
override init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
super.init(request: request, cachedResponse: cachedResponse, client: client)
if session == nil {
self.wkWebViewUuid = MyURLProtocol.getUuid(request)
if session == nil && self.wkWebViewUuid != nil {
session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
}
override class func canInit(with request: URLRequest) -> Bool {
if MyURLProtocol.property(forKey: Constants.RequestHandledKey, in: request) != nil {
if getUuid(request) == nil {
return false
}
// if MyURLProtocol.property(forKey: Constants.RequestHandledKey, in: request) != nil {
// return false
// }
return true
}
@ -38,25 +56,54 @@ class MyURLProtocol: URLProtocol {
override func startLoading() {
let newRequest = ((request as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
MyURLProtocol.setProperty(true, forKey: Constants.RequestHandledKey, in: newRequest)
loadingTime = currentTimeInMilliSeconds()
//MyURLProtocol.setProperty(true, forKey: Constants.RequestHandledKey, in: newRequest)
sessionTask = session?.dataTask(with: newRequest as URLRequest)
sessionTask?.resume()
}
override func stopLoading() {
if let uuid = self.wkWebViewUuid {
if MyURLProtocol.wkWebViewDelegateMap[uuid] != nil && self.response != nil {
loadingTime = currentTimeInMilliSeconds() - loadingTime
if self.data == nil {
self.data = Data()
}
MyURLProtocol.wkWebViewDelegateMap[uuid]!.didReceiveResponse(self.response!, fromRequest: request, withData: self.data!, loadingTime: loadingTime)
}
}
sessionTask?.cancel()
}
class func getUuid(_ request: URLRequest?) -> String? {
let userAgent: String? = request?.allHTTPHeaderFields?["User-Agent"]
var uuid: String? = nil
if userAgent != nil {
if userAgent!.contains("WKWebView/") {
let userAgentSplitted = userAgent!.split(separator: " ")
uuid = String(userAgentSplitted[userAgentSplitted.count-1]).replacingOccurrences(of: "WKWebView/", with: "")
}
}
return uuid
}
}
extension MyURLProtocol: URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if self.data == nil {
self.data = data
}
else {
self.data!.append(data)
}
client?.urlProtocol(self, didLoad: data)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
let policy = URLCache.StoragePolicy(rawValue: request.cachePolicy.rawValue) ?? .notAllowed
self.response = response
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: policy)
MyURLProtocol.URLProtocolDelegate?.didReceiveResponse(response, from: dataTask.currentRequest)
completionHandler(.allow)
}
@ -98,5 +145,5 @@ extension MyURLProtocol: URLSessionDataDelegate {
}
protocol MyURLProtocolDelegate {
func didReceiveResponse(_ response: URLResponse, from request: URLRequest?)
func didReceiveResponse(_ response: URLResponse, fromRequest request: URLRequest?, withData data: Data, loadingTime time: Int)
}

View File

@ -46,6 +46,9 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
public static func register(with registrar: FlutterPluginRegistrar) {
URLProtocol.wk_registerScheme("http")
URLProtocol.wk_registerScheme("https")
URLProtocol.registerClass(MyURLProtocol.self)
let channel = FlutterMethodChannel(name: "com.pichillilorenzo/flutter_inappbrowser", binaryMessenger: registrar.messenger())
let instance = SwiftFlutterPlugin(with: registrar)
registrar.addMethodCallDelegate(instance, channel: channel)
@ -489,16 +492,28 @@ public class SwiftFlutterPlugin: NSObject, FlutterPlugin {
}
}
func onLoadResource(uuid: String, webView: WKWebView, response: URLResponse) {
func onLoadResource(uuid: String, webView: WKWebView, response: URLResponse, fromRequest request: URLRequest?, withData data: Data, loadingTime time: Int) {
if self.webViewControllers[uuid] != nil {
var headers = (response as! HTTPURLResponse).allHeaderFields as! [String: String]
headers.lowercaseKeys()
var headersResponse = (response as! HTTPURLResponse).allHeaderFields as! [String: String]
headersResponse.lowercaseKeys()
var headersRequest = request!.allHTTPHeaderFields! as [String: String]
headersRequest.lowercaseKeys()
let arguments: [String : Any] = [
"uuid": uuid,
"url": response.url?.absoluteString ?? "",
"statusCode": (response as! HTTPURLResponse).statusCode,
"headers": headers
"response": [
"url": response.url!.absoluteString,
"statusCode": (response as! HTTPURLResponse).statusCode,
"headers": headersResponse,
"loadingTime": time,
"data": data
],
"request": [
"url": request!.url!.absoluteString,
"headers": headersRequest,
"method": request!.httpMethod!
]
]
channel.invokeMethod("onLoadResource", arguments: arguments)
}

View File

@ -21,6 +21,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:uuid/uuid.dart';
@ -34,6 +35,28 @@ enum ConsoleMessageLevel {
DEBUG, ERROR, LOG, TIP, WARNING
}
class WebResourceRequest {
String url;
Map<String, String> headers;
String method;
WebResourceRequest(this.url, this.headers, this.method);
}
class WebResourceResponse {
String url;
Map<String, String> headers;
int statusCode;
int loadingTime;
Uint8List data;
WebResourceResponse(this.url, this.headers, this.statusCode, this.loadingTime, this.data);
}
///Public class representing a JavaScript console message from WebCore.
///This could be a issued by a call to one of the console logging functions (e.g. console.log('...')) or a JavaScript error on the page.
///
@ -107,10 +130,27 @@ class InAppBrowser {
shouldOverrideUrlLoading(url);
break;
case "onLoadResource":
String url = call.arguments["url"];
int statusCode = call.arguments["statusCode"];
Map<dynamic, dynamic> headers = call.arguments["headers"];
onLoadResource(url, statusCode, headers.cast<String, String>());
Map<dynamic, dynamic> rawResponse = call.arguments["response"];
rawResponse = rawResponse.cast<String, dynamic>();
Map<dynamic, dynamic> rawRequest = call.arguments["request"];
rawRequest = rawRequest.cast<String, dynamic>();
String urlResponse = rawResponse["url"];
Map<dynamic, dynamic> headersResponse = rawResponse["headers"];
headersResponse = headersResponse.cast<String, String>();
int statusCode = rawResponse["statusCode"];
int loadingTime = rawResponse["loadingTime"];
Uint8List data = rawResponse["data"];
String urlRequest = rawRequest["url"];
Map<dynamic, dynamic> headersRequest = rawRequest["headers"];
headersRequest = headersResponse.cast<String, String>();
String method = rawRequest["method"];
var response = new WebResourceResponse(urlResponse, headersResponse, statusCode, loadingTime, data);
var request = new WebResourceRequest(urlRequest, headersRequest, method);
onLoadResource(response, request);
break;
case "onConsoleMessage":
String sourceURL = call.arguments["sourceURL"];
@ -187,7 +227,7 @@ 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, {Map<String, String> headers = const {}, String target = "_self", Map<String, dynamic> options = const {}}) async {
Future<void> open({String url = "about:blank", Map<String, String> headers = const {}, String target = "_self", Map<String, dynamic> options = const {}}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('uuid', () => uuid);
args.putIfAbsent('url', () => url);
@ -328,8 +368,8 @@ class InAppBrowser {
}
///Event fires when the [InAppBrowser] webview will load the resource specified by the given [url].
void onLoadResource(String url, int statusCode, Map<String, String> headers) {
///Event fires when the [InAppBrowser] webview will load the resource specified by the given [WebResourceRequest].
void onLoadResource(WebResourceResponse response, WebResourceRequest request) {
}

View File

@ -1,6 +1,6 @@
name: flutter_inappbrowser
description: A Flutter plugin that allows you to open an in-app browser window. (inspired by the popular cordova-plugin-inappbrowser).
version: 0.2.1
version: 0.3.0
author: Lorenzo Pichilli <pichillilorenzo@gmail.com>
homepage: https://github.com/pichillilorenzo/flutter_inappbrowser