@capacitor/android 6.0.0-rc.0 → 6.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/capacitor/src/main/assets/native-bridge.js +61 -20
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +9 -1
- package/capacitor/src/main/java/com/getcapacitor/JSInjector.java +7 -2
- package/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +131 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +18 -9
- package/capacitor/src/main/java/com/getcapacitor/plugin/WebView.java +7 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/HttpRequestHandler.java +25 -16
- package/package.json +2 -2
|
@@ -111,13 +111,9 @@ var nativeBridge = (function (exports) {
|
|
|
111
111
|
}
|
|
112
112
|
else if (body instanceof FormData) {
|
|
113
113
|
const formData = await convertFormData(body);
|
|
114
|
-
const boundary = `${Date.now()}`;
|
|
115
114
|
return {
|
|
116
115
|
data: formData,
|
|
117
116
|
type: 'formData',
|
|
118
|
-
headers: {
|
|
119
|
-
'Content-Type': `multipart/form-data; boundary=--${boundary}`,
|
|
120
|
-
},
|
|
121
117
|
};
|
|
122
118
|
}
|
|
123
119
|
else if (body instanceof File) {
|
|
@@ -130,6 +126,26 @@ var nativeBridge = (function (exports) {
|
|
|
130
126
|
}
|
|
131
127
|
return { data: body, type: 'json' };
|
|
132
128
|
};
|
|
129
|
+
const CAPACITOR_HTTP_INTERCEPTOR = '/_capacitor_http_interceptor_';
|
|
130
|
+
const CAPACITOR_HTTPS_INTERCEPTOR = '/_capacitor_https_interceptor_';
|
|
131
|
+
// TODO: export as Cap function
|
|
132
|
+
const isRelativeOrProxyUrl = (url) => !url ||
|
|
133
|
+
!(url.startsWith('http:') || url.startsWith('https:')) ||
|
|
134
|
+
url.indexOf(CAPACITOR_HTTP_INTERCEPTOR) > -1 ||
|
|
135
|
+
url.indexOf(CAPACITOR_HTTPS_INTERCEPTOR) > -1;
|
|
136
|
+
// TODO: export as Cap function
|
|
137
|
+
const createProxyUrl = (url, win) => {
|
|
138
|
+
var _a, _b;
|
|
139
|
+
if (isRelativeOrProxyUrl(url))
|
|
140
|
+
return url;
|
|
141
|
+
const proxyUrl = new URL(url);
|
|
142
|
+
const bridgeUrl = new URL((_b = (_a = win.Capacitor) === null || _a === void 0 ? void 0 : _a.getServerUrl()) !== null && _b !== void 0 ? _b : '');
|
|
143
|
+
const isHttps = proxyUrl.protocol === 'https:';
|
|
144
|
+
bridgeUrl.search = proxyUrl.search;
|
|
145
|
+
bridgeUrl.hash = proxyUrl.hash;
|
|
146
|
+
bridgeUrl.pathname = `${isHttps ? CAPACITOR_HTTPS_INTERCEPTOR : CAPACITOR_HTTP_INTERCEPTOR}/${encodeURIComponent(proxyUrl.host)}${proxyUrl.pathname}`;
|
|
147
|
+
return bridgeUrl.toString();
|
|
148
|
+
};
|
|
133
149
|
const initBridge = (w) => {
|
|
134
150
|
const getPlatformId = (win) => {
|
|
135
151
|
var _a, _b;
|
|
@@ -279,6 +295,10 @@ var nativeBridge = (function (exports) {
|
|
|
279
295
|
callback(result.path);
|
|
280
296
|
});
|
|
281
297
|
};
|
|
298
|
+
IonicWebView.setServerAssetPath = (path) => {
|
|
299
|
+
var _a;
|
|
300
|
+
(_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerAssetPath({ path });
|
|
301
|
+
};
|
|
282
302
|
IonicWebView.setServerBasePath = (path) => {
|
|
283
303
|
var _a;
|
|
284
304
|
(_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerBasePath({ path });
|
|
@@ -355,15 +375,15 @@ var nativeBridge = (function (exports) {
|
|
|
355
375
|
typeof c.dir === 'function');
|
|
356
376
|
};
|
|
357
377
|
const serializeConsoleMessage = (msg) => {
|
|
358
|
-
|
|
359
|
-
|
|
378
|
+
try {
|
|
379
|
+
if (typeof msg === 'object') {
|
|
360
380
|
msg = JSON.stringify(msg);
|
|
361
381
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
382
|
+
return String(msg);
|
|
383
|
+
}
|
|
384
|
+
catch (e) {
|
|
385
|
+
return '';
|
|
365
386
|
}
|
|
366
|
-
return String(msg);
|
|
367
387
|
};
|
|
368
388
|
const platform = getPlatformId(win);
|
|
369
389
|
if (platform == 'android' || platform == 'ios') {
|
|
@@ -472,6 +492,19 @@ var nativeBridge = (function (exports) {
|
|
|
472
492
|
if (request.url.startsWith(`${cap.getServerUrl()}/`)) {
|
|
473
493
|
return win.CapacitorWebFetch(resource, options);
|
|
474
494
|
}
|
|
495
|
+
if (!(options === null || options === void 0 ? void 0 : options.method) ||
|
|
496
|
+
options.method.toLocaleUpperCase() === 'GET' ||
|
|
497
|
+
options.method.toLocaleUpperCase() === 'HEAD' ||
|
|
498
|
+
options.method.toLocaleUpperCase() === 'OPTIONS' ||
|
|
499
|
+
options.method.toLocaleUpperCase() === 'TRACE') {
|
|
500
|
+
if (typeof resource === 'string') {
|
|
501
|
+
return await win.CapacitorWebFetch(createProxyUrl(resource, win), options);
|
|
502
|
+
}
|
|
503
|
+
else if (resource instanceof Request) {
|
|
504
|
+
const modifiedRequest = new Request(createProxyUrl(resource.url, win), resource);
|
|
505
|
+
return await win.CapacitorWebFetch(modifiedRequest, options);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
475
508
|
const tag = `CapacitorHttp fetch ${Date.now()} ${resource}`;
|
|
476
509
|
console.time(tag);
|
|
477
510
|
try {
|
|
@@ -541,12 +574,11 @@ var nativeBridge = (function (exports) {
|
|
|
541
574
|
});
|
|
542
575
|
xhr.readyState = 0;
|
|
543
576
|
const prototype = win.CapacitorWebXMLHttpRequest.prototype;
|
|
544
|
-
const isRelativeURL = (url) => !url || !(url.startsWith('http:') || url.startsWith('https:'));
|
|
545
577
|
const isProgressEventAvailable = () => typeof ProgressEvent !== 'undefined' &&
|
|
546
578
|
ProgressEvent.prototype instanceof Event;
|
|
547
579
|
// XHR patch abort
|
|
548
580
|
prototype.abort = function () {
|
|
549
|
-
if (
|
|
581
|
+
if (isRelativeOrProxyUrl(this._url)) {
|
|
550
582
|
return win.CapacitorWebXMLHttpRequest.abort.call(this);
|
|
551
583
|
}
|
|
552
584
|
this.readyState = 0;
|
|
@@ -557,10 +589,18 @@ var nativeBridge = (function (exports) {
|
|
|
557
589
|
};
|
|
558
590
|
// XHR patch open
|
|
559
591
|
prototype.open = function (method, url) {
|
|
592
|
+
this._method = method.toLocaleUpperCase();
|
|
560
593
|
this._url = url;
|
|
561
|
-
this._method
|
|
562
|
-
|
|
563
|
-
|
|
594
|
+
if (!this._method ||
|
|
595
|
+
this._method === 'GET' ||
|
|
596
|
+
this._method === 'HEAD' ||
|
|
597
|
+
this._method === 'OPTIONS' ||
|
|
598
|
+
this._method === 'TRACE') {
|
|
599
|
+
if (isRelativeOrProxyUrl(url)) {
|
|
600
|
+
return win.CapacitorWebXMLHttpRequest.open.call(this, method, url);
|
|
601
|
+
}
|
|
602
|
+
this._url = createProxyUrl(this._url, win);
|
|
603
|
+
return win.CapacitorWebXMLHttpRequest.open.call(this, method, this._url);
|
|
564
604
|
}
|
|
565
605
|
setTimeout(() => {
|
|
566
606
|
this.dispatchEvent(new Event('loadstart'));
|
|
@@ -569,14 +609,14 @@ var nativeBridge = (function (exports) {
|
|
|
569
609
|
};
|
|
570
610
|
// XHR patch set request header
|
|
571
611
|
prototype.setRequestHeader = function (header, value) {
|
|
572
|
-
if (
|
|
612
|
+
if (isRelativeOrProxyUrl(this._url)) {
|
|
573
613
|
return win.CapacitorWebXMLHttpRequest.setRequestHeader.call(this, header, value);
|
|
574
614
|
}
|
|
575
615
|
this._headers[header] = value;
|
|
576
616
|
};
|
|
577
617
|
// XHR patch send
|
|
578
618
|
prototype.send = function (body) {
|
|
579
|
-
if (
|
|
619
|
+
if (isRelativeOrProxyUrl(this._url)) {
|
|
580
620
|
return win.CapacitorWebXMLHttpRequest.send.call(this, body);
|
|
581
621
|
}
|
|
582
622
|
const tag = `CapacitorHttp XMLHttpRequest ${Date.now()} ${this._url}`;
|
|
@@ -638,7 +678,8 @@ var nativeBridge = (function (exports) {
|
|
|
638
678
|
else {
|
|
639
679
|
this.response = nativeResponse.data;
|
|
640
680
|
}
|
|
641
|
-
this.responseText = ((_a = nativeResponse.headers['Content-Type']
|
|
681
|
+
this.responseText = ((_a = (nativeResponse.headers['Content-Type'] ||
|
|
682
|
+
nativeResponse.headers['content-type'])) === null || _a === void 0 ? void 0 : _a.startsWith('application/json'))
|
|
642
683
|
? JSON.stringify(nativeResponse.data)
|
|
643
684
|
: nativeResponse.data;
|
|
644
685
|
this.responseURL = nativeResponse.url;
|
|
@@ -695,7 +736,7 @@ var nativeBridge = (function (exports) {
|
|
|
695
736
|
};
|
|
696
737
|
// XHR patch getAllResponseHeaders
|
|
697
738
|
prototype.getAllResponseHeaders = function () {
|
|
698
|
-
if (
|
|
739
|
+
if (isRelativeOrProxyUrl(this._url)) {
|
|
699
740
|
return win.CapacitorWebXMLHttpRequest.getAllResponseHeaders.call(this);
|
|
700
741
|
}
|
|
701
742
|
let returnString = '';
|
|
@@ -708,7 +749,7 @@ var nativeBridge = (function (exports) {
|
|
|
708
749
|
};
|
|
709
750
|
// XHR patch getResponseHeader
|
|
710
751
|
prototype.getResponseHeader = function (name) {
|
|
711
|
-
if (
|
|
752
|
+
if (isRelativeOrProxyUrl(this._url)) {
|
|
712
753
|
return win.CapacitorWebXMLHttpRequest.getResponseHeader.call(this, name);
|
|
713
754
|
}
|
|
714
755
|
return this._headers[name];
|
|
@@ -91,6 +91,9 @@ public class Bridge {
|
|
|
91
91
|
public static final String CAPACITOR_HTTPS_SCHEME = "https";
|
|
92
92
|
public static final String CAPACITOR_FILE_START = "/_capacitor_file_";
|
|
93
93
|
public static final String CAPACITOR_CONTENT_START = "/_capacitor_content_";
|
|
94
|
+
public static final String CAPACITOR_HTTP_INTERCEPTOR_START = "/_capacitor_http_interceptor_";
|
|
95
|
+
public static final String CAPACITOR_HTTPS_INTERCEPTOR_START = "/_capacitor_https_interceptor_";
|
|
96
|
+
|
|
94
97
|
public static final int DEFAULT_ANDROID_WEBVIEW_VERSION = 60;
|
|
95
98
|
public static final int MINIMUM_ANDROID_WEBVIEW_VERSION = 55;
|
|
96
99
|
public static final int DEFAULT_HUAWEI_WEBVIEW_VERSION = 10;
|
|
@@ -251,7 +254,12 @@ public class Bridge {
|
|
|
251
254
|
// Start the local web server
|
|
252
255
|
JSInjector injector = getJSInjector();
|
|
253
256
|
if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) {
|
|
254
|
-
|
|
257
|
+
String allowedOrigin = appUrl;
|
|
258
|
+
Uri appUri = Uri.parse(appUrl);
|
|
259
|
+
if (appUri.getPath() != null) {
|
|
260
|
+
allowedOrigin = appUri.toString().replace(appUri.getPath(), "");
|
|
261
|
+
}
|
|
262
|
+
WebViewCompat.addDocumentStartJavaScript(webView, injector.getScriptString(), Collections.singleton(allowedOrigin));
|
|
255
263
|
injector = null;
|
|
256
264
|
}
|
|
257
265
|
localServer = new WebViewLocalServer(context, this, injector, authorities, html5mode);
|
|
@@ -71,10 +71,15 @@ class JSInjector {
|
|
|
71
71
|
public InputStream getInjectedStream(InputStream responseStream) {
|
|
72
72
|
String js = "<script type=\"text/javascript\">" + getScriptString() + "</script>";
|
|
73
73
|
String html = this.readAssetStream(responseStream);
|
|
74
|
+
|
|
75
|
+
// Insert the js string at the position after <head> or before </head> using StringBuilder
|
|
76
|
+
StringBuilder modifiedHtml = new StringBuilder(html);
|
|
74
77
|
if (html.contains("<head>")) {
|
|
75
|
-
html
|
|
78
|
+
modifiedHtml.insert(html.indexOf("<head>") + "<head>".length(), "\n" + js + "\n");
|
|
79
|
+
html = modifiedHtml.toString();
|
|
76
80
|
} else if (html.contains("</head>")) {
|
|
77
|
-
html
|
|
81
|
+
modifiedHtml.insert(html.indexOf("</head>"), "\n" + js + "\n");
|
|
82
|
+
html = modifiedHtml.toString();
|
|
78
83
|
} else {
|
|
79
84
|
Logger.error("Unable to inject Capacitor, Plugins won't work");
|
|
80
85
|
}
|
|
@@ -15,20 +15,26 @@ limitations under the License.
|
|
|
15
15
|
*/
|
|
16
16
|
package com.getcapacitor;
|
|
17
17
|
|
|
18
|
+
import static com.getcapacitor.plugin.util.HttpRequestHandler.isDomainExcludedFromSSL;
|
|
19
|
+
|
|
18
20
|
import android.content.Context;
|
|
19
21
|
import android.net.Uri;
|
|
20
22
|
import android.util.Base64;
|
|
21
23
|
import android.webkit.CookieManager;
|
|
22
24
|
import android.webkit.WebResourceRequest;
|
|
23
25
|
import android.webkit.WebResourceResponse;
|
|
26
|
+
import com.getcapacitor.plugin.util.CapacitorHttpUrlConnection;
|
|
27
|
+
import com.getcapacitor.plugin.util.HttpRequestHandler;
|
|
24
28
|
import java.io.IOException;
|
|
25
29
|
import java.io.InputStream;
|
|
26
30
|
import java.net.HttpURLConnection;
|
|
27
31
|
import java.net.URL;
|
|
28
32
|
import java.net.URLConnection;
|
|
33
|
+
import java.net.URLDecoder;
|
|
29
34
|
import java.nio.charset.StandardCharsets;
|
|
30
35
|
import java.util.ArrayList;
|
|
31
36
|
import java.util.HashMap;
|
|
37
|
+
import java.util.LinkedHashMap;
|
|
32
38
|
import java.util.List;
|
|
33
39
|
import java.util.Map;
|
|
34
40
|
|
|
@@ -165,6 +171,23 @@ public class WebViewLocalServer {
|
|
|
165
171
|
*/
|
|
166
172
|
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
|
|
167
173
|
Uri loadingUrl = request.getUrl();
|
|
174
|
+
|
|
175
|
+
if (
|
|
176
|
+
null != loadingUrl.getPath() &&
|
|
177
|
+
(
|
|
178
|
+
loadingUrl.getPath().startsWith(Bridge.CAPACITOR_HTTP_INTERCEPTOR_START) ||
|
|
179
|
+
loadingUrl.getPath().startsWith(Bridge.CAPACITOR_HTTPS_INTERCEPTOR_START)
|
|
180
|
+
)
|
|
181
|
+
) {
|
|
182
|
+
Logger.debug("Handling CapacitorHttp request: " + loadingUrl);
|
|
183
|
+
try {
|
|
184
|
+
return handleCapacitorHttpRequest(request);
|
|
185
|
+
} catch (Exception e) {
|
|
186
|
+
Logger.error(e.getLocalizedMessage());
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
168
191
|
PathHandler handler;
|
|
169
192
|
synchronized (uriMatcher) {
|
|
170
193
|
handler = (PathHandler) uriMatcher.match(request.getUrl());
|
|
@@ -199,6 +222,114 @@ public class WebViewLocalServer {
|
|
|
199
222
|
return !(bridge.getServerUrl() == null && !bridge.getAppAllowNavigationMask().matches(loadingUrl.getHost()));
|
|
200
223
|
}
|
|
201
224
|
|
|
225
|
+
private String getReasonPhraseFromResponseCode(int code) {
|
|
226
|
+
return switch (code) {
|
|
227
|
+
case 100 -> "Continue";
|
|
228
|
+
case 101 -> "Switching Protocols";
|
|
229
|
+
case 200 -> "OK";
|
|
230
|
+
case 201 -> "Created";
|
|
231
|
+
case 202 -> "Accepted";
|
|
232
|
+
case 203 -> "Non-Authoritative Information";
|
|
233
|
+
case 204 -> "No Content";
|
|
234
|
+
case 205 -> "Reset Content";
|
|
235
|
+
case 206 -> "Partial Content";
|
|
236
|
+
case 300 -> "Multiple Choices";
|
|
237
|
+
case 301 -> "Moved Permanently";
|
|
238
|
+
case 302 -> "Found";
|
|
239
|
+
case 303 -> "See Other";
|
|
240
|
+
case 304 -> "Not Modified";
|
|
241
|
+
case 400 -> "Bad Request";
|
|
242
|
+
case 401 -> "Unauthorized";
|
|
243
|
+
case 403 -> "Forbidden";
|
|
244
|
+
case 404 -> "Not Found";
|
|
245
|
+
case 405 -> "Method Not Allowed";
|
|
246
|
+
case 406 -> "Not Acceptable";
|
|
247
|
+
case 407 -> "Proxy Authentication Required";
|
|
248
|
+
case 408 -> "Request Timeout";
|
|
249
|
+
case 409 -> "Conflict";
|
|
250
|
+
case 410 -> "Gone";
|
|
251
|
+
case 500 -> "Internal Server Error";
|
|
252
|
+
case 501 -> "Not Implemented";
|
|
253
|
+
case 502 -> "Bad Gateway";
|
|
254
|
+
case 503 -> "Service Unavailable";
|
|
255
|
+
case 504 -> "Gateway Timeout";
|
|
256
|
+
case 505 -> "HTTP Version Not Supported";
|
|
257
|
+
default -> "Unknown";
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private WebResourceResponse handleCapacitorHttpRequest(WebResourceRequest request) throws IOException {
|
|
262
|
+
boolean isHttps =
|
|
263
|
+
request.getUrl().getPath() != null && request.getUrl().getPath().startsWith(Bridge.CAPACITOR_HTTPS_INTERCEPTOR_START);
|
|
264
|
+
|
|
265
|
+
String urlString = request
|
|
266
|
+
.getUrl()
|
|
267
|
+
.toString()
|
|
268
|
+
.replace(bridge.getLocalUrl(), isHttps ? "https:/" : "http:/")
|
|
269
|
+
.replace(Bridge.CAPACITOR_HTTP_INTERCEPTOR_START, "")
|
|
270
|
+
.replace(Bridge.CAPACITOR_HTTPS_INTERCEPTOR_START, "");
|
|
271
|
+
urlString = URLDecoder.decode(urlString, "UTF-8");
|
|
272
|
+
URL url = new URL(urlString);
|
|
273
|
+
JSObject headers = new JSObject();
|
|
274
|
+
|
|
275
|
+
for (Map.Entry<String, String> header : request.getRequestHeaders().entrySet()) {
|
|
276
|
+
headers.put(header.getKey(), header.getValue());
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
HttpRequestHandler.HttpURLConnectionBuilder connectionBuilder = new HttpRequestHandler.HttpURLConnectionBuilder()
|
|
280
|
+
.setUrl(url)
|
|
281
|
+
.setMethod(request.getMethod())
|
|
282
|
+
.setHeaders(headers)
|
|
283
|
+
.openConnection();
|
|
284
|
+
|
|
285
|
+
CapacitorHttpUrlConnection connection = connectionBuilder.build();
|
|
286
|
+
|
|
287
|
+
if (!isDomainExcludedFromSSL(bridge, url)) {
|
|
288
|
+
connection.setSSLSocketFactory(bridge);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
connection.connect();
|
|
292
|
+
|
|
293
|
+
String mimeType = null;
|
|
294
|
+
String encoding = null;
|
|
295
|
+
Map<String, String> responseHeaders = new LinkedHashMap<>();
|
|
296
|
+
for (Map.Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) {
|
|
297
|
+
StringBuilder builder = new StringBuilder();
|
|
298
|
+
for (String value : entry.getValue()) {
|
|
299
|
+
builder.append(value);
|
|
300
|
+
builder.append(", ");
|
|
301
|
+
}
|
|
302
|
+
builder.setLength(builder.length() - 2);
|
|
303
|
+
|
|
304
|
+
if ("Content-Type".equalsIgnoreCase(entry.getKey())) {
|
|
305
|
+
String[] contentTypeParts = builder.toString().split(";");
|
|
306
|
+
mimeType = contentTypeParts[0].trim();
|
|
307
|
+
if (contentTypeParts.length > 1) {
|
|
308
|
+
String[] encodingParts = contentTypeParts[1].split("=");
|
|
309
|
+
if (encodingParts.length > 1) {
|
|
310
|
+
encoding = encodingParts[1].trim();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
responseHeaders.put(entry.getKey(), builder.toString());
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
InputStream inputStream = connection.getErrorStream();
|
|
319
|
+
if (inputStream == null) {
|
|
320
|
+
inputStream = connection.getInputStream();
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (null == mimeType) {
|
|
324
|
+
mimeType = getMimeType(request.getUrl().getPath(), inputStream);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
int responseCode = connection.getResponseCode();
|
|
328
|
+
String reasonPhrase = getReasonPhraseFromResponseCode(responseCode);
|
|
329
|
+
|
|
330
|
+
return new WebResourceResponse(mimeType, encoding, responseCode, reasonPhrase, responseHeaders, inputStream);
|
|
331
|
+
}
|
|
332
|
+
|
|
202
333
|
private WebResourceResponse handleLocalRequest(WebResourceRequest request, PathHandler handler) {
|
|
203
334
|
String path = request.getUrl().getPath();
|
|
204
335
|
|
|
@@ -24,7 +24,7 @@ import java.util.concurrent.Executors;
|
|
|
24
24
|
)
|
|
25
25
|
public class CapacitorHttp extends Plugin {
|
|
26
26
|
|
|
27
|
-
private Map<Runnable, PluginCall> activeRequests = new HashMap<>();
|
|
27
|
+
private final Map<Runnable, PluginCall> activeRequests = new HashMap<>();
|
|
28
28
|
private final ExecutorService executor = Executors.newCachedThreadPool();
|
|
29
29
|
|
|
30
30
|
@Override
|
|
@@ -59,17 +59,26 @@ public class CapacitorHttp extends Plugin {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
private void http(final PluginCall call, final String httpMethod) {
|
|
62
|
-
Runnable asyncHttpCall = ()
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
Runnable asyncHttpCall = new Runnable() {
|
|
63
|
+
@Override
|
|
64
|
+
public void run() {
|
|
65
|
+
try {
|
|
66
|
+
JSObject response = HttpRequestHandler.request(call, httpMethod, getBridge());
|
|
67
|
+
call.resolve(response);
|
|
68
|
+
} catch (Exception e) {
|
|
69
|
+
call.reject(e.getLocalizedMessage(), e.getClass().getSimpleName(), e);
|
|
70
|
+
} finally {
|
|
71
|
+
activeRequests.remove(this);
|
|
72
|
+
}
|
|
68
73
|
}
|
|
69
74
|
};
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
if (!executor.isShutdown()) {
|
|
77
|
+
activeRequests.put(asyncHttpCall, call);
|
|
78
|
+
executor.submit(asyncHttpCall);
|
|
79
|
+
} else {
|
|
80
|
+
call.reject("Failed to execute request - Http Plugin was shutdown");
|
|
81
|
+
}
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
@JavascriptInterface
|
|
@@ -14,6 +14,13 @@ public class WebView extends Plugin {
|
|
|
14
14
|
public static final String WEBVIEW_PREFS_NAME = "CapWebViewSettings";
|
|
15
15
|
public static final String CAP_SERVER_PATH = "serverBasePath";
|
|
16
16
|
|
|
17
|
+
@PluginMethod
|
|
18
|
+
public void setServerAssetPath(PluginCall call) {
|
|
19
|
+
String path = call.getString("path");
|
|
20
|
+
bridge.setServerAssetPath(path);
|
|
21
|
+
call.resolve();
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
@PluginMethod
|
|
18
25
|
public void setServerBasePath(PluginCall call) {
|
|
19
26
|
String path = call.getString("path");
|
|
@@ -12,12 +12,14 @@ import java.io.ByteArrayOutputStream;
|
|
|
12
12
|
import java.io.IOException;
|
|
13
13
|
import java.io.InputStream;
|
|
14
14
|
import java.io.InputStreamReader;
|
|
15
|
+
import java.io.UnsupportedEncodingException;
|
|
15
16
|
import java.lang.reflect.Method;
|
|
16
17
|
import java.net.HttpURLConnection;
|
|
17
18
|
import java.net.MalformedURLException;
|
|
18
19
|
import java.net.URI;
|
|
19
20
|
import java.net.URISyntaxException;
|
|
20
21
|
import java.net.URL;
|
|
22
|
+
import java.net.URLEncoder;
|
|
21
23
|
import java.util.Iterator;
|
|
22
24
|
import java.util.List;
|
|
23
25
|
import java.util.Locale;
|
|
@@ -141,7 +143,7 @@ public class HttpRequestHandler {
|
|
|
141
143
|
StringBuilder value = new StringBuilder();
|
|
142
144
|
JSONArray arr = params.getJSONArray(key);
|
|
143
145
|
for (int x = 0; x < arr.length(); x++) {
|
|
144
|
-
|
|
146
|
+
this.addUrlParam(value, key, arr.getString(x), shouldEncode);
|
|
145
147
|
if (x != arr.length() - 1) {
|
|
146
148
|
value.append("&");
|
|
147
149
|
}
|
|
@@ -154,30 +156,37 @@ public class HttpRequestHandler {
|
|
|
154
156
|
if (urlQueryBuilder.length() > 0) {
|
|
155
157
|
urlQueryBuilder.append("&");
|
|
156
158
|
}
|
|
157
|
-
|
|
159
|
+
this.addUrlParam(urlQueryBuilder, key, params.getString(key), shouldEncode);
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
String urlQuery = urlQueryBuilder.toString();
|
|
162
164
|
|
|
163
165
|
URI uri = url.toURI();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
uri.getPath() +
|
|
173
|
-
((!urlQuery.equals("")) ? "?" + urlQuery : "") +
|
|
174
|
-
((uri.getFragment() != null) ? uri.getFragment() : "");
|
|
175
|
-
this.url = new URL(unEncodedUrlString);
|
|
176
|
-
}
|
|
166
|
+
String unEncodedUrlString =
|
|
167
|
+
uri.getScheme() +
|
|
168
|
+
"://" +
|
|
169
|
+
uri.getAuthority() +
|
|
170
|
+
uri.getPath() +
|
|
171
|
+
((!urlQuery.equals("")) ? "?" + urlQuery : "") +
|
|
172
|
+
((uri.getFragment() != null) ? uri.getFragment() : "");
|
|
173
|
+
this.url = new URL(unEncodedUrlString);
|
|
177
174
|
|
|
178
175
|
return this;
|
|
179
176
|
}
|
|
180
177
|
|
|
178
|
+
private static void addUrlParam(StringBuilder sb, String key, String value, boolean shouldEncode) {
|
|
179
|
+
if (shouldEncode) {
|
|
180
|
+
try {
|
|
181
|
+
key = URLEncoder.encode(key, "UTF-8");
|
|
182
|
+
value = URLEncoder.encode(value, "UTF-8");
|
|
183
|
+
} catch (UnsupportedEncodingException ex) {
|
|
184
|
+
throw new RuntimeException(ex.getCause());
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
sb.append(key).append("=").append(value);
|
|
188
|
+
}
|
|
189
|
+
|
|
181
190
|
public CapacitorHttpUrlConnection build() {
|
|
182
191
|
return connection;
|
|
183
192
|
}
|
|
@@ -426,7 +435,7 @@ public class HttpRequestHandler {
|
|
|
426
435
|
return response;
|
|
427
436
|
}
|
|
428
437
|
|
|
429
|
-
|
|
438
|
+
public static Boolean isDomainExcludedFromSSL(Bridge bridge, URL url) {
|
|
430
439
|
try {
|
|
431
440
|
Class<?> sslPinningImpl = Class.forName("io.ionic.sslpinning.SSLPinning");
|
|
432
441
|
Method method = sslPinningImpl.getDeclaredMethod("isDomainExcluded", Bridge.class, URL.class);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/android",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.2",
|
|
4
4
|
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capacitorjs.com",
|
|
6
6
|
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"verify": "./gradlew clean lint build test -b capacitor/build.gradle"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@capacitor/core": "^6.0.0-rc.
|
|
26
|
+
"@capacitor/core": "^6.0.0-rc.2"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|