@capgo/capacitor-inappbrowser 8.6.17 → 8.6.19
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/android/src/main/java/ee/forgr/capacitor_inappbrowser/CapgoInAppBrowserPlugin.java +1820 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +3 -1806
- package/dist/esm/index.js +20 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/plugin.cjs.js +19 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +19 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +10 -7
- package/ios/Sources/InAppBrowserPlugin/ProxySchemeHandler.swift +2 -2
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +1 -1
- package/package.json +1 -1
|
@@ -1,59 +1,12 @@
|
|
|
1
1
|
package ee.forgr.capacitor_inappbrowser;
|
|
2
2
|
|
|
3
3
|
import android.Manifest;
|
|
4
|
-
import android.app.Activity;
|
|
5
|
-
import android.content.ComponentName;
|
|
6
|
-
import android.content.Intent;
|
|
7
|
-
import android.content.pm.PackageManager;
|
|
8
|
-
import android.content.pm.ResolveInfo;
|
|
9
|
-
import android.graphics.Bitmap;
|
|
10
|
-
import android.graphics.BitmapFactory;
|
|
11
|
-
import android.graphics.Canvas;
|
|
12
|
-
import android.graphics.Color;
|
|
13
|
-
import android.graphics.drawable.Drawable;
|
|
14
|
-
import android.net.Uri;
|
|
15
|
-
import android.os.Bundle;
|
|
16
|
-
import android.os.Message;
|
|
17
|
-
import android.text.TextUtils;
|
|
18
|
-
import android.util.Log;
|
|
19
|
-
import android.webkit.CookieManager;
|
|
20
|
-
import android.webkit.PermissionRequest;
|
|
21
|
-
import android.webkit.WebView;
|
|
22
|
-
import androidx.activity.result.ActivityResult;
|
|
23
|
-
import androidx.activity.result.ActivityResultLauncher;
|
|
24
|
-
import androidx.activity.result.contract.ActivityResultContracts;
|
|
25
|
-
import androidx.annotation.NonNull;
|
|
26
|
-
import androidx.appcompat.content.res.AppCompatResources;
|
|
27
|
-
import androidx.browser.customtabs.CustomTabColorSchemeParams;
|
|
28
|
-
import androidx.browser.customtabs.CustomTabsCallback;
|
|
29
|
-
import androidx.browser.customtabs.CustomTabsClient;
|
|
30
|
-
import androidx.browser.customtabs.CustomTabsIntent;
|
|
31
|
-
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
|
32
|
-
import androidx.browser.customtabs.CustomTabsSession;
|
|
33
|
-
import androidx.core.content.ContextCompat;
|
|
34
|
-
import com.getcapacitor.JSArray;
|
|
35
|
-
import com.getcapacitor.JSObject;
|
|
36
|
-
import com.getcapacitor.Plugin;
|
|
37
|
-
import com.getcapacitor.PluginCall;
|
|
38
|
-
import com.getcapacitor.PluginMethod;
|
|
39
4
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
40
5
|
import com.getcapacitor.annotation.Permission;
|
|
41
|
-
import java.lang.reflect.Field;
|
|
42
|
-
import java.util.ArrayDeque;
|
|
43
|
-
import java.util.ArrayList;
|
|
44
|
-
import java.util.Deque;
|
|
45
|
-
import java.util.HashMap;
|
|
46
|
-
import java.util.Iterator;
|
|
47
|
-
import java.util.List;
|
|
48
|
-
import java.util.Map;
|
|
49
|
-
import java.util.UUID;
|
|
50
|
-
import java.util.regex.Pattern;
|
|
51
|
-
import java.util.regex.PatternSyntaxException;
|
|
52
|
-
import org.json.JSONException;
|
|
53
|
-
import org.json.JSONObject;
|
|
54
6
|
|
|
7
|
+
@Deprecated
|
|
55
8
|
@CapacitorPlugin(
|
|
56
|
-
name = "
|
|
9
|
+
name = "CapgoInAppBrowser",
|
|
57
10
|
permissions = {
|
|
58
11
|
@Permission(alias = "camera", strings = { Manifest.permission.CAMERA }),
|
|
59
12
|
@Permission(alias = "microphone", strings = { Manifest.permission.RECORD_AUDIO }),
|
|
@@ -61,1760 +14,4 @@ import org.json.JSONObject;
|
|
|
61
14
|
},
|
|
62
15
|
requestCodes = { WebViewDialog.FILE_CHOOSER_REQUEST_CODE }
|
|
63
16
|
)
|
|
64
|
-
public class InAppBrowserPlugin extends
|
|
65
|
-
|
|
66
|
-
private final String pluginVersion = "8.6.17";
|
|
67
|
-
|
|
68
|
-
public static final String CUSTOM_TAB_PACKAGE_NAME = "com.android.chrome"; // Change when in stable
|
|
69
|
-
private CustomTabsClient customTabsClient;
|
|
70
|
-
private CustomTabsSession currentSession;
|
|
71
|
-
private WebViewDialog webViewDialog = null;
|
|
72
|
-
private final Map<String, WebViewDialog> webViewDialogs = new HashMap<>();
|
|
73
|
-
private final Deque<String> webViewStack = new ArrayDeque<>();
|
|
74
|
-
private String activeWebViewId = null;
|
|
75
|
-
private String currentUrl = "";
|
|
76
|
-
|
|
77
|
-
private PermissionRequest currentPermissionRequest;
|
|
78
|
-
private boolean currentPermissionNeedsCamera = false;
|
|
79
|
-
private boolean currentPermissionNeedsMicrophone = false;
|
|
80
|
-
|
|
81
|
-
private ActivityResultLauncher<Intent> fileChooserLauncher;
|
|
82
|
-
private ActivityResultLauncher<String[]> webPermissionLauncher;
|
|
83
|
-
private PluginCall pendingCameraPermissionCall;
|
|
84
|
-
|
|
85
|
-
private PluginCall openSecureWindowSavedCall;
|
|
86
|
-
private String openSecureWindowRedirectUri;
|
|
87
|
-
|
|
88
|
-
@Override
|
|
89
|
-
public void load() {
|
|
90
|
-
super.load();
|
|
91
|
-
fileChooserLauncher = getActivity().registerForActivityResult(
|
|
92
|
-
new ActivityResultContracts.StartActivityForResult(),
|
|
93
|
-
this::handleFileChooserResult
|
|
94
|
-
);
|
|
95
|
-
webPermissionLauncher = getActivity().registerForActivityResult(
|
|
96
|
-
new ActivityResultContracts.RequestMultiplePermissions(),
|
|
97
|
-
this::handleWebPermissionResult
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private List<NativeProxyRule> parseProxyRules(JSArray rawRules, String optionName, PluginCall call) {
|
|
102
|
-
List<NativeProxyRule> parsed = new ArrayList<>();
|
|
103
|
-
if (rawRules == null) {
|
|
104
|
-
return parsed;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
for (int index = 0; index < rawRules.length(); index++) {
|
|
108
|
-
try {
|
|
109
|
-
JSONObject rule = rawRules.getJSONObject(index);
|
|
110
|
-
parsed.add(
|
|
111
|
-
new NativeProxyRule(
|
|
112
|
-
rule.optString("id", null),
|
|
113
|
-
NativeProxyRule.compilePattern(rule.optString("urlRegex", null)),
|
|
114
|
-
NativeProxyRule.compilePattern(rule.optString("methodRegex", null)),
|
|
115
|
-
NativeProxyRule.compilePattern(rule.optString("headerRegex", null)),
|
|
116
|
-
NativeProxyRule.compilePattern(rule.optString("bodyRegex", null)),
|
|
117
|
-
NativeProxyRule.compilePattern(rule.optString("statusRegex", null)),
|
|
118
|
-
NativeProxyRule.compilePattern(rule.optString("responseHeaderRegex", null)),
|
|
119
|
-
NativeProxyRule.compilePattern(rule.optString("responseBodyRegex", null)),
|
|
120
|
-
rule.optBoolean("mainFrameOnly", false),
|
|
121
|
-
NativeProxyRule.Action.fromString(rule.optString("action", "continue"))
|
|
122
|
-
)
|
|
123
|
-
);
|
|
124
|
-
} catch (JSONException | PatternSyntaxException error) {
|
|
125
|
-
call.reject("Invalid " + optionName + " at index " + index + ": " + error.getMessage());
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return parsed;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private WebViewCallbacks buildCallbacks(String webViewId) {
|
|
134
|
-
return new WebViewCallbacks() {
|
|
135
|
-
@Override
|
|
136
|
-
public void urlChangeEvent(String url) {
|
|
137
|
-
notifyListeners("urlChangeEvent", new JSObject().put("id", webViewId).put("url", url));
|
|
138
|
-
if (webViewId.equals(activeWebViewId)) {
|
|
139
|
-
currentUrl = url;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
@Override
|
|
144
|
-
public void closeEvent(String url) {
|
|
145
|
-
notifyListeners("closeEvent", new JSObject().put("id", webViewId).put("url", url));
|
|
146
|
-
unregisterWebView(webViewId);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@Override
|
|
150
|
-
public void pageLoaded() {
|
|
151
|
-
notifyListeners("browserPageLoaded", new JSObject().put("id", webViewId));
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
@Override
|
|
155
|
-
public void pageLoadError() {
|
|
156
|
-
notifyListeners("pageLoadError", new JSObject().put("id", webViewId));
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
@Override
|
|
160
|
-
public void customSchemeIntercepted(String url, boolean opened) {
|
|
161
|
-
notifyListeners("customSchemeIntercepted", new JSObject().put("id", webViewId).put("url", url).put("opened", opened));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
@Override
|
|
165
|
-
public void buttonNearDoneClicked() {
|
|
166
|
-
notifyListeners("buttonNearDoneClick", new JSObject().put("id", webViewId));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
@Override
|
|
170
|
-
public void confirmBtnClicked(String url) {
|
|
171
|
-
notifyListeners("confirmBtnClicked", new JSObject().put("id", webViewId).put("url", url));
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@Override
|
|
175
|
-
public void screenshotTaken(JSObject screenshot) {
|
|
176
|
-
JSObject event = new JSObject();
|
|
177
|
-
Iterator<String> keys = screenshot.keys();
|
|
178
|
-
while (keys.hasNext()) {
|
|
179
|
-
String key = keys.next();
|
|
180
|
-
event.put(key, screenshot.opt(key));
|
|
181
|
-
}
|
|
182
|
-
event.put("id", webViewId);
|
|
183
|
-
notifyListeners("screenshotTaken", event);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
@Override
|
|
187
|
-
public void downloadCompleted(
|
|
188
|
-
String sourceUrl,
|
|
189
|
-
String fileName,
|
|
190
|
-
String mimeType,
|
|
191
|
-
String path,
|
|
192
|
-
String localUrl,
|
|
193
|
-
String handledBy
|
|
194
|
-
) {
|
|
195
|
-
JSObject event = new JSObject();
|
|
196
|
-
event.put("id", webViewId);
|
|
197
|
-
if (sourceUrl != null) {
|
|
198
|
-
event.put("sourceUrl", sourceUrl);
|
|
199
|
-
}
|
|
200
|
-
event.put("fileName", fileName);
|
|
201
|
-
if (mimeType != null) {
|
|
202
|
-
event.put("mimeType", mimeType);
|
|
203
|
-
}
|
|
204
|
-
event.put("path", path);
|
|
205
|
-
event.put("localUrl", localUrl);
|
|
206
|
-
event.put("handledBy", handledBy);
|
|
207
|
-
notifyListeners("downloadCompleted", event);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
@Override
|
|
211
|
-
public void downloadFailed(String sourceUrl, String fileName, String mimeType, String error) {
|
|
212
|
-
JSObject event = new JSObject();
|
|
213
|
-
event.put("id", webViewId);
|
|
214
|
-
if (sourceUrl != null) {
|
|
215
|
-
event.put("sourceUrl", sourceUrl);
|
|
216
|
-
}
|
|
217
|
-
if (fileName != null) {
|
|
218
|
-
event.put("fileName", fileName);
|
|
219
|
-
}
|
|
220
|
-
if (mimeType != null) {
|
|
221
|
-
event.put("mimeType", mimeType);
|
|
222
|
-
}
|
|
223
|
-
event.put("error", error);
|
|
224
|
-
notifyListeners("downloadFailed", event);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
@Override
|
|
228
|
-
public void proxyRequestEvent(
|
|
229
|
-
String requestId,
|
|
230
|
-
String phase,
|
|
231
|
-
String url,
|
|
232
|
-
String method,
|
|
233
|
-
String headersJson,
|
|
234
|
-
String body,
|
|
235
|
-
Integer status,
|
|
236
|
-
String responseHeadersJson,
|
|
237
|
-
String responseBody,
|
|
238
|
-
String dialogWebViewId
|
|
239
|
-
) {
|
|
240
|
-
JSObject event = new JSObject();
|
|
241
|
-
event.put("requestId", requestId);
|
|
242
|
-
event.put("phase", phase);
|
|
243
|
-
event.put("url", url);
|
|
244
|
-
event.put("method", method);
|
|
245
|
-
try {
|
|
246
|
-
event.put("headers", new JSObject(headersJson));
|
|
247
|
-
} catch (Exception ignored) {
|
|
248
|
-
event.put("headers", new JSObject());
|
|
249
|
-
}
|
|
250
|
-
event.put("body", body);
|
|
251
|
-
if (status != null) {
|
|
252
|
-
event.put("status", status);
|
|
253
|
-
}
|
|
254
|
-
if (responseHeadersJson != null) {
|
|
255
|
-
try {
|
|
256
|
-
event.put("responseHeaders", new JSObject(responseHeadersJson));
|
|
257
|
-
} catch (Exception ignored) {
|
|
258
|
-
event.put("responseHeaders", new JSObject());
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
event.put("responseBody", responseBody);
|
|
262
|
-
event.put("webviewId", dialogWebViewId);
|
|
263
|
-
notifyListeners("proxyRequest", event);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
@Override
|
|
267
|
-
public void javascriptCallback(String message) {
|
|
268
|
-
Log.d("WebViewDialog", "Received message from JavaScript: " + message);
|
|
269
|
-
try {
|
|
270
|
-
JSONObject jsonMessage = new JSONObject(message);
|
|
271
|
-
JSObject jsObject = new JSObject();
|
|
272
|
-
Iterator<String> keys = jsonMessage.keys();
|
|
273
|
-
while (keys.hasNext()) {
|
|
274
|
-
String key = keys.next();
|
|
275
|
-
jsObject.put(key, jsonMessage.get(key));
|
|
276
|
-
}
|
|
277
|
-
jsObject.put("id", webViewId);
|
|
278
|
-
notifyListeners("messageFromWebview", jsObject);
|
|
279
|
-
} catch (JSONException e) {
|
|
280
|
-
Log.e("WebViewDialog", "Error parsing JSON message: " + e.getMessage());
|
|
281
|
-
JSObject jsObject = new JSObject();
|
|
282
|
-
jsObject.put("rawMessage", message);
|
|
283
|
-
jsObject.put("id", webViewId);
|
|
284
|
-
notifyListeners("messageFromWebview", jsObject);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
@Override
|
|
289
|
-
public void consoleMessage(String level, String message, String source, Integer line, Integer column) {
|
|
290
|
-
notifyListeners("consoleMessage", ConsoleMessageEventHelper.create(webViewId, level, message, source, line, column));
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
private WebViewDialog createManagedDialog(String webViewId, Options options) {
|
|
296
|
-
return createManagedDialog(webViewId, options, true);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
private WebViewDialog createManagedDialog(String webViewId, Options options, boolean makeActive) {
|
|
300
|
-
WebViewDialog dialog = new WebViewDialog(
|
|
301
|
-
getContext(),
|
|
302
|
-
android.R.style.Theme_NoTitleBar,
|
|
303
|
-
options,
|
|
304
|
-
InAppBrowserPlugin.this,
|
|
305
|
-
getBridge().getWebView()
|
|
306
|
-
);
|
|
307
|
-
dialog.setInstanceId(webViewId);
|
|
308
|
-
dialog.activity = InAppBrowserPlugin.this.getActivity();
|
|
309
|
-
registerWebView(webViewId, dialog, makeActive);
|
|
310
|
-
return dialog;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private void notifyPopupWindowOpened(String popupId, String parentId, String popupUrl, boolean visible) {
|
|
314
|
-
JSObject event = new JSObject();
|
|
315
|
-
event.put("id", popupId);
|
|
316
|
-
if (parentId != null && !parentId.isEmpty()) {
|
|
317
|
-
event.put("parentId", parentId);
|
|
318
|
-
}
|
|
319
|
-
if (popupUrl != null && !popupUrl.isEmpty()) {
|
|
320
|
-
event.put("url", popupUrl);
|
|
321
|
-
}
|
|
322
|
-
event.put("visible", visible);
|
|
323
|
-
notifyListeners("popupWindowOpened", event);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
@Override
|
|
327
|
-
public boolean createManagedPopupWindow(WebViewDialog parentDialog, Message resultMsg, boolean isUserGesture, String popupUrl) {
|
|
328
|
-
if (resultMsg == null || !(resultMsg.obj instanceof WebView.WebViewTransport) || parentDialog == null) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
Options parentOptions = parentDialog.getOptions();
|
|
333
|
-
if (parentOptions == null) {
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
String popupWebViewId = UUID.randomUUID().toString();
|
|
338
|
-
Options popupOptions = parentOptions.copyForPopup();
|
|
339
|
-
popupOptions.setCallbacks(buildCallbacks(popupWebViewId));
|
|
340
|
-
popupOptions.setPluginCall(null);
|
|
341
|
-
|
|
342
|
-
boolean shouldActivatePopup = ActiveWebViewSupport.shouldActivateNewWebView(popupOptions.isHidden(), activeWebViewId != null);
|
|
343
|
-
WebViewDialog popupDialog = createManagedDialog(popupWebViewId, popupOptions, shouldActivatePopup);
|
|
344
|
-
if (popupOptions.isHidden()) {
|
|
345
|
-
popupDialog.setHidden(true);
|
|
346
|
-
}
|
|
347
|
-
popupDialog.presentWebView();
|
|
348
|
-
|
|
349
|
-
WebView popupWebView = popupDialog.getManagedWebView();
|
|
350
|
-
if (popupWebView == null) {
|
|
351
|
-
unregisterWebView(popupWebViewId);
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
|
356
|
-
transport.setWebView(popupWebView);
|
|
357
|
-
resultMsg.sendToTarget();
|
|
358
|
-
notifyPopupWindowOpened(popupWebViewId, parentDialog.getInstanceId(), popupUrl, !popupOptions.isHidden());
|
|
359
|
-
return true;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
private void registerWebView(String id, WebViewDialog dialog, boolean makeActive) {
|
|
363
|
-
webViewDialogs.put(id, dialog);
|
|
364
|
-
webViewStack.remove(id);
|
|
365
|
-
webViewStack.addLast(id);
|
|
366
|
-
if (makeActive || activeWebViewId == null || webViewDialog == null) {
|
|
367
|
-
setActiveWebView(id, dialog);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
private void setActiveWebView(String id, WebViewDialog dialog) {
|
|
372
|
-
activeWebViewId = id;
|
|
373
|
-
webViewDialog = dialog;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
private void unregisterWebView(String id) {
|
|
377
|
-
webViewDialogs.remove(id);
|
|
378
|
-
webViewStack.remove(id);
|
|
379
|
-
activeWebViewId = webViewStack.peekLast();
|
|
380
|
-
webViewDialog = activeWebViewId != null ? webViewDialogs.get(activeWebViewId) : null;
|
|
381
|
-
if (webViewDialog != null) {
|
|
382
|
-
String url = webViewDialog.getUrl();
|
|
383
|
-
if (url != null) {
|
|
384
|
-
currentUrl = url;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
private String resolveTargetId(PluginCall call) {
|
|
390
|
-
String id = call.getString("id");
|
|
391
|
-
return id != null ? id : activeWebViewId;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
private WebViewDialog resolveDialog(String id) {
|
|
395
|
-
if (id != null) {
|
|
396
|
-
return webViewDialogs.get(id);
|
|
397
|
-
}
|
|
398
|
-
if (activeWebViewId != null) {
|
|
399
|
-
WebViewDialog dialog = webViewDialogs.get(activeWebViewId);
|
|
400
|
-
if (dialog != null) {
|
|
401
|
-
return dialog;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return webViewDialog;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
private ArrayList<WebView> cacheWebViewsFor(String targetId) {
|
|
408
|
-
ArrayList<WebView> targetWebViews = new ArrayList<>();
|
|
409
|
-
if (targetId != null) {
|
|
410
|
-
WebViewDialog dialog = webViewDialogs.get(targetId);
|
|
411
|
-
if (dialog != null && dialog.getManagedWebView() != null) {
|
|
412
|
-
targetWebViews.add(dialog.getManagedWebView());
|
|
413
|
-
}
|
|
414
|
-
return targetWebViews;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
for (WebViewDialog dialog : webViewDialogs.values()) {
|
|
418
|
-
WebView managedWebView = dialog.getManagedWebView();
|
|
419
|
-
if (managedWebView != null) {
|
|
420
|
-
targetWebViews.add(managedWebView);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
if (targetWebViews.isEmpty() && getBridge() != null && getBridge().getWebView() != null) {
|
|
425
|
-
targetWebViews.add(getBridge().getWebView());
|
|
426
|
-
}
|
|
427
|
-
return targetWebViews;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
private WebViewDialog findFileChooserDialog() {
|
|
431
|
-
if (activeWebViewId != null) {
|
|
432
|
-
WebViewDialog dialog = webViewDialogs.get(activeWebViewId);
|
|
433
|
-
if (dialog != null && dialog.mFilePathCallback != null) {
|
|
434
|
-
return dialog;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (webViewDialog != null && webViewDialog.mFilePathCallback != null) {
|
|
439
|
-
return webViewDialog;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
for (WebViewDialog dialog : webViewDialogs.values()) {
|
|
443
|
-
if (dialog != null && dialog.mFilePathCallback != null) {
|
|
444
|
-
return dialog;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
private void handleFileChooserResult(ActivityResult result) {
|
|
452
|
-
WebViewDialog webViewDialog = findFileChooserDialog();
|
|
453
|
-
if (webViewDialog != null && webViewDialog.mFilePathCallback != null) {
|
|
454
|
-
Uri[] results = null;
|
|
455
|
-
Intent data = result.getData();
|
|
456
|
-
|
|
457
|
-
if (result.getResultCode() == Activity.RESULT_OK) {
|
|
458
|
-
// Handle camera capture result
|
|
459
|
-
if (webViewDialog.tempCameraUri != null && (data == null || data.getData() == null)) {
|
|
460
|
-
results = new Uri[] { webViewDialog.tempCameraUri };
|
|
461
|
-
}
|
|
462
|
-
// Handle regular file picker result
|
|
463
|
-
else if (data != null) {
|
|
464
|
-
if (data.getClipData() != null) {
|
|
465
|
-
// Handle multiple files
|
|
466
|
-
int count = data.getClipData().getItemCount();
|
|
467
|
-
results = new Uri[count];
|
|
468
|
-
for (int i = 0; i < count; i++) {
|
|
469
|
-
results[i] = data.getClipData().getItemAt(i).getUri();
|
|
470
|
-
}
|
|
471
|
-
} else if (data.getData() != null) {
|
|
472
|
-
// Handle single file
|
|
473
|
-
results = new Uri[] { data.getData() };
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Send the result to WebView and clean up
|
|
479
|
-
webViewDialog.mFilePathCallback.onReceiveValue(results);
|
|
480
|
-
webViewDialog.mFilePathCallback = null;
|
|
481
|
-
webViewDialog.tempCameraUri = null;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
public void handleMicrophonePermissionRequest(PermissionRequest request) {
|
|
486
|
-
if (request == null) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
handleWebPermissionRequest(
|
|
491
|
-
request,
|
|
492
|
-
WebViewPermissionSupport.hasResource(request.getResources(), PermissionRequest.RESOURCE_VIDEO_CAPTURE),
|
|
493
|
-
true
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
public void handleCameraPermissionRequest(PermissionRequest request) {
|
|
498
|
-
if (request == null) {
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
handleWebPermissionRequest(
|
|
503
|
-
request,
|
|
504
|
-
true,
|
|
505
|
-
WebViewPermissionSupport.hasResource(request.getResources(), PermissionRequest.RESOURCE_AUDIO_CAPTURE)
|
|
506
|
-
);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
private boolean isAndroidPermissionGranted(String permission) {
|
|
510
|
-
return ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
private void handleWebPermissionRequest(PermissionRequest request, boolean needsCamera, boolean needsMicrophone) {
|
|
514
|
-
if (request == null) {
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
if (!needsCamera && !needsMicrophone) {
|
|
519
|
-
request.deny();
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
if (currentPermissionRequest != null && currentPermissionRequest != request) {
|
|
524
|
-
try {
|
|
525
|
-
currentPermissionRequest.deny();
|
|
526
|
-
} catch (Exception e) {
|
|
527
|
-
Log.w(getLogTag(), "Could not deny previous WebView permission request: " + e.getMessage());
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
currentPermissionRequest = request;
|
|
532
|
-
currentPermissionNeedsCamera = needsCamera;
|
|
533
|
-
currentPermissionNeedsMicrophone = needsMicrophone;
|
|
534
|
-
|
|
535
|
-
String[] missingPermissions = WebViewPermissionSupport.missingAndroidPermissions(
|
|
536
|
-
needsCamera,
|
|
537
|
-
needsMicrophone,
|
|
538
|
-
isAndroidPermissionGranted(Manifest.permission.CAMERA),
|
|
539
|
-
isAndroidPermissionGranted(Manifest.permission.RECORD_AUDIO)
|
|
540
|
-
);
|
|
541
|
-
|
|
542
|
-
if (missingPermissions.length == 0) {
|
|
543
|
-
grantCurrentWebPermissionRequest();
|
|
544
|
-
} else if (webPermissionLauncher != null) {
|
|
545
|
-
webPermissionLauncher.launch(missingPermissions);
|
|
546
|
-
} else {
|
|
547
|
-
denyCurrentWebPermissionRequest();
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
private void handleWebPermissionResult(Map<String, Boolean> result) {
|
|
552
|
-
if (currentPermissionRequest != null) {
|
|
553
|
-
boolean cameraGranted = !currentPermissionNeedsCamera || isAndroidPermissionGranted(Manifest.permission.CAMERA);
|
|
554
|
-
boolean microphoneGranted = !currentPermissionNeedsMicrophone || isAndroidPermissionGranted(Manifest.permission.RECORD_AUDIO);
|
|
555
|
-
|
|
556
|
-
if (cameraGranted && microphoneGranted) {
|
|
557
|
-
grantCurrentWebPermissionRequest();
|
|
558
|
-
} else {
|
|
559
|
-
denyCurrentWebPermissionRequest();
|
|
560
|
-
}
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
if (pendingCameraPermissionCall != null) {
|
|
565
|
-
PluginCall call = pendingCameraPermissionCall;
|
|
566
|
-
pendingCameraPermissionCall = null;
|
|
567
|
-
if (isAndroidPermissionGranted(Manifest.permission.CAMERA)) {
|
|
568
|
-
call.resolve();
|
|
569
|
-
} else {
|
|
570
|
-
call.reject("Camera permission is required");
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
private void grantCurrentWebPermissionRequest() {
|
|
576
|
-
if (currentPermissionRequest != null) {
|
|
577
|
-
currentPermissionRequest.grant(
|
|
578
|
-
WebViewPermissionSupport.grantResources(currentPermissionNeedsCamera, currentPermissionNeedsMicrophone)
|
|
579
|
-
);
|
|
580
|
-
clearCurrentWebPermissionRequest();
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
private void denyCurrentWebPermissionRequest() {
|
|
585
|
-
if (currentPermissionRequest != null) {
|
|
586
|
-
currentPermissionRequest.deny();
|
|
587
|
-
clearCurrentWebPermissionRequest();
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
@Override
|
|
592
|
-
public void clearPendingPermissionRequest(PermissionRequest request) {
|
|
593
|
-
if (currentPermissionRequest == request) {
|
|
594
|
-
clearCurrentWebPermissionRequest();
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
private void clearCurrentWebPermissionRequest() {
|
|
599
|
-
currentPermissionRequest = null;
|
|
600
|
-
currentPermissionNeedsCamera = false;
|
|
601
|
-
currentPermissionNeedsMicrophone = false;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
|
|
605
|
-
@Override
|
|
606
|
-
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
|
|
607
|
-
customTabsClient = client;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
@Override
|
|
611
|
-
public void onServiceDisconnected(ComponentName name) {
|
|
612
|
-
customTabsClient = null;
|
|
613
|
-
}
|
|
614
|
-
};
|
|
615
|
-
|
|
616
|
-
@PluginMethod
|
|
617
|
-
public void requestCameraPermission(PluginCall call) {
|
|
618
|
-
if (isAndroidPermissionGranted(Manifest.permission.CAMERA)) {
|
|
619
|
-
call.resolve();
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
if (webPermissionLauncher == null) {
|
|
624
|
-
call.reject("Camera permission request is unavailable");
|
|
625
|
-
return;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
if (pendingCameraPermissionCall != null) {
|
|
629
|
-
pendingCameraPermissionCall.reject("Camera permission request was replaced");
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
pendingCameraPermissionCall = call;
|
|
633
|
-
webPermissionLauncher.launch(new String[] { Manifest.permission.CAMERA });
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
@PluginMethod
|
|
637
|
-
public void setUrl(PluginCall call) {
|
|
638
|
-
String url = call.getString("url");
|
|
639
|
-
if (url == null || TextUtils.isEmpty(url)) {
|
|
640
|
-
call.reject("Invalid URL");
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
String targetId = call.getString("id");
|
|
645
|
-
WebViewDialog webViewDialog = resolveDialog(targetId);
|
|
646
|
-
if (webViewDialog == null) {
|
|
647
|
-
call.reject("WebView is not initialized");
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
currentUrl = url;
|
|
652
|
-
this.getActivity().runOnUiThread(
|
|
653
|
-
new Runnable() {
|
|
654
|
-
@Override
|
|
655
|
-
public void run() {
|
|
656
|
-
try {
|
|
657
|
-
webViewDialog.setUrl(url);
|
|
658
|
-
call.resolve();
|
|
659
|
-
} catch (Exception e) {
|
|
660
|
-
Log.e("InAppBrowser", "Error setting URL: " + e.getMessage());
|
|
661
|
-
call.reject("Failed to set URL: " + e.getMessage());
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
@PluginMethod
|
|
669
|
-
public void open(PluginCall call) {
|
|
670
|
-
String url = call.getString("url");
|
|
671
|
-
if (url == null) {
|
|
672
|
-
call.reject("URL is required");
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// get the deeplink prevention, if provided
|
|
677
|
-
Boolean preventDeeplink = call.getBoolean("preventDeeplink", false);
|
|
678
|
-
Boolean isPresentAfterPageLoad = call.getBoolean("isPresentAfterPageLoad", false);
|
|
679
|
-
|
|
680
|
-
if (TextUtils.isEmpty(url)) {
|
|
681
|
-
call.reject("Invalid URL");
|
|
682
|
-
}
|
|
683
|
-
currentUrl = url;
|
|
684
|
-
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getCustomTabsSession());
|
|
685
|
-
|
|
686
|
-
// --- Chrome Custom Tab UI customization ---
|
|
687
|
-
|
|
688
|
-
// Toolbar color (applied to both light and dark color schemes)
|
|
689
|
-
String toolbarColor = call.getString("toolbarColor");
|
|
690
|
-
if (toolbarColor != null) {
|
|
691
|
-
try {
|
|
692
|
-
int colorInt = Color.parseColor(toolbarColor);
|
|
693
|
-
CustomTabColorSchemeParams colorParams = new CustomTabColorSchemeParams.Builder()
|
|
694
|
-
.setToolbarColor(colorInt)
|
|
695
|
-
.setNavigationBarColor(colorInt)
|
|
696
|
-
.build();
|
|
697
|
-
builder.setDefaultColorSchemeParams(colorParams);
|
|
698
|
-
builder.setColorSchemeParams(CustomTabsIntent.COLOR_SCHEME_DARK, colorParams);
|
|
699
|
-
} catch (IllegalArgumentException e) {
|
|
700
|
-
Log.w(getLogTag(), "Invalid toolbarColor value: " + toolbarColor, e);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Auto-hide URL bar on scroll
|
|
705
|
-
if (call.getBoolean("urlBarHidingEnabled", false)) {
|
|
706
|
-
builder.setUrlBarHidingEnabled(true);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
// Show page <title> instead of URL
|
|
710
|
-
if (call.getBoolean("showTitle", false)) {
|
|
711
|
-
builder.setShowTitle(true);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
// Replace X close icon with a back arrow
|
|
715
|
-
if (call.getBoolean("showArrow", false)) {
|
|
716
|
-
Drawable arrowDrawable = AppCompatResources.getDrawable(getContext(), R.drawable.arrow_back_enabled);
|
|
717
|
-
if (arrowDrawable != null) {
|
|
718
|
-
Bitmap backArrow = Bitmap.createBitmap(
|
|
719
|
-
arrowDrawable.getIntrinsicWidth(),
|
|
720
|
-
arrowDrawable.getIntrinsicHeight(),
|
|
721
|
-
Bitmap.Config.ARGB_8888
|
|
722
|
-
);
|
|
723
|
-
Canvas canvas = new Canvas(backArrow);
|
|
724
|
-
arrowDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
725
|
-
arrowDrawable.draw(canvas);
|
|
726
|
-
builder.setCloseButtonIcon(backArrow);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// Remove share action from overflow menu
|
|
731
|
-
if (call.getBoolean("disableShare", false)) {
|
|
732
|
-
builder.setShareState(CustomTabsIntent.SHARE_STATE_OFF);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
CustomTabsIntent tabsIntent = builder.build();
|
|
736
|
-
|
|
737
|
-
// Undocumented Chromium flags — these may stop working on future Chrome updates
|
|
738
|
-
if (call.getBoolean("disableBookmark", false)) {
|
|
739
|
-
tabsIntent.intent.putExtra("org.chromium.chrome.browser.customtabs.EXTRA_DISABLE_STAR_BUTTON", true);
|
|
740
|
-
}
|
|
741
|
-
if (call.getBoolean("disableDownload", false)) {
|
|
742
|
-
tabsIntent.intent.putExtra("org.chromium.chrome.browser.customtabs.EXTRA_DISABLE_DOWNLOAD_BUTTON", true);
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
tabsIntent.intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + getContext().getPackageName()));
|
|
746
|
-
tabsIntent.intent.putExtra(android.provider.Browser.EXTRA_HEADERS, this.getHeaders(call));
|
|
747
|
-
|
|
748
|
-
if (preventDeeplink != false) {
|
|
749
|
-
String browserPackageName = "";
|
|
750
|
-
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
|
|
751
|
-
ResolveInfo resolveInfo = getContext().getPackageManager().resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
|
|
752
|
-
|
|
753
|
-
if (resolveInfo != null) {
|
|
754
|
-
browserPackageName = resolveInfo.activityInfo.packageName;
|
|
755
|
-
|
|
756
|
-
if (!browserPackageName.isEmpty()) {
|
|
757
|
-
tabsIntent.intent.setPackage(browserPackageName);
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
if (isPresentAfterPageLoad) {
|
|
763
|
-
tabsIntent.intent.putExtra("isPresentAfterPageLoad", true);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
tabsIntent.launchUrl(getContext(), Uri.parse(url));
|
|
767
|
-
|
|
768
|
-
call.resolve();
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
@PluginMethod
|
|
772
|
-
public void clearCache(PluginCall call) {
|
|
773
|
-
String targetId = call.getString("id");
|
|
774
|
-
this.getActivity().runOnUiThread(() -> {
|
|
775
|
-
ArrayList<WebView> targetWebViews = cacheWebViewsFor(targetId);
|
|
776
|
-
if (targetWebViews.isEmpty()) {
|
|
777
|
-
call.reject("WebView is not initialized");
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
for (WebView targetWebView : targetWebViews) {
|
|
782
|
-
targetWebView.clearCache(true);
|
|
783
|
-
}
|
|
784
|
-
call.resolve();
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
@PluginMethod
|
|
789
|
-
public void clearAllCookies(PluginCall call) {
|
|
790
|
-
CookieManager cookieManager = CookieManager.getInstance();
|
|
791
|
-
cookieManager.removeAllCookies(null);
|
|
792
|
-
cookieManager.flush();
|
|
793
|
-
call.resolve();
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
@PluginMethod
|
|
797
|
-
public void clearCookies(PluginCall call) {
|
|
798
|
-
String url = call.getString("url", currentUrl);
|
|
799
|
-
if (url == null || TextUtils.isEmpty(url)) {
|
|
800
|
-
call.reject("Invalid URL");
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
Uri uri = Uri.parse(url);
|
|
805
|
-
String host = uri.getHost();
|
|
806
|
-
if (host == null || TextUtils.isEmpty(host)) {
|
|
807
|
-
call.reject("Invalid URL (Host is null)");
|
|
808
|
-
return;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
CookieManager cookieManager = CookieManager.getInstance();
|
|
812
|
-
String cookieString = cookieManager.getCookie(url);
|
|
813
|
-
ArrayList<String> cookiesToRemove = new ArrayList<>();
|
|
814
|
-
|
|
815
|
-
if (cookieString != null) {
|
|
816
|
-
String[] cookies = cookieString.split("; ");
|
|
817
|
-
|
|
818
|
-
String domain = uri.getHost();
|
|
819
|
-
|
|
820
|
-
for (String cookie : cookies) {
|
|
821
|
-
String[] parts = cookie.split("=");
|
|
822
|
-
if (parts.length > 0) {
|
|
823
|
-
cookiesToRemove.add(parts[0].trim());
|
|
824
|
-
CookieManager.getInstance().setCookie(url, String.format("%s=del;", parts[0].trim()));
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
StringBuilder scriptToRun = new StringBuilder();
|
|
830
|
-
for (String cookieToRemove : cookiesToRemove) {
|
|
831
|
-
scriptToRun.append(
|
|
832
|
-
String.format("window.cookieStore.delete('%s', {name: '%s', domain: '%s'});", cookieToRemove, cookieToRemove, url)
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
Log.i("DelCookies", String.format("Script to run:\n%s", scriptToRun));
|
|
837
|
-
|
|
838
|
-
String targetId = call.getString("id");
|
|
839
|
-
ArrayList<WebViewDialog> targetDialogs = new ArrayList<>();
|
|
840
|
-
|
|
841
|
-
if (targetId != null) {
|
|
842
|
-
WebViewDialog dialog = webViewDialogs.get(targetId);
|
|
843
|
-
if (dialog == null) {
|
|
844
|
-
call.reject("WebView is not initialized");
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
targetDialogs.add(dialog);
|
|
848
|
-
} else if (!webViewDialogs.isEmpty()) {
|
|
849
|
-
targetDialogs.addAll(webViewDialogs.values());
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
this.getActivity().runOnUiThread(
|
|
853
|
-
new Runnable() {
|
|
854
|
-
@Override
|
|
855
|
-
public void run() {
|
|
856
|
-
try {
|
|
857
|
-
if (!targetDialogs.isEmpty()) {
|
|
858
|
-
for (WebViewDialog dialog : targetDialogs) {
|
|
859
|
-
dialog.executeScript(scriptToRun.toString());
|
|
860
|
-
}
|
|
861
|
-
call.resolve();
|
|
862
|
-
} else {
|
|
863
|
-
call.reject("WebView is not initialized");
|
|
864
|
-
}
|
|
865
|
-
} catch (Exception e) {
|
|
866
|
-
Log.e("InAppBrowser", "Error clearing cookies: " + e.getMessage());
|
|
867
|
-
call.reject("Failed to clear cookies: " + e.getMessage());
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
@PluginMethod
|
|
875
|
-
public void getCookies(PluginCall call) {
|
|
876
|
-
String url = call.getString("url");
|
|
877
|
-
if (url == null || TextUtils.isEmpty(url)) {
|
|
878
|
-
call.reject("Invalid URL");
|
|
879
|
-
return;
|
|
880
|
-
}
|
|
881
|
-
CookieManager cookieManager = CookieManager.getInstance();
|
|
882
|
-
String cookieString = cookieManager.getCookie(url);
|
|
883
|
-
JSObject result = new JSObject();
|
|
884
|
-
if (cookieString != null) {
|
|
885
|
-
String[] cookiePairs = cookieString.split("; ");
|
|
886
|
-
for (String cookie : cookiePairs) {
|
|
887
|
-
String[] parts = cookie.split("=", 2);
|
|
888
|
-
if (parts.length == 2) {
|
|
889
|
-
result.put(parts[0], parts[1]);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
call.resolve(result);
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
@PluginMethod
|
|
897
|
-
public void openWebView(PluginCall call) {
|
|
898
|
-
String url = call.getString("url");
|
|
899
|
-
if (url == null || TextUtils.isEmpty(url)) {
|
|
900
|
-
call.reject("Invalid URL");
|
|
901
|
-
}
|
|
902
|
-
currentUrl = url;
|
|
903
|
-
final String webViewId = UUID.randomUUID().toString();
|
|
904
|
-
final Options options = new Options();
|
|
905
|
-
options.setUrl(url);
|
|
906
|
-
options.setHeaders(call.getObject("headers"));
|
|
907
|
-
options.setCredentials(call.getObject("credentials"));
|
|
908
|
-
options.setShowReloadButton(Boolean.TRUE.equals(call.getBoolean("showReloadButton", false)));
|
|
909
|
-
options.setVisibleTitle(Boolean.TRUE.equals(call.getBoolean("visibleTitle", true)));
|
|
910
|
-
if (Boolean.TRUE.equals(options.getVisibleTitle())) {
|
|
911
|
-
options.setTitle(call.getString("title", "New Window"));
|
|
912
|
-
} else {
|
|
913
|
-
options.setTitle(call.getString("title", ""));
|
|
914
|
-
}
|
|
915
|
-
options.setToolbarColor(call.getString("toolbarColor", "#ffffff"));
|
|
916
|
-
options.setBackgroundColor(call.getString("backgroundColor", "white"));
|
|
917
|
-
options.setToolbarTextColor(call.getString("toolbarTextColor"));
|
|
918
|
-
options.setArrow(Boolean.TRUE.equals(call.getBoolean("showArrow", false)));
|
|
919
|
-
options.setIgnoreUntrustedSSLError(Boolean.TRUE.equals(call.getBoolean("ignoreUntrustedSSLError", false)));
|
|
920
|
-
options.setShowScreenshotButton(Boolean.TRUE.equals(call.getBoolean("showScreenshotButton", false)));
|
|
921
|
-
options.setAllowScreenshotsFromWebPage(Boolean.TRUE.equals(call.getBoolean("allowScreenshotsFromWebPage", false)));
|
|
922
|
-
options.setCaptureConsoleLogs(Boolean.TRUE.equals(call.getBoolean("captureConsoleLogs", false)));
|
|
923
|
-
options.setHandleDownloads(Boolean.TRUE.equals(call.getBoolean("handleDownloads", false)));
|
|
924
|
-
|
|
925
|
-
// Set text zoom if specified in options (default is 100)
|
|
926
|
-
Integer textZoom = call.getInt("textZoom");
|
|
927
|
-
if (textZoom != null) {
|
|
928
|
-
options.setTextZoom(textZoom);
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
options.setProxyRequests(Boolean.TRUE.equals(call.getBoolean("proxyRequests", false)));
|
|
932
|
-
|
|
933
|
-
Object rawProxyRequests = call.getData().opt("proxyRequests");
|
|
934
|
-
if (rawProxyRequests instanceof String proxyRequestsStr) {
|
|
935
|
-
try {
|
|
936
|
-
Pattern proxyRequestsPattern = ProxyRequestSupport.compileProxyRequestsPattern(rawProxyRequests);
|
|
937
|
-
if (proxyRequestsPattern != null) {
|
|
938
|
-
options.setProxyRequestsPattern(proxyRequestsPattern);
|
|
939
|
-
}
|
|
940
|
-
} catch (PatternSyntaxException e) {
|
|
941
|
-
Log.e("WebViewDialog", String.format("Pattern '%s' is not a valid pattern", proxyRequestsStr));
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
List<NativeProxyRule> outboundProxyRules = parseProxyRules(call.getArray("outboundProxyRules"), "outboundProxyRules", call);
|
|
946
|
-
if (outboundProxyRules == null) {
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
options.setOutboundProxyRules(outboundProxyRules);
|
|
950
|
-
|
|
951
|
-
List<NativeProxyRule> inboundProxyRules = parseProxyRules(call.getArray("inboundProxyRules"), "inboundProxyRules", call);
|
|
952
|
-
if (inboundProxyRules == null) {
|
|
953
|
-
return;
|
|
954
|
-
}
|
|
955
|
-
options.setInboundProxyRules(inboundProxyRules);
|
|
956
|
-
|
|
957
|
-
JSObject buttonNearDoneObj = call.getObject("buttonNearDone");
|
|
958
|
-
try {
|
|
959
|
-
// Try to set buttonNearDone if present, with better error handling
|
|
960
|
-
if (buttonNearDoneObj != null) {
|
|
961
|
-
try {
|
|
962
|
-
// Provide better debugging for buttonNearDone
|
|
963
|
-
JSObject androidObj = buttonNearDoneObj.getJSObject("android");
|
|
964
|
-
if (androidObj != null) {
|
|
965
|
-
String iconType = androidObj.getString("iconType", "asset");
|
|
966
|
-
String icon = androidObj.getString("icon", "");
|
|
967
|
-
Log.d("InAppBrowser", "ButtonNearDone config - iconType: " + iconType + ", icon: " + icon);
|
|
968
|
-
|
|
969
|
-
// For vector type, verify if resource exists
|
|
970
|
-
if ("vector".equals(iconType)) {
|
|
971
|
-
int resourceId = getContext().getResources().getIdentifier(icon, "drawable", getContext().getPackageName());
|
|
972
|
-
if (resourceId == 0) {
|
|
973
|
-
Log.e("InAppBrowser", "Vector resource not found: " + icon);
|
|
974
|
-
call.reject("buttonNearDone validation failed: vector resource not found: " + icon);
|
|
975
|
-
return;
|
|
976
|
-
} else {
|
|
977
|
-
Log.d("InAppBrowser", "Vector resource found with ID: " + resourceId);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// Try to create the ButtonNearDone object
|
|
983
|
-
Options.ButtonNearDone buttonNearDone = Options.ButtonNearDone.generateFromPluginCall(call, getContext().getAssets());
|
|
984
|
-
options.setButtonNearDone(buttonNearDone);
|
|
985
|
-
} catch (Exception e) {
|
|
986
|
-
Log.e("InAppBrowser", "Error setting buttonNearDone: " + e.getMessage(), e);
|
|
987
|
-
call.reject("buttonNearDone validation failed: " + e.getMessage());
|
|
988
|
-
return;
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
} catch (Exception e) {
|
|
992
|
-
Log.e("InAppBrowser", "Error processing buttonNearDone: " + e.getMessage(), e);
|
|
993
|
-
call.reject("buttonNearDone validation failed: " + e.getMessage());
|
|
994
|
-
return;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
options.setShareDisclaimer(call.getObject("shareDisclaimer", null));
|
|
998
|
-
options.setPreShowScript(call.getString("preShowScript", null));
|
|
999
|
-
options.setShareSubject(call.getString("shareSubject", null));
|
|
1000
|
-
options.setToolbarType(call.getString("toolbarType", ""));
|
|
1001
|
-
options.setPreventDeeplink(Boolean.TRUE.equals(call.getBoolean("preventDeeplink", false)));
|
|
1002
|
-
options.setOpenBlankTargetInWebView(Boolean.TRUE.equals(call.getBoolean("openBlankTargetInWebView", false)));
|
|
1003
|
-
|
|
1004
|
-
// Validate preShowScript requires isPresentAfterPageLoad
|
|
1005
|
-
if (call.getData().has("preShowScript") && !Boolean.TRUE.equals(call.getBoolean("isPresentAfterPageLoad", false))) {
|
|
1006
|
-
call.reject("preShowScript requires isPresentAfterPageLoad to be true");
|
|
1007
|
-
return;
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Validate closeModal options
|
|
1011
|
-
if (Boolean.TRUE.equals(call.getBoolean("closeModal", false))) {
|
|
1012
|
-
options.setCloseModal(true);
|
|
1013
|
-
options.setCloseModalTitle(call.getString("closeModalTitle", "Close"));
|
|
1014
|
-
options.setCloseModalDescription(call.getString("closeModalDescription", "Are you sure ?"));
|
|
1015
|
-
options.setCloseModalOk(call.getString("closeModalOk", "Ok"));
|
|
1016
|
-
options.setCloseModalCancel(call.getString("closeModalCancel", "Cancel"));
|
|
1017
|
-
String closeModalURLPatternStr = call.getString("closeModalURLPattern");
|
|
1018
|
-
if (closeModalURLPatternStr != null) {
|
|
1019
|
-
try {
|
|
1020
|
-
options.setCloseModalURLPattern(Pattern.compile(closeModalURLPatternStr));
|
|
1021
|
-
} catch (PatternSyntaxException e) {
|
|
1022
|
-
call.reject("Invalid closeModalURLPattern regex: " + e.getMessage());
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
} else {
|
|
1027
|
-
// Reject if closeModal is false but closeModal options are provided
|
|
1028
|
-
if (
|
|
1029
|
-
call.getData().has("closeModalTitle") ||
|
|
1030
|
-
call.getData().has("closeModalDescription") ||
|
|
1031
|
-
call.getData().has("closeModalOk") ||
|
|
1032
|
-
call.getData().has("closeModalCancel") ||
|
|
1033
|
-
call.getData().has("closeModalURLPattern")
|
|
1034
|
-
) {
|
|
1035
|
-
call.reject("closeModal options require closeModal to be true");
|
|
1036
|
-
return;
|
|
1037
|
-
}
|
|
1038
|
-
options.setCloseModal(false);
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
// Validate shareDisclaimer requires shareSubject
|
|
1042
|
-
if (call.getData().has("shareDisclaimer") && !call.getData().has("shareSubject")) {
|
|
1043
|
-
call.reject("shareDisclaimer requires shareSubject to be provided");
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// Validate buttonNearDone compatibility with toolbar type
|
|
1048
|
-
if (buttonNearDoneObj != null && options.getShowScreenshotButton()) {
|
|
1049
|
-
call.reject("showScreenshotButton is not compatible with buttonNearDone");
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
if (buttonNearDoneObj != null || options.getShowScreenshotButton()) {
|
|
1054
|
-
String toolbarType = options.getToolbarType();
|
|
1055
|
-
if (
|
|
1056
|
-
TextUtils.equals(toolbarType, "activity") ||
|
|
1057
|
-
TextUtils.equals(toolbarType, "navigation") ||
|
|
1058
|
-
TextUtils.equals(toolbarType, "blank")
|
|
1059
|
-
) {
|
|
1060
|
-
String optionName = options.getShowScreenshotButton() ? "showScreenshotButton" : "buttonNearDone";
|
|
1061
|
-
call.reject(optionName + " is not compatible with toolbarType: " + toolbarType);
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
options.setActiveNativeNavigationForWebview(Boolean.TRUE.equals(call.getBoolean("activeNativeNavigationForWebview", false)));
|
|
1067
|
-
options.setDisableGoBackOnNativeApplication(Boolean.TRUE.equals(call.getBoolean("disableGoBackOnNativeApplication", false)));
|
|
1068
|
-
options.setPresentAfterPageLoad(Boolean.TRUE.equals(call.getBoolean("isPresentAfterPageLoad", false)));
|
|
1069
|
-
options.setPluginCall(call);
|
|
1070
|
-
|
|
1071
|
-
// Set Material Design picker option
|
|
1072
|
-
options.setMaterialPicker(Boolean.TRUE.equals(call.getBoolean("materialPicker", false)));
|
|
1073
|
-
|
|
1074
|
-
// Set enabledSafeBottomMargin option
|
|
1075
|
-
options.setEnabledSafeMargin(Boolean.TRUE.equals(call.getBoolean("enabledSafeBottomMargin", false)));
|
|
1076
|
-
|
|
1077
|
-
// Set enabledSafeTopMargin option (defaults to true for safe area)
|
|
1078
|
-
options.setEnabledSafeTopMargin(call.getBoolean("enabledSafeTopMargin", true));
|
|
1079
|
-
|
|
1080
|
-
// Use system top inset for WebView margin when explicitly enabled
|
|
1081
|
-
options.setUseTopInset(Boolean.TRUE.equals(call.getBoolean("useTopInset", false)));
|
|
1082
|
-
|
|
1083
|
-
// options.getToolbarItemTypes().add(ToolbarItemType.RELOAD); TODO: fix this
|
|
1084
|
-
options.setCallbacks(buildCallbacks(webViewId));
|
|
1085
|
-
|
|
1086
|
-
JSArray jsAuthorizedLinks = call.getArray("authorizedAppLinks");
|
|
1087
|
-
if (jsAuthorizedLinks != null && jsAuthorizedLinks.length() > 0) {
|
|
1088
|
-
List<String> authorizedLinks = new ArrayList<>();
|
|
1089
|
-
for (int i = 0; i < jsAuthorizedLinks.length(); i++) {
|
|
1090
|
-
try {
|
|
1091
|
-
String link = jsAuthorizedLinks.getString(i);
|
|
1092
|
-
if (link != null && !link.trim().isEmpty()) {
|
|
1093
|
-
authorizedLinks.add(link);
|
|
1094
|
-
}
|
|
1095
|
-
} catch (Exception e) {
|
|
1096
|
-
Log.w("InAppBrowserPlugin", "Error reading authorized app link at index " + i, e);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
Log.d("InAppBrowserPlugin", "Parsed authorized app links: " + authorizedLinks);
|
|
1100
|
-
options.setAuthorizedAppLinks(authorizedLinks);
|
|
1101
|
-
} else {
|
|
1102
|
-
Log.d("InAppBrowserPlugin", "No authorized app links provided.");
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
JSArray blockedHostsRaw = call.getArray("blockedHosts");
|
|
1106
|
-
if (blockedHostsRaw != null && blockedHostsRaw.length() > 0) {
|
|
1107
|
-
List<String> blockedHosts = new ArrayList<>();
|
|
1108
|
-
for (int i = 0; i < blockedHostsRaw.length(); i++) {
|
|
1109
|
-
try {
|
|
1110
|
-
String host = blockedHostsRaw.getString(i);
|
|
1111
|
-
if (host != null && !host.trim().isEmpty()) {
|
|
1112
|
-
blockedHosts.add(host);
|
|
1113
|
-
}
|
|
1114
|
-
} catch (Exception e) {
|
|
1115
|
-
Log.w("InAppBrowserPlugin", "Error reading blocked host at index " + i, e);
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
Log.d("InAppBrowserPlugin", "Parsed blocked hosts: " + blockedHosts);
|
|
1119
|
-
options.setBlockedHosts(blockedHosts);
|
|
1120
|
-
} else {
|
|
1121
|
-
Log.d("InAppBrowserPlugin", "No blocked hosts provided.");
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
// Set Google Pay support option
|
|
1125
|
-
options.setEnableGooglePaySupport(Boolean.TRUE.equals(call.getBoolean("enableGooglePaySupport", false)));
|
|
1126
|
-
options.setHiddenPopupWindow(Boolean.TRUE.equals(call.getBoolean("hiddenPopupWindow", false)));
|
|
1127
|
-
options.setEnableZoom(Boolean.TRUE.equals(call.getBoolean("enableZoom", false)));
|
|
1128
|
-
options.setHiddenPopupWindow(Boolean.TRUE.equals(call.getBoolean("hiddenPopupWindow", false)));
|
|
1129
|
-
|
|
1130
|
-
// Set dimensions if provided
|
|
1131
|
-
Integer width = call.getInt("width");
|
|
1132
|
-
Integer height = call.getInt("height");
|
|
1133
|
-
Integer x = call.getInt("x");
|
|
1134
|
-
Integer y = call.getInt("y");
|
|
1135
|
-
|
|
1136
|
-
// Validate dimension parameters
|
|
1137
|
-
if (width != null && height == null) {
|
|
1138
|
-
call.reject("Height must be specified when width is provided");
|
|
1139
|
-
return;
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
if (width != null) {
|
|
1143
|
-
options.setWidth(width);
|
|
1144
|
-
}
|
|
1145
|
-
if (height != null) {
|
|
1146
|
-
options.setHeight(height);
|
|
1147
|
-
}
|
|
1148
|
-
if (x != null) {
|
|
1149
|
-
options.setX(x);
|
|
1150
|
-
}
|
|
1151
|
-
if (y != null) {
|
|
1152
|
-
options.setY(y);
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
options.setHidden(Boolean.TRUE.equals(call.getBoolean("hidden", false)));
|
|
1156
|
-
boolean allowWebViewJsVisibilityControl = getConfig().getBoolean("allowWebViewJsVisibilityControl", false);
|
|
1157
|
-
options.setAllowWebViewJsVisibilityControl(allowWebViewJsVisibilityControl);
|
|
1158
|
-
options.setInvisibilityMode(Options.InvisibilityMode.fromString(call.getString("invisibilityMode", "AWARE")));
|
|
1159
|
-
|
|
1160
|
-
// Set HTTP method and body if provided
|
|
1161
|
-
String httpMethod = call.getString("method");
|
|
1162
|
-
String httpBody = call.getString("body");
|
|
1163
|
-
if (httpMethod != null) {
|
|
1164
|
-
options.setHttpMethod(httpMethod);
|
|
1165
|
-
}
|
|
1166
|
-
if (httpBody != null) {
|
|
1167
|
-
options.setHttpBody(httpBody);
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
this.getActivity().runOnUiThread(
|
|
1171
|
-
new Runnable() {
|
|
1172
|
-
@Override
|
|
1173
|
-
public void run() {
|
|
1174
|
-
WebViewDialog dialog = createManagedDialog(webViewId, options);
|
|
1175
|
-
dialog.presentWebView();
|
|
1176
|
-
if (options.isHidden()) {
|
|
1177
|
-
dialog.setHidden(true);
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
);
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
@NonNull
|
|
1185
|
-
private static StringBuilder getStringBuilder() {
|
|
1186
|
-
Field[] drawables = R.drawable.class.getFields();
|
|
1187
|
-
StringBuilder availableResources = new StringBuilder("Available resources: ");
|
|
1188
|
-
for (int i = 0; i < Math.min(10, drawables.length); i++) {
|
|
1189
|
-
availableResources.append(drawables[i].getName()).append(", ");
|
|
1190
|
-
}
|
|
1191
|
-
if (drawables.length > 10) {
|
|
1192
|
-
availableResources.append("... (").append(drawables.length - 10).append(" more)");
|
|
1193
|
-
}
|
|
1194
|
-
return availableResources;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
@PluginMethod
|
|
1198
|
-
public void postMessage(PluginCall call) {
|
|
1199
|
-
JSObject eventData = call.getObject("detail");
|
|
1200
|
-
// Log event data
|
|
1201
|
-
if (eventData == null) {
|
|
1202
|
-
call.reject("No event data provided");
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
String targetId = call.getString("id");
|
|
1207
|
-
Log.d("InAppBrowserPlugin", "Event data: " + eventData.toString());
|
|
1208
|
-
this.getActivity().runOnUiThread(
|
|
1209
|
-
new Runnable() {
|
|
1210
|
-
@Override
|
|
1211
|
-
public void run() {
|
|
1212
|
-
if (targetId != null) {
|
|
1213
|
-
WebViewDialog dialog = webViewDialogs.get(targetId);
|
|
1214
|
-
if (dialog == null) {
|
|
1215
|
-
call.reject("WebView is not initialized");
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
dialog.postMessageToJS(eventData);
|
|
1219
|
-
call.resolve();
|
|
1220
|
-
return;
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
if (!webViewDialogs.isEmpty()) {
|
|
1224
|
-
for (WebViewDialog dialog : webViewDialogs.values()) {
|
|
1225
|
-
dialog.postMessageToJS(eventData);
|
|
1226
|
-
}
|
|
1227
|
-
call.resolve();
|
|
1228
|
-
return;
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
// TODO: Legacy, can be removed(?)
|
|
1232
|
-
if (webViewDialog != null) {
|
|
1233
|
-
webViewDialog.postMessageToJS(eventData);
|
|
1234
|
-
call.resolve();
|
|
1235
|
-
} else {
|
|
1236
|
-
call.reject("WebView is not initialized");
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
);
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
@PluginMethod
|
|
1244
|
-
public void hide(PluginCall call) {
|
|
1245
|
-
String targetId = resolveTargetId(call);
|
|
1246
|
-
WebViewDialog targetDialog = resolveDialog(targetId);
|
|
1247
|
-
if (targetDialog == null) {
|
|
1248
|
-
call.reject("WebView is not initialized");
|
|
1249
|
-
return;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
this.getActivity().runOnUiThread(
|
|
1253
|
-
new Runnable() {
|
|
1254
|
-
@Override
|
|
1255
|
-
public void run() {
|
|
1256
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1257
|
-
if (dialog == null) {
|
|
1258
|
-
call.reject("WebView is not initialized");
|
|
1259
|
-
return;
|
|
1260
|
-
}
|
|
1261
|
-
dialog.setHidden(true);
|
|
1262
|
-
call.resolve();
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
);
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
@PluginMethod
|
|
1269
|
-
public void show(PluginCall call) {
|
|
1270
|
-
String targetId = resolveTargetId(call);
|
|
1271
|
-
WebViewDialog targetDialog = resolveDialog(targetId);
|
|
1272
|
-
if (targetDialog == null) {
|
|
1273
|
-
call.reject("WebView is not initialized");
|
|
1274
|
-
return;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
this.getActivity().runOnUiThread(
|
|
1278
|
-
new Runnable() {
|
|
1279
|
-
@Override
|
|
1280
|
-
public void run() {
|
|
1281
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1282
|
-
if (dialog == null) {
|
|
1283
|
-
call.reject("WebView is not initialized");
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
if (!dialog.isShowing()) {
|
|
1287
|
-
dialog.show();
|
|
1288
|
-
}
|
|
1289
|
-
dialog.setHidden(false);
|
|
1290
|
-
if (dialog.getInstanceId() != null) {
|
|
1291
|
-
setActiveWebView(dialog.getInstanceId(), dialog);
|
|
1292
|
-
}
|
|
1293
|
-
call.resolve();
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
);
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
@PluginMethod
|
|
1300
|
-
public void executeScript(PluginCall call) {
|
|
1301
|
-
String script = call.getString("code");
|
|
1302
|
-
if (script == null || script.trim().isEmpty()) {
|
|
1303
|
-
call.reject("Script is required");
|
|
1304
|
-
return;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
String targetId = call.getString("id");
|
|
1308
|
-
this.getActivity().runOnUiThread(
|
|
1309
|
-
new Runnable() {
|
|
1310
|
-
@Override
|
|
1311
|
-
public void run() {
|
|
1312
|
-
try {
|
|
1313
|
-
if (targetId != null) {
|
|
1314
|
-
WebViewDialog dialog = webViewDialogs.get(targetId);
|
|
1315
|
-
if (dialog == null) {
|
|
1316
|
-
call.reject("WebView is not initialized");
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
dialog.executeScript(script);
|
|
1320
|
-
call.resolve();
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
if (!webViewDialogs.isEmpty()) {
|
|
1325
|
-
for (WebViewDialog dialog : webViewDialogs.values()) {
|
|
1326
|
-
dialog.executeScript(script);
|
|
1327
|
-
}
|
|
1328
|
-
call.resolve();
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
// TODO: Legacy, can be removed(?)
|
|
1333
|
-
if (webViewDialog != null) {
|
|
1334
|
-
webViewDialog.executeScript(script);
|
|
1335
|
-
call.resolve();
|
|
1336
|
-
} else {
|
|
1337
|
-
call.reject("WebView is not initialized");
|
|
1338
|
-
}
|
|
1339
|
-
} catch (Exception e) {
|
|
1340
|
-
Log.e("InAppBrowser", "Error executing script: " + e.getMessage());
|
|
1341
|
-
call.reject("Failed to execute script: " + e.getMessage());
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
);
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
@PluginMethod
|
|
1349
|
-
public void takeScreenshot(PluginCall call) {
|
|
1350
|
-
this.getActivity().runOnUiThread(
|
|
1351
|
-
new Runnable() {
|
|
1352
|
-
@Override
|
|
1353
|
-
public void run() {
|
|
1354
|
-
String targetId = resolveTargetId(call);
|
|
1355
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1356
|
-
if (dialog == null) {
|
|
1357
|
-
call.reject("WebView is not initialized");
|
|
1358
|
-
return;
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
dialog.takeScreenshot(
|
|
1362
|
-
new WebViewDialog.ScreenshotResultCallback() {
|
|
1363
|
-
@Override
|
|
1364
|
-
public void onSuccess(JSObject screenshot) {
|
|
1365
|
-
call.resolve(screenshot);
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
@Override
|
|
1369
|
-
public void onError(String message) {
|
|
1370
|
-
call.reject(message);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
);
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
);
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
@PluginMethod
|
|
1380
|
-
public void goBack(PluginCall call) {
|
|
1381
|
-
this.getActivity().runOnUiThread(
|
|
1382
|
-
new Runnable() {
|
|
1383
|
-
@Override
|
|
1384
|
-
public void run() {
|
|
1385
|
-
String targetId = resolveTargetId(call);
|
|
1386
|
-
WebViewDialog webViewDialog = resolveDialog(targetId);
|
|
1387
|
-
if (webViewDialog != null) {
|
|
1388
|
-
boolean canGoBack = webViewDialog.goBack();
|
|
1389
|
-
JSObject result = new JSObject();
|
|
1390
|
-
result.put("canGoBack", canGoBack);
|
|
1391
|
-
call.resolve(result);
|
|
1392
|
-
} else {
|
|
1393
|
-
JSObject result = new JSObject();
|
|
1394
|
-
result.put("canGoBack", false);
|
|
1395
|
-
call.resolve(result);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
);
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
@PluginMethod
|
|
1403
|
-
public void reload(PluginCall call) {
|
|
1404
|
-
this.getActivity().runOnUiThread(
|
|
1405
|
-
new Runnable() {
|
|
1406
|
-
@Override
|
|
1407
|
-
public void run() {
|
|
1408
|
-
String targetId = resolveTargetId(call);
|
|
1409
|
-
WebViewDialog webViewDialog = resolveDialog(targetId);
|
|
1410
|
-
if (webViewDialog != null) {
|
|
1411
|
-
webViewDialog.reload();
|
|
1412
|
-
call.resolve();
|
|
1413
|
-
} else {
|
|
1414
|
-
call.reject("WebView is not initialized");
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
);
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
@PluginMethod
|
|
1422
|
-
public void lsuakdchgbbaHandleProxiedRequest(PluginCall call) {
|
|
1423
|
-
String requestId = call.getString("id");
|
|
1424
|
-
if (requestId == null) {
|
|
1425
|
-
Log.e("InAppBrowserProxy", "CRITICAL ERROR, proxy id = null");
|
|
1426
|
-
call.resolve();
|
|
1427
|
-
return;
|
|
1428
|
-
}
|
|
1429
|
-
JSObject decision = null;
|
|
1430
|
-
if (Boolean.TRUE.equals(call.getBoolean("ok", false))) {
|
|
1431
|
-
JSONObject object = call.getObject("result");
|
|
1432
|
-
if (object != null) {
|
|
1433
|
-
decision = new JSObject();
|
|
1434
|
-
decision.put("response", ProxyRequestSupport.normalizeLegacySyntheticResponse(object));
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
handleProxyRequestInternal(call.getString("webviewId"), requestId, decision, call);
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
@PluginMethod
|
|
1441
|
-
public void handleProxyRequest(PluginCall call) {
|
|
1442
|
-
String requestId = call.getString("requestId");
|
|
1443
|
-
if (requestId == null) {
|
|
1444
|
-
call.reject("requestId is required");
|
|
1445
|
-
return;
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
JSObject decision = call.getObject("decision");
|
|
1449
|
-
if (decision == null) {
|
|
1450
|
-
decision = call.getObject("response");
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
handleProxyRequestInternal(call.getString("webviewId"), requestId, decision, call);
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
private void handleProxyRequestInternal(String webviewId, String requestId, JSObject decision, PluginCall call) {
|
|
1457
|
-
WebViewDialog dialog = ProxyResponseRouting.resolveTargetDialog(webviewId, requestId, webViewDialogs);
|
|
1458
|
-
if (dialog == null) {
|
|
1459
|
-
if (webviewId == null || webviewId.isBlank()) {
|
|
1460
|
-
call.reject("webviewId is required when the proxy request cannot be mapped to a unique WebView");
|
|
1461
|
-
return;
|
|
1462
|
-
}
|
|
1463
|
-
call.reject("Target WebView not found for proxy request");
|
|
1464
|
-
return;
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
dialog.handleProxyResponse(requestId, decision);
|
|
1468
|
-
call.resolve();
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
@PluginMethod
|
|
1472
|
-
public void close(PluginCall call) {
|
|
1473
|
-
String targetId = resolveTargetId(call);
|
|
1474
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1475
|
-
if (dialog == null) {
|
|
1476
|
-
// Fallback: try to bring main activity to foreground
|
|
1477
|
-
try {
|
|
1478
|
-
Intent intent = new Intent(getContext(), getBridge().getActivity().getClass());
|
|
1479
|
-
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
1480
|
-
getContext().startActivity(intent);
|
|
1481
|
-
call.resolve();
|
|
1482
|
-
} catch (Exception e) {
|
|
1483
|
-
Log.e("InAppBrowser", "Error bringing main activity to foreground: " + e.getMessage());
|
|
1484
|
-
call.reject("WebView is not initialized and failed to restore main activity");
|
|
1485
|
-
}
|
|
1486
|
-
return;
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
this.getActivity().runOnUiThread(
|
|
1490
|
-
new Runnable() {
|
|
1491
|
-
@Override
|
|
1492
|
-
public void run() {
|
|
1493
|
-
try {
|
|
1494
|
-
if (dialog != null) {
|
|
1495
|
-
String currentUrl = "";
|
|
1496
|
-
try {
|
|
1497
|
-
currentUrl = dialog.getUrl();
|
|
1498
|
-
if (currentUrl == null) {
|
|
1499
|
-
currentUrl = "";
|
|
1500
|
-
}
|
|
1501
|
-
} catch (Exception e) {
|
|
1502
|
-
Log.e("InAppBrowser", "Error getting URL before close: " + e.getMessage());
|
|
1503
|
-
currentUrl = "";
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
|
-
// Notify listeners about the close event
|
|
1507
|
-
JSObject eventData = new JSObject().put("url", currentUrl);
|
|
1508
|
-
if (targetId != null) {
|
|
1509
|
-
eventData.put("id", targetId);
|
|
1510
|
-
}
|
|
1511
|
-
notifyListeners("closeEvent", eventData);
|
|
1512
|
-
|
|
1513
|
-
dialog.dismiss();
|
|
1514
|
-
if (targetId != null) {
|
|
1515
|
-
unregisterWebView(targetId);
|
|
1516
|
-
} else {
|
|
1517
|
-
webViewDialog = null;
|
|
1518
|
-
}
|
|
1519
|
-
call.resolve();
|
|
1520
|
-
} else {
|
|
1521
|
-
// Secondary fallback inside UI thread
|
|
1522
|
-
try {
|
|
1523
|
-
Intent intent = new Intent(getContext(), getBridge().getActivity().getClass());
|
|
1524
|
-
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
1525
|
-
getContext().startActivity(intent);
|
|
1526
|
-
call.resolve();
|
|
1527
|
-
} catch (Exception e) {
|
|
1528
|
-
Log.e("InAppBrowser", "Error in secondary fallback: " + e.getMessage());
|
|
1529
|
-
call.reject("WebView is not initialized");
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
} catch (Exception e) {
|
|
1533
|
-
Log.e("InAppBrowser", "Error closing WebView: " + e.getMessage());
|
|
1534
|
-
call.reject("Failed to close WebView: " + e.getMessage());
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
);
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
private Bundle getHeaders(PluginCall pluginCall) {
|
|
1542
|
-
JSObject headersProvided = pluginCall.getObject("headers");
|
|
1543
|
-
Bundle headers = new Bundle();
|
|
1544
|
-
if (headersProvided != null) {
|
|
1545
|
-
Iterator<String> keys = headersProvided.keys();
|
|
1546
|
-
while (keys.hasNext()) {
|
|
1547
|
-
String key = keys.next();
|
|
1548
|
-
headers.putString(key, headersProvided.getString(key));
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
return headers;
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
protected void handleOnResume() {
|
|
1555
|
-
boolean ok = CustomTabsClient.bindCustomTabsService(getContext(), CUSTOM_TAB_PACKAGE_NAME, connection);
|
|
1556
|
-
if (!ok) {
|
|
1557
|
-
Log.e(getLogTag(), "Error binding to custom tabs service");
|
|
1558
|
-
}
|
|
1559
|
-
// If we have a saved call and user returned without callback, reject
|
|
1560
|
-
if (openSecureWindowSavedCall != null) {
|
|
1561
|
-
openSecureWindowSavedCall.reject("OAuth cancelled or no callback received");
|
|
1562
|
-
openSecureWindowSavedCall = null;
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
protected void handleOnPause() {
|
|
1567
|
-
getContext().unbindService(connection);
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
public CustomTabsSession getCustomTabsSession() {
|
|
1571
|
-
if (customTabsClient == null) {
|
|
1572
|
-
return null;
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
if (currentSession == null) {
|
|
1576
|
-
currentSession = customTabsClient.newSession(
|
|
1577
|
-
new CustomTabsCallback() {
|
|
1578
|
-
@Override
|
|
1579
|
-
public void onNavigationEvent(int navigationEvent, Bundle extras) {
|
|
1580
|
-
// Only fire browserPageLoaded for Custom Tabs, not for WebView
|
|
1581
|
-
if (navigationEvent == NAVIGATION_FINISHED && webViewDialogs.isEmpty() && webViewDialog == null) {
|
|
1582
|
-
notifyListeners("browserPageLoaded", new JSObject());
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
);
|
|
1587
|
-
}
|
|
1588
|
-
return currentSession;
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
@Override
|
|
1592
|
-
protected void handleOnDestroy() {
|
|
1593
|
-
for (WebViewDialog dialog : webViewDialogs.values()) {
|
|
1594
|
-
try {
|
|
1595
|
-
dialog.dismiss();
|
|
1596
|
-
} catch (Exception e) {
|
|
1597
|
-
// Ignore, dialog may already be dismissed
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
webViewDialogs.clear();
|
|
1601
|
-
webViewStack.clear();
|
|
1602
|
-
activeWebViewId = null;
|
|
1603
|
-
webViewDialog = null;
|
|
1604
|
-
clearCurrentWebPermissionRequest();
|
|
1605
|
-
if (pendingCameraPermissionCall != null) {
|
|
1606
|
-
pendingCameraPermissionCall.reject("Plugin destroyed before permission response");
|
|
1607
|
-
pendingCameraPermissionCall = null;
|
|
1608
|
-
}
|
|
1609
|
-
customTabsClient = null;
|
|
1610
|
-
currentSession = null;
|
|
1611
|
-
openSecureWindowSavedCall = null;
|
|
1612
|
-
super.handleOnDestroy();
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
@PluginMethod
|
|
1616
|
-
public void getPluginVersion(final PluginCall call) {
|
|
1617
|
-
try {
|
|
1618
|
-
final JSObject ret = new JSObject();
|
|
1619
|
-
ret.put("version", this.pluginVersion);
|
|
1620
|
-
call.resolve(ret);
|
|
1621
|
-
} catch (final Exception e) {
|
|
1622
|
-
call.reject("Could not get plugin version", e);
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
@PluginMethod
|
|
1627
|
-
public void updateDimensions(PluginCall call) {
|
|
1628
|
-
String targetId = resolveTargetId(call);
|
|
1629
|
-
WebViewDialog webViewDialog = resolveDialog(targetId);
|
|
1630
|
-
if (webViewDialog == null) {
|
|
1631
|
-
call.reject("WebView is not initialized");
|
|
1632
|
-
return;
|
|
1633
|
-
}
|
|
1634
|
-
|
|
1635
|
-
Integer width = call.getInt("width");
|
|
1636
|
-
Integer height = call.getInt("height");
|
|
1637
|
-
Integer x = call.getInt("x");
|
|
1638
|
-
Integer y = call.getInt("y");
|
|
1639
|
-
|
|
1640
|
-
this.getActivity().runOnUiThread(
|
|
1641
|
-
new Runnable() {
|
|
1642
|
-
@Override
|
|
1643
|
-
public void run() {
|
|
1644
|
-
try {
|
|
1645
|
-
if (webViewDialog != null) {
|
|
1646
|
-
webViewDialog.updateDimensions(width, height, x, y);
|
|
1647
|
-
call.resolve();
|
|
1648
|
-
} else {
|
|
1649
|
-
call.reject("WebView is not initialized");
|
|
1650
|
-
}
|
|
1651
|
-
} catch (Exception e) {
|
|
1652
|
-
Log.e("InAppBrowser", "Error updating dimensions: " + e.getMessage());
|
|
1653
|
-
call.reject("Failed to update dimensions: " + e.getMessage());
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
);
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
|
-
@PluginMethod
|
|
1661
|
-
public void setEnabledSafeTopMargin(PluginCall call) {
|
|
1662
|
-
Boolean enabledValue = call.getBoolean("enabled");
|
|
1663
|
-
if (enabledValue == null) {
|
|
1664
|
-
call.reject("'enabled' (boolean) is required");
|
|
1665
|
-
return;
|
|
1666
|
-
}
|
|
1667
|
-
boolean enabled = enabledValue;
|
|
1668
|
-
String targetId = resolveTargetId(call);
|
|
1669
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1670
|
-
if (dialog == null) {
|
|
1671
|
-
call.reject("WebView is not initialized");
|
|
1672
|
-
return;
|
|
1673
|
-
}
|
|
1674
|
-
this.getActivity().runOnUiThread(() -> {
|
|
1675
|
-
try {
|
|
1676
|
-
dialog.setEnabledSafeTopMargin(enabled);
|
|
1677
|
-
call.resolve();
|
|
1678
|
-
} catch (Exception e) {
|
|
1679
|
-
Log.e("InAppBrowser", "Error setting safe top margin: " + e.getMessage());
|
|
1680
|
-
call.reject("Failed to set safe top margin: " + e.getMessage());
|
|
1681
|
-
}
|
|
1682
|
-
});
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
@PluginMethod
|
|
1686
|
-
public void setEnabledSafeBottomMargin(PluginCall call) {
|
|
1687
|
-
Boolean enabledValue = call.getBoolean("enabled");
|
|
1688
|
-
if (enabledValue == null) {
|
|
1689
|
-
call.reject("'enabled' (boolean) is required");
|
|
1690
|
-
return;
|
|
1691
|
-
}
|
|
1692
|
-
boolean enabled = enabledValue;
|
|
1693
|
-
String targetId = resolveTargetId(call);
|
|
1694
|
-
WebViewDialog dialog = resolveDialog(targetId);
|
|
1695
|
-
if (dialog == null) {
|
|
1696
|
-
call.reject("WebView is not initialized");
|
|
1697
|
-
return;
|
|
1698
|
-
}
|
|
1699
|
-
this.getActivity().runOnUiThread(() -> {
|
|
1700
|
-
try {
|
|
1701
|
-
dialog.setEnabledSafeBottomMargin(enabled);
|
|
1702
|
-
call.resolve();
|
|
1703
|
-
} catch (Exception e) {
|
|
1704
|
-
Log.e("InAppBrowser", "Error setting safe bottom margin: " + e.getMessage());
|
|
1705
|
-
call.reject("Failed to set safe bottom margin: " + e.getMessage());
|
|
1706
|
-
}
|
|
1707
|
-
});
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
@PluginMethod
|
|
1711
|
-
public void openSecureWindow(PluginCall call) {
|
|
1712
|
-
String authEndpoint = call.getString("authEndpoint");
|
|
1713
|
-
|
|
1714
|
-
if (authEndpoint == null || authEndpoint.isEmpty()) {
|
|
1715
|
-
call.reject("Auth endpoint is required");
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
|
-
String redirectUri = call.getString("redirectUri");
|
|
1720
|
-
if (redirectUri == null || redirectUri.isEmpty()) {
|
|
1721
|
-
call.reject("Redirect URI is required");
|
|
1722
|
-
return;
|
|
1723
|
-
}
|
|
1724
|
-
|
|
1725
|
-
openSecureWindowSavedCall = call;
|
|
1726
|
-
openSecureWindowRedirectUri = redirectUri;
|
|
1727
|
-
|
|
1728
|
-
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
|
1729
|
-
builder.enableUrlBarHiding();
|
|
1730
|
-
builder.setShareState(CustomTabsIntent.SHARE_STATE_OFF);
|
|
1731
|
-
builder.setEphemeralBrowsingEnabled(Boolean.TRUE.equals(call.getBoolean("prefersEphemeralWebBrowserSession", false)));
|
|
1732
|
-
CustomTabsIntent customTabsIntent = builder.build();
|
|
1733
|
-
customTabsIntent.intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
1734
|
-
customTabsIntent.intent.putExtra(CustomTabsIntent.EXTRA_ENABLE_INSTANT_APPS, false);
|
|
1735
|
-
customTabsIntent.intent.putExtra(CustomTabsIntent.EXTRA_DISABLE_BACKGROUND_INTERACTION, false);
|
|
1736
|
-
customTabsIntent.launchUrl(getActivity(), Uri.parse(authEndpoint));
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
@Override
|
|
1740
|
-
protected void handleOnNewIntent(Intent intent) {
|
|
1741
|
-
super.handleOnNewIntent(intent);
|
|
1742
|
-
|
|
1743
|
-
if (intent == null || !Intent.ACTION_VIEW.equals(intent.getAction())) {
|
|
1744
|
-
return;
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
Uri uri = intent.getData();
|
|
1748
|
-
if (uri == null) {
|
|
1749
|
-
return;
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
|
-
if (openSecureWindowRedirectUri == null) {
|
|
1753
|
-
return;
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
if (uri.getHost() == null || !uri.toString().startsWith(openSecureWindowRedirectUri)) {
|
|
1757
|
-
return;
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
|
-
try {
|
|
1761
|
-
// Resolve the original call with the callback url
|
|
1762
|
-
if (openSecureWindowSavedCall != null) {
|
|
1763
|
-
final JSObject ret = new JSObject();
|
|
1764
|
-
ret.put("redirectedUri", uri.toString());
|
|
1765
|
-
openSecureWindowSavedCall.resolve(ret);
|
|
1766
|
-
openSecureWindowSavedCall = null;
|
|
1767
|
-
}
|
|
1768
|
-
} catch (Exception e) {
|
|
1769
|
-
if (openSecureWindowSavedCall != null) {
|
|
1770
|
-
openSecureWindowSavedCall.reject("Failed to process OAuth callback", e);
|
|
1771
|
-
openSecureWindowSavedCall = null;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
final class ConsoleMessageEventHelper {
|
|
1778
|
-
|
|
1779
|
-
private ConsoleMessageEventHelper() {}
|
|
1780
|
-
|
|
1781
|
-
static JSObject create(String webViewId, String level, String message, String source, Integer line, Integer column) {
|
|
1782
|
-
Map<String, Object> data = createData(webViewId, level, message, source, line, column);
|
|
1783
|
-
JSObject event = new JSObject();
|
|
1784
|
-
for (Map.Entry<String, Object> entry : data.entrySet()) {
|
|
1785
|
-
event.put(entry.getKey(), entry.getValue());
|
|
1786
|
-
}
|
|
1787
|
-
return event;
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
static Map<String, Object> createData(String webViewId, String level, String message, String source, Integer line, Integer column) {
|
|
1791
|
-
Map<String, Object> event = new HashMap<>();
|
|
1792
|
-
if (webViewId != null && !webViewId.isEmpty()) {
|
|
1793
|
-
event.put("id", webViewId);
|
|
1794
|
-
}
|
|
1795
|
-
event.put("level", normalizeLevel(level));
|
|
1796
|
-
event.put("message", message != null ? message : "");
|
|
1797
|
-
if (source != null && !source.isEmpty()) {
|
|
1798
|
-
event.put("source", source);
|
|
1799
|
-
}
|
|
1800
|
-
if (line != null) {
|
|
1801
|
-
event.put("line", line);
|
|
1802
|
-
}
|
|
1803
|
-
if (column != null) {
|
|
1804
|
-
event.put("column", column);
|
|
1805
|
-
}
|
|
1806
|
-
return event;
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
|
-
static String normalizeLevel(String level) {
|
|
1810
|
-
if (level == null) {
|
|
1811
|
-
return "log";
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
|
-
String normalized = level.trim().toLowerCase();
|
|
1815
|
-
return switch (normalized) {
|
|
1816
|
-
case "log", "info", "warn", "error", "debug", "assert" -> normalized;
|
|
1817
|
-
default -> "log";
|
|
1818
|
-
};
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
17
|
+
public class InAppBrowserPlugin extends CapgoInAppBrowserPlugin {}
|