@capgo/inappbrowser 7.10.10 → 7.11.1
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.
|
@@ -24,6 +24,8 @@ import android.print.PrintAttributes;
|
|
|
24
24
|
import android.print.PrintDocumentAdapter;
|
|
25
25
|
import android.print.PrintManager;
|
|
26
26
|
import android.provider.MediaStore;
|
|
27
|
+
import android.security.KeyChain;
|
|
28
|
+
import android.security.KeyChainAliasCallback;
|
|
27
29
|
import android.text.TextUtils;
|
|
28
30
|
import android.util.Base64;
|
|
29
31
|
import android.util.Log;
|
|
@@ -65,6 +67,8 @@ import java.io.InputStream;
|
|
|
65
67
|
import java.net.URI;
|
|
66
68
|
import java.net.URISyntaxException;
|
|
67
69
|
import java.nio.charset.StandardCharsets;
|
|
70
|
+
import java.security.PrivateKey;
|
|
71
|
+
import java.security.cert.X509Certificate;
|
|
68
72
|
import java.util.Arrays;
|
|
69
73
|
import java.util.HashMap;
|
|
70
74
|
import java.util.Iterator;
|
|
@@ -186,19 +190,7 @@ public class WebViewDialog extends Dialog {
|
|
|
186
190
|
|
|
187
191
|
activity.runOnUiThread(() -> {
|
|
188
192
|
try {
|
|
189
|
-
String currentUrl =
|
|
190
|
-
if (_webView != null) {
|
|
191
|
-
try {
|
|
192
|
-
currentUrl = _webView.getUrl();
|
|
193
|
-
if (currentUrl == null) {
|
|
194
|
-
currentUrl = "";
|
|
195
|
-
}
|
|
196
|
-
} catch (Exception e) {
|
|
197
|
-
Log.e("InAppBrowser", "Error getting URL: " + e.getMessage());
|
|
198
|
-
currentUrl = "";
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
193
|
+
String currentUrl = getUrl();
|
|
202
194
|
dismiss();
|
|
203
195
|
|
|
204
196
|
if (_options != null && _options.getCallbacks() != null) {
|
|
@@ -444,11 +436,7 @@ public class WebViewDialog extends Dialog {
|
|
|
444
436
|
// DEBUG: Log details about the file chooser request
|
|
445
437
|
Log.d("InAppBrowser", "onShowFileChooser called");
|
|
446
438
|
Log.d("InAppBrowser", "Accept type: " + acceptType);
|
|
447
|
-
Log.d(
|
|
448
|
-
"InAppBrowser",
|
|
449
|
-
"Current URL: " +
|
|
450
|
-
(webView.getUrl() != null ? webView.getUrl() : "null")
|
|
451
|
-
);
|
|
439
|
+
Log.d("InAppBrowser", "Current URL: " + getUrl());
|
|
452
440
|
Log.d(
|
|
453
441
|
"InAppBrowser",
|
|
454
442
|
"Original URL: " +
|
|
@@ -477,7 +465,7 @@ public class WebViewDialog extends Dialog {
|
|
|
477
465
|
// Direct check for capture attribute in URL (fallback method)
|
|
478
466
|
boolean isCaptureInUrl;
|
|
479
467
|
String captureMode;
|
|
480
|
-
String currentUrl =
|
|
468
|
+
String currentUrl = getUrl();
|
|
481
469
|
|
|
482
470
|
// Look for capture in URL parameters - sometimes the attribute shows up in URL
|
|
483
471
|
if (currentUrl != null && currentUrl.contains("capture=")) {
|
|
@@ -512,43 +500,48 @@ public class WebViewDialog extends Dialog {
|
|
|
512
500
|
|
|
513
501
|
// Fixed JavaScript with proper error handling
|
|
514
502
|
String js =
|
|
515
|
-
"
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
503
|
+
"""
|
|
504
|
+
try {
|
|
505
|
+
(function() {
|
|
506
|
+
var captureAttr = null;
|
|
507
|
+
// Check active element first
|
|
508
|
+
if (document.activeElement &&
|
|
509
|
+
document.activeElement.tagName === 'INPUT' &&
|
|
510
|
+
document.activeElement.type === 'file') {
|
|
511
|
+
if (document.activeElement.hasAttribute('capture')) {
|
|
512
|
+
captureAttr = document.activeElement.getAttribute('capture') || 'environment';
|
|
513
|
+
return captureAttr;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// Try to find any input with capture attribute
|
|
517
|
+
var inputs = document.querySelectorAll('input[type="file"][capture]');
|
|
518
|
+
if (inputs && inputs.length > 0) {
|
|
519
|
+
captureAttr = inputs[0].getAttribute('capture') || 'environment';
|
|
520
|
+
return captureAttr;
|
|
521
|
+
}
|
|
522
|
+
// Try to extract from HTML attributes
|
|
523
|
+
var allInputs = document.getElementsByTagName('input');
|
|
524
|
+
for (var i = 0; i < allInputs.length; i++) {
|
|
525
|
+
var input = allInputs[i];
|
|
526
|
+
if (input.type === 'file') {
|
|
527
|
+
if (input.hasAttribute('capture')) {
|
|
528
|
+
captureAttr = input.getAttribute('capture') || 'environment';
|
|
529
|
+
return captureAttr;
|
|
530
|
+
}
|
|
531
|
+
// Look for the accept attribute containing image/* as this might be a camera input
|
|
532
|
+
var acceptAttr = input.getAttribute('accept');
|
|
533
|
+
if (acceptAttr && acceptAttr.indexOf('image/*') >= 0) {
|
|
534
|
+
console.log('Found input with image/* accept');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return '';
|
|
539
|
+
})();
|
|
540
|
+
} catch(e) {
|
|
541
|
+
console.error('Capture detection error:', e);
|
|
542
|
+
return '';
|
|
543
|
+
}
|
|
544
|
+
""";
|
|
552
545
|
|
|
553
546
|
webView.evaluateJavascript(js, value -> {
|
|
554
547
|
Log.d("InAppBrowser", "Capture attribute JS result: " + value);
|
|
@@ -1462,7 +1455,7 @@ public class WebViewDialog extends Dialog {
|
|
|
1462
1455
|
_webView.stopLoading();
|
|
1463
1456
|
|
|
1464
1457
|
// Check if there's a URL to reload
|
|
1465
|
-
String currentUrl =
|
|
1458
|
+
String currentUrl = getUrl();
|
|
1466
1459
|
if (currentUrl != null && !currentUrl.equals("about:blank")) {
|
|
1467
1460
|
// Reload the current page
|
|
1468
1461
|
_webView.reload();
|
|
@@ -1486,7 +1479,16 @@ public class WebViewDialog extends Dialog {
|
|
|
1486
1479
|
}
|
|
1487
1480
|
|
|
1488
1481
|
public String getUrl() {
|
|
1489
|
-
|
|
1482
|
+
try {
|
|
1483
|
+
WebView webView = _webView;
|
|
1484
|
+
if (webView != null) {
|
|
1485
|
+
String url = webView.getUrl();
|
|
1486
|
+
return url != null ? url : "";
|
|
1487
|
+
}
|
|
1488
|
+
} catch (Exception e) {
|
|
1489
|
+
Log.w("InAppBrowser", "Error getting URL: " + e.getMessage());
|
|
1490
|
+
}
|
|
1491
|
+
return "";
|
|
1490
1492
|
}
|
|
1491
1493
|
|
|
1492
1494
|
public void executeScript(String script) {
|
|
@@ -1628,9 +1630,7 @@ public class WebViewDialog extends Dialog {
|
|
|
1628
1630
|
new OnClickListener() {
|
|
1629
1631
|
public void onClick(DialogInterface dialog, int which) {
|
|
1630
1632
|
// Close button clicked, do something
|
|
1631
|
-
String currentUrl =
|
|
1632
|
-
? _webView.getUrl()
|
|
1633
|
-
: "";
|
|
1633
|
+
String currentUrl = getUrl();
|
|
1634
1634
|
dismiss();
|
|
1635
1635
|
if (_options != null && _options.getCallbacks() != null) {
|
|
1636
1636
|
_options.getCallbacks().closeEvent(currentUrl);
|
|
@@ -1641,7 +1641,7 @@ public class WebViewDialog extends Dialog {
|
|
|
1641
1641
|
.setNegativeButton(_options.getCloseModalCancel(), null)
|
|
1642
1642
|
.show();
|
|
1643
1643
|
} else {
|
|
1644
|
-
String currentUrl =
|
|
1644
|
+
String currentUrl = getUrl();
|
|
1645
1645
|
dismiss();
|
|
1646
1646
|
if (_options != null && _options.getCallbacks() != null) {
|
|
1647
1647
|
_options.getCallbacks().closeEvent(currentUrl);
|
|
@@ -1671,7 +1671,7 @@ public class WebViewDialog extends Dialog {
|
|
|
1671
1671
|
_webView.stopLoading();
|
|
1672
1672
|
|
|
1673
1673
|
// Check if there's a URL to reload
|
|
1674
|
-
String currentUrl =
|
|
1674
|
+
String currentUrl = getUrl();
|
|
1675
1675
|
if (currentUrl != null) {
|
|
1676
1676
|
// Reload the current page
|
|
1677
1677
|
_webView.reload();
|
|
@@ -2153,6 +2153,109 @@ public class WebViewDialog extends Dialog {
|
|
|
2153
2153
|
return false;
|
|
2154
2154
|
}
|
|
2155
2155
|
|
|
2156
|
+
@Override
|
|
2157
|
+
public void onReceivedClientCertRequest(
|
|
2158
|
+
WebView view,
|
|
2159
|
+
android.webkit.ClientCertRequest request
|
|
2160
|
+
) {
|
|
2161
|
+
Log.i("InAppBrowser", "onReceivedClientCertRequest CALLED");
|
|
2162
|
+
|
|
2163
|
+
if (request == null) {
|
|
2164
|
+
Log.e("InAppBrowser", "ClientCertRequest is null");
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
if (activity == null) {
|
|
2169
|
+
Log.e("InAppBrowser", "Activity is null, canceling request");
|
|
2170
|
+
try {
|
|
2171
|
+
request.cancel();
|
|
2172
|
+
} catch (Exception e) {
|
|
2173
|
+
Log.e(
|
|
2174
|
+
"InAppBrowser",
|
|
2175
|
+
"Error canceling request: " + e.getMessage()
|
|
2176
|
+
);
|
|
2177
|
+
}
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
try {
|
|
2182
|
+
Log.i("InAppBrowser", "Host: " + request.getHost());
|
|
2183
|
+
Log.i("InAppBrowser", "Port: " + request.getPort());
|
|
2184
|
+
Log.i(
|
|
2185
|
+
"InAppBrowser",
|
|
2186
|
+
"Principals: " +
|
|
2187
|
+
java.util.Arrays.toString(request.getPrincipals())
|
|
2188
|
+
);
|
|
2189
|
+
Log.i(
|
|
2190
|
+
"InAppBrowser",
|
|
2191
|
+
"KeyTypes: " + java.util.Arrays.toString(request.getKeyTypes())
|
|
2192
|
+
);
|
|
2193
|
+
|
|
2194
|
+
KeyChain.choosePrivateKeyAlias(
|
|
2195
|
+
activity,
|
|
2196
|
+
new KeyChainAliasCallback() {
|
|
2197
|
+
@Override
|
|
2198
|
+
public void alias(String alias) {
|
|
2199
|
+
if (alias != null) {
|
|
2200
|
+
try {
|
|
2201
|
+
PrivateKey privateKey = KeyChain.getPrivateKey(
|
|
2202
|
+
activity,
|
|
2203
|
+
alias
|
|
2204
|
+
);
|
|
2205
|
+
X509Certificate[] certChain =
|
|
2206
|
+
KeyChain.getCertificateChain(activity, alias);
|
|
2207
|
+
request.proceed(privateKey, certChain);
|
|
2208
|
+
Log.i("InAppBrowser", "Selected certificate: " + alias);
|
|
2209
|
+
} catch (Exception e) {
|
|
2210
|
+
try {
|
|
2211
|
+
request.cancel();
|
|
2212
|
+
} catch (Exception cancelEx) {
|
|
2213
|
+
Log.e(
|
|
2214
|
+
"InAppBrowser",
|
|
2215
|
+
"Error canceling request: " + cancelEx.getMessage()
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
Log.e(
|
|
2219
|
+
"InAppBrowser",
|
|
2220
|
+
"Error selecting certificate: " + e.getMessage()
|
|
2221
|
+
);
|
|
2222
|
+
}
|
|
2223
|
+
} else {
|
|
2224
|
+
try {
|
|
2225
|
+
request.cancel();
|
|
2226
|
+
} catch (Exception e) {
|
|
2227
|
+
Log.e(
|
|
2228
|
+
"InAppBrowser",
|
|
2229
|
+
"Error canceling request: " + e.getMessage()
|
|
2230
|
+
);
|
|
2231
|
+
}
|
|
2232
|
+
Log.i("InAppBrowser", "No certificate found");
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
},
|
|
2236
|
+
null, // keyTypes
|
|
2237
|
+
null, // issuers
|
|
2238
|
+
request.getHost(),
|
|
2239
|
+
request.getPort(),
|
|
2240
|
+
null // alias (null = system asks user to choose)
|
|
2241
|
+
);
|
|
2242
|
+
} catch (Exception e) {
|
|
2243
|
+
Log.e(
|
|
2244
|
+
"InAppBrowser",
|
|
2245
|
+
"Error in onReceivedClientCertRequest: " + e.getMessage()
|
|
2246
|
+
);
|
|
2247
|
+
try {
|
|
2248
|
+
request.cancel();
|
|
2249
|
+
} catch (Exception cancelEx) {
|
|
2250
|
+
Log.e(
|
|
2251
|
+
"InAppBrowser",
|
|
2252
|
+
"Error canceling request after exception: " +
|
|
2253
|
+
cancelEx.getMessage()
|
|
2254
|
+
);
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2156
2259
|
private String randomRequestId() {
|
|
2157
2260
|
return UUID.randomUUID().toString();
|
|
2158
2261
|
}
|
|
@@ -2567,7 +2670,7 @@ public class WebViewDialog extends Dialog {
|
|
|
2567
2670
|
) {
|
|
2568
2671
|
_webView.goBack();
|
|
2569
2672
|
} else if (!_options.getDisableGoBackOnNativeApplication()) {
|
|
2570
|
-
String currentUrl =
|
|
2673
|
+
String currentUrl = getUrl();
|
|
2571
2674
|
_options.getCallbacks().closeEvent(currentUrl);
|
|
2572
2675
|
if (_webView != null) {
|
|
2573
2676
|
_webView.destroy();
|
|
@@ -443,11 +443,20 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
443
443
|
|
|
444
444
|
// Method to send a message from Swift to JavaScript
|
|
445
445
|
open func postMessageToJS(message: [String: Any]) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
446
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: message, options: []),
|
|
447
|
+
let jsonString = String(data: jsonData, encoding: .utf8) else {
|
|
448
|
+
print("[InAppBrowser] Failed to serialize message to JSON")
|
|
449
|
+
return
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Safely build the script to avoid any potential issues
|
|
453
|
+
let script = "window.dispatchEvent(new CustomEvent('messageFromNative', { detail: \(jsonString) }));"
|
|
454
|
+
|
|
455
|
+
DispatchQueue.main.async {
|
|
456
|
+
self.webView?.evaluateJavaScript(script) { result, error in
|
|
457
|
+
if let error = error {
|
|
458
|
+
print("[InAppBrowser] JavaScript evaluation error in postMessageToJS: \(error)")
|
|
459
|
+
}
|
|
451
460
|
}
|
|
452
461
|
}
|
|
453
462
|
}
|
|
@@ -1339,20 +1348,25 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
1339
1348
|
return
|
|
1340
1349
|
}
|
|
1341
1350
|
|
|
1342
|
-
//
|
|
1343
|
-
let
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1351
|
+
// Safely construct script template with proper escaping
|
|
1352
|
+
let userScript = self.preShowScript ?? ""
|
|
1353
|
+
|
|
1354
|
+
// Build script using safe concatenation to avoid multi-line string issues
|
|
1355
|
+
let scriptTemplate = [
|
|
1356
|
+
"async function preShowFunction() {",
|
|
1357
|
+
userScript,
|
|
1358
|
+
"}",
|
|
1359
|
+
"preShowFunction().then(",
|
|
1360
|
+
" () => window.webkit.messageHandlers.preShowScriptSuccess.postMessage({})",
|
|
1361
|
+
").catch(",
|
|
1362
|
+
" err => {",
|
|
1363
|
+
" console.error('Preshow error', err);",
|
|
1364
|
+
" window.webkit.messageHandlers.preShowScriptError.postMessage(JSON.stringify(err, Object.getOwnPropertyNames(err)));",
|
|
1365
|
+
" }",
|
|
1366
|
+
")"
|
|
1367
|
+
]
|
|
1368
|
+
|
|
1369
|
+
let script = scriptTemplate.joined(separator: "\n")
|
|
1356
1370
|
print("[InAppBrowser - InjectPreShowScript] PreShowScript script: \(script)")
|
|
1357
1371
|
|
|
1358
1372
|
self.preShowSemaphore = DispatchSemaphore(value: 0)
|