@capgo/inappbrowser 8.0.0 → 8.0.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/CapgoInappbrowser.podspec +2 -2
- package/LICENSE +373 -21
- package/Package.swift +28 -0
- package/README.md +600 -74
- package/android/build.gradle +17 -16
- package/android/src/main/AndroidManifest.xml +14 -2
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +952 -204
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +478 -81
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +10 -4
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +3021 -226
- package/android/src/main/res/drawable/ic_refresh.xml +9 -0
- package/android/src/main/res/drawable/ic_share.xml +10 -0
- package/android/src/main/res/layout/activity_browser.xml +10 -0
- package/android/src/main/res/layout/content_browser.xml +3 -2
- package/android/src/main/res/layout/tool_bar.xml +44 -7
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/main/res/values/themes.xml +27 -0
- package/android/src/main/res/xml/file_paths.xml +14 -0
- package/dist/docs.json +1289 -149
- package/dist/esm/definitions.d.ts +614 -25
- package/dist/esm/definitions.js +17 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +16 -3
- package/dist/esm/web.js +43 -7
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +60 -8
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +60 -8
- package/dist/plugin.js.map +1 -1
- package/ios/{Plugin → Sources/InAppBrowserPlugin}/Enums.swift +5 -5
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +954 -0
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +2003 -0
- package/package.json +32 -30
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@3x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Contents.json +0 -26
- package/ios/Plugin/Assets.xcassets/Contents.json +0 -6
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Contents.json +0 -26
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@3x.png +0 -0
- package/ios/Plugin/InAppBrowserPlugin.h +0 -10
- package/ios/Plugin/InAppBrowserPlugin.m +0 -17
- package/ios/Plugin/InAppBrowserPlugin.swift +0 -203
- package/ios/Plugin/Info.plist +0 -24
- package/ios/Plugin/WKWebViewController.swift +0 -784
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package ee.forgr.capacitor_inappbrowser;
|
|
2
2
|
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import android.app.Activity;
|
|
3
5
|
import android.content.ComponentName;
|
|
4
6
|
import android.content.Intent;
|
|
5
7
|
import android.content.pm.PackageManager;
|
|
@@ -8,235 +10,981 @@ import android.net.Uri;
|
|
|
8
10
|
import android.os.Bundle;
|
|
9
11
|
import android.text.TextUtils;
|
|
10
12
|
import android.util.Log;
|
|
11
|
-
import android.webkit.
|
|
13
|
+
import android.webkit.CookieManager;
|
|
14
|
+
import android.webkit.PermissionRequest;
|
|
15
|
+
import androidx.activity.result.ActivityResult;
|
|
16
|
+
import androidx.activity.result.ActivityResultLauncher;
|
|
17
|
+
import androidx.activity.result.contract.ActivityResultContracts;
|
|
18
|
+
import androidx.annotation.NonNull;
|
|
12
19
|
import androidx.browser.customtabs.CustomTabsCallback;
|
|
13
20
|
import androidx.browser.customtabs.CustomTabsClient;
|
|
14
21
|
import androidx.browser.customtabs.CustomTabsIntent;
|
|
15
22
|
import androidx.browser.customtabs.CustomTabsServiceConnection;
|
|
16
23
|
import androidx.browser.customtabs.CustomTabsSession;
|
|
24
|
+
import com.getcapacitor.JSArray;
|
|
17
25
|
import com.getcapacitor.JSObject;
|
|
26
|
+
import com.getcapacitor.PermissionState;
|
|
18
27
|
import com.getcapacitor.Plugin;
|
|
19
28
|
import com.getcapacitor.PluginCall;
|
|
20
29
|
import com.getcapacitor.PluginMethod;
|
|
21
30
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
31
|
+
import com.getcapacitor.annotation.Permission;
|
|
32
|
+
import com.getcapacitor.annotation.PermissionCallback;
|
|
33
|
+
import java.lang.reflect.Field;
|
|
34
|
+
import java.util.ArrayList;
|
|
22
35
|
import java.util.Iterator;
|
|
36
|
+
import java.util.List;
|
|
37
|
+
import java.util.regex.Pattern;
|
|
38
|
+
import java.util.regex.PatternSyntaxException;
|
|
39
|
+
import org.json.JSONException;
|
|
40
|
+
import org.json.JSONObject;
|
|
23
41
|
|
|
24
|
-
@CapacitorPlugin(
|
|
25
|
-
|
|
42
|
+
@CapacitorPlugin(
|
|
43
|
+
name = "InAppBrowser",
|
|
44
|
+
permissions = {
|
|
45
|
+
@Permission(alias = "camera", strings = { Manifest.permission.CAMERA }),
|
|
46
|
+
@Permission(alias = "microphone", strings = { Manifest.permission.RECORD_AUDIO }),
|
|
47
|
+
@Permission(alias = "storage", strings = { Manifest.permission.READ_EXTERNAL_STORAGE })
|
|
48
|
+
},
|
|
49
|
+
requestCodes = { WebViewDialog.FILE_CHOOSER_REQUEST_CODE }
|
|
50
|
+
)
|
|
51
|
+
public class InAppBrowserPlugin extends Plugin implements WebViewDialog.PermissionHandler {
|
|
26
52
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
53
|
+
private final String pluginVersion = "8.0.2";
|
|
54
|
+
|
|
55
|
+
public static final String CUSTOM_TAB_PACKAGE_NAME = "com.android.chrome"; // Change when in stable
|
|
56
|
+
private CustomTabsClient customTabsClient;
|
|
57
|
+
private CustomTabsSession currentSession;
|
|
58
|
+
private WebViewDialog webViewDialog = null;
|
|
59
|
+
private String currentUrl = "";
|
|
60
|
+
|
|
61
|
+
private PermissionRequest currentPermissionRequest;
|
|
62
|
+
|
|
63
|
+
private ActivityResultLauncher<Intent> fileChooserLauncher;
|
|
31
64
|
|
|
32
|
-
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
|
|
33
65
|
@Override
|
|
34
|
-
public void
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
66
|
+
public void load() {
|
|
67
|
+
super.load();
|
|
68
|
+
fileChooserLauncher = getActivity().registerForActivityResult(
|
|
69
|
+
new ActivityResultContracts.StartActivityForResult(),
|
|
70
|
+
this::handleFileChooserResult
|
|
71
|
+
);
|
|
40
72
|
}
|
|
41
73
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
call.reject("Invalid URL");
|
|
73
|
-
}
|
|
74
|
-
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(
|
|
75
|
-
getCustomTabsSession()
|
|
76
|
-
);
|
|
77
|
-
CustomTabsIntent tabsIntent = builder.build();
|
|
78
|
-
tabsIntent.intent.putExtra(
|
|
79
|
-
Intent.EXTRA_REFERRER,
|
|
80
|
-
Uri.parse(
|
|
81
|
-
Intent.URI_ANDROID_APP_SCHEME + "//" + getContext().getPackageName()
|
|
82
|
-
)
|
|
83
|
-
);
|
|
84
|
-
tabsIntent.intent.putExtra(
|
|
85
|
-
android.provider.Browser.EXTRA_HEADERS,
|
|
86
|
-
this.getHeaders(call)
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
if (preventDeeplink != null) {
|
|
90
|
-
String browserPackageName = "";
|
|
91
|
-
Intent browserIntent = new Intent(
|
|
92
|
-
Intent.ACTION_VIEW,
|
|
93
|
-
Uri.parse("http://")
|
|
94
|
-
);
|
|
95
|
-
ResolveInfo resolveInfo = getContext()
|
|
96
|
-
.getPackageManager()
|
|
97
|
-
.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
|
|
98
|
-
|
|
99
|
-
if (resolveInfo != null) {
|
|
100
|
-
browserPackageName = resolveInfo.activityInfo.packageName;
|
|
101
|
-
|
|
102
|
-
if (!browserPackageName.isEmpty()) {
|
|
103
|
-
tabsIntent.intent.setPackage(browserPackageName);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
tabsIntent.launchUrl(getContext(), Uri.parse(url));
|
|
109
|
-
|
|
110
|
-
call.resolve();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
@PluginMethod
|
|
114
|
-
public void clearCookies(PluginCall call) {
|
|
115
|
-
WebStorage.getInstance().deleteAllData();
|
|
116
|
-
call.resolve();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@PluginMethod
|
|
120
|
-
public void openWebView(PluginCall call) {
|
|
121
|
-
String url = call.getString("url");
|
|
122
|
-
if (url == null || TextUtils.isEmpty(url)) {
|
|
123
|
-
call.reject("Invalid URL");
|
|
124
|
-
}
|
|
125
|
-
final Options options = new Options();
|
|
126
|
-
options.setUrl(url);
|
|
127
|
-
options.setHeaders(call.getObject("headers"));
|
|
128
|
-
options.setTitle(call.getString("title", "New Window"));
|
|
129
|
-
options.setShareDisclaimer(call.getObject("shareDisclaimer", null));
|
|
130
|
-
options.setShareSubject(call.getString("shareSubject", null));
|
|
131
|
-
options.setToolbarType(call.getString("toolbarType", ""));
|
|
132
|
-
options.setPresentAfterPageLoad(
|
|
133
|
-
call.getBoolean("isPresentAfterPageLoad", false)
|
|
134
|
-
);
|
|
135
|
-
options.setPluginCall(call);
|
|
136
|
-
options.setCallbacks(
|
|
137
|
-
new WebViewCallbacks() {
|
|
138
|
-
@Override
|
|
139
|
-
public void urlChangeEvent(String url) {
|
|
140
|
-
notifyListeners("urlChangeEvent", new JSObject().put("url", url));
|
|
74
|
+
private void handleFileChooserResult(ActivityResult result) {
|
|
75
|
+
if (webViewDialog != null && webViewDialog.mFilePathCallback != null) {
|
|
76
|
+
Uri[] results = null;
|
|
77
|
+
Intent data = result.getData();
|
|
78
|
+
|
|
79
|
+
if (result.getResultCode() == Activity.RESULT_OK) {
|
|
80
|
+
// Handle camera capture result
|
|
81
|
+
if (webViewDialog.tempCameraUri != null && (data == null || data.getData() == null)) {
|
|
82
|
+
results = new Uri[] { webViewDialog.tempCameraUri };
|
|
83
|
+
}
|
|
84
|
+
// Handle regular file picker result
|
|
85
|
+
else if (data != null) {
|
|
86
|
+
if (data.getClipData() != null) {
|
|
87
|
+
// Handle multiple files
|
|
88
|
+
int count = data.getClipData().getItemCount();
|
|
89
|
+
results = new Uri[count];
|
|
90
|
+
for (int i = 0; i < count; i++) {
|
|
91
|
+
results[i] = data.getClipData().getItemAt(i).getUri();
|
|
92
|
+
}
|
|
93
|
+
} else if (data.getData() != null) {
|
|
94
|
+
// Handle single file
|
|
95
|
+
results = new Uri[] { data.getData() };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Send the result to WebView and clean up
|
|
101
|
+
webViewDialog.mFilePathCallback.onReceiveValue(results);
|
|
102
|
+
webViewDialog.mFilePathCallback = null;
|
|
103
|
+
webViewDialog.tempCameraUri = null;
|
|
141
104
|
}
|
|
105
|
+
}
|
|
142
106
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
107
|
+
public void handleMicrophonePermissionRequest(PermissionRequest request) {
|
|
108
|
+
this.currentPermissionRequest = request;
|
|
109
|
+
if (getPermissionState("microphone") != PermissionState.GRANTED) {
|
|
110
|
+
requestPermissionForAlias("microphone", null, "microphonePermissionCallback");
|
|
111
|
+
} else {
|
|
112
|
+
grantMicrophonePermission();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void grantMicrophonePermission() {
|
|
117
|
+
if (currentPermissionRequest != null) {
|
|
118
|
+
currentPermissionRequest.grant(new String[] { PermissionRequest.RESOURCE_AUDIO_CAPTURE });
|
|
119
|
+
currentPermissionRequest = null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@PermissionCallback
|
|
124
|
+
private void microphonePermissionCallback(PluginCall call) {
|
|
125
|
+
if (getPermissionState("microphone") == PermissionState.GRANTED) {
|
|
126
|
+
grantCameraAndMicrophonePermission();
|
|
127
|
+
} else {
|
|
128
|
+
if (currentPermissionRequest != null) {
|
|
129
|
+
currentPermissionRequest.deny();
|
|
130
|
+
currentPermissionRequest = null;
|
|
131
|
+
}
|
|
132
|
+
if (call != null) {
|
|
133
|
+
call.reject("Microphone permission is required");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private void grantCameraAndMicrophonePermission() {
|
|
139
|
+
if (currentPermissionRequest != null) {
|
|
140
|
+
currentPermissionRequest.grant(
|
|
141
|
+
new String[] { PermissionRequest.RESOURCE_VIDEO_CAPTURE, PermissionRequest.RESOURCE_AUDIO_CAPTURE }
|
|
142
|
+
);
|
|
143
|
+
currentPermissionRequest = null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public void handleCameraPermissionRequest(PermissionRequest request) {
|
|
148
|
+
this.currentPermissionRequest = request;
|
|
149
|
+
if (getPermissionState("camera") != PermissionState.GRANTED) {
|
|
150
|
+
requestPermissionForAlias("camera", null, "cameraPermissionCallback");
|
|
151
|
+
} else if (getPermissionState("microphone") != PermissionState.GRANTED) {
|
|
152
|
+
requestPermissionForAlias("microphone", null, "microphonePermissionCallback");
|
|
153
|
+
} else {
|
|
154
|
+
grantCameraAndMicrophonePermission();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@PermissionCallback
|
|
159
|
+
private void cameraPermissionCallback(PluginCall call) {
|
|
160
|
+
if (getPermissionState("camera") == PermissionState.GRANTED) {
|
|
161
|
+
if (getPermissionState("microphone") != PermissionState.GRANTED) {
|
|
162
|
+
requestPermissionForAlias("microphone", null, "microphonePermissionCallback");
|
|
163
|
+
} else {
|
|
164
|
+
grantCameraAndMicrophonePermission();
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
if (currentPermissionRequest != null) {
|
|
168
|
+
currentPermissionRequest.deny();
|
|
169
|
+
currentPermissionRequest = null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Reject only if there's a call - could be null for WebViewDialog flow
|
|
173
|
+
if (call != null) {
|
|
174
|
+
call.reject("Camera permission is required");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@PermissionCallback
|
|
180
|
+
private void cameraPermissionCallback() {
|
|
181
|
+
if (getPermissionState("camera") == PermissionState.GRANTED) {
|
|
182
|
+
grantCameraPermission();
|
|
183
|
+
} else {
|
|
184
|
+
if (currentPermissionRequest != null) {
|
|
185
|
+
currentPermissionRequest.deny();
|
|
186
|
+
currentPermissionRequest = null;
|
|
187
|
+
}
|
|
146
188
|
}
|
|
189
|
+
}
|
|
147
190
|
|
|
191
|
+
private void grantCameraPermission() {
|
|
192
|
+
if (currentPermissionRequest != null) {
|
|
193
|
+
currentPermissionRequest.grant(new String[] { PermissionRequest.RESOURCE_VIDEO_CAPTURE });
|
|
194
|
+
currentPermissionRequest = null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
|
|
148
199
|
@Override
|
|
149
|
-
public void
|
|
150
|
-
|
|
200
|
+
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
|
|
201
|
+
customTabsClient = client;
|
|
151
202
|
}
|
|
152
203
|
|
|
153
204
|
@Override
|
|
154
|
-
public void
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
205
|
+
public void onServiceDisconnected(ComponentName name) {
|
|
206
|
+
customTabsClient = null;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
@PluginMethod
|
|
211
|
+
public void requestCameraPermission(PluginCall call) {
|
|
212
|
+
if (getPermissionState("camera") != PermissionState.GRANTED) {
|
|
213
|
+
requestPermissionForAlias("camera", call, "cameraPermissionCallback");
|
|
214
|
+
} else {
|
|
215
|
+
call.resolve();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@PluginMethod
|
|
220
|
+
public void setUrl(PluginCall call) {
|
|
221
|
+
String url = call.getString("url");
|
|
222
|
+
if (url == null || TextUtils.isEmpty(url)) {
|
|
223
|
+
call.reject("Invalid URL");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (webViewDialog == null) {
|
|
228
|
+
call.reject("WebView is not initialized");
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
currentUrl = url;
|
|
233
|
+
this.getActivity().runOnUiThread(
|
|
234
|
+
new Runnable() {
|
|
235
|
+
@Override
|
|
236
|
+
public void run() {
|
|
237
|
+
try {
|
|
238
|
+
if (webViewDialog != null) {
|
|
239
|
+
webViewDialog.setUrl(url);
|
|
240
|
+
call.resolve();
|
|
241
|
+
} else {
|
|
242
|
+
call.reject("WebView is not initialized");
|
|
243
|
+
}
|
|
244
|
+
} catch (Exception e) {
|
|
245
|
+
Log.e("InAppBrowser", "Error setting URL: " + e.getMessage());
|
|
246
|
+
call.reject("Failed to set URL: " + e.getMessage());
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@PluginMethod
|
|
254
|
+
public void open(PluginCall call) {
|
|
255
|
+
String url = call.getString("url");
|
|
256
|
+
if (url == null) {
|
|
257
|
+
call.reject("URL is required");
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// get the deeplink prevention, if provided
|
|
262
|
+
Boolean preventDeeplink = call.getBoolean("preventDeeplink", false);
|
|
263
|
+
Boolean isPresentAfterPageLoad = call.getBoolean("isPresentAfterPageLoad", false);
|
|
264
|
+
|
|
265
|
+
if (url == null || TextUtils.isEmpty(url)) {
|
|
266
|
+
call.reject("Invalid URL");
|
|
267
|
+
}
|
|
268
|
+
currentUrl = url;
|
|
269
|
+
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getCustomTabsSession());
|
|
270
|
+
CustomTabsIntent tabsIntent = builder.build();
|
|
271
|
+
tabsIntent.intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(Intent.URI_ANDROID_APP_SCHEME + "//" + getContext().getPackageName()));
|
|
272
|
+
tabsIntent.intent.putExtra(android.provider.Browser.EXTRA_HEADERS, this.getHeaders(call));
|
|
273
|
+
|
|
274
|
+
if (preventDeeplink != false) {
|
|
275
|
+
String browserPackageName = "";
|
|
276
|
+
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
|
|
277
|
+
ResolveInfo resolveInfo = getContext().getPackageManager().resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
|
|
278
|
+
|
|
279
|
+
if (resolveInfo != null) {
|
|
280
|
+
browserPackageName = resolveInfo.activityInfo.packageName;
|
|
281
|
+
|
|
282
|
+
if (!browserPackageName.isEmpty()) {
|
|
283
|
+
tabsIntent.intent.setPackage(browserPackageName);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (isPresentAfterPageLoad) {
|
|
289
|
+
tabsIntent.intent.putExtra("isPresentAfterPageLoad", true);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
tabsIntent.launchUrl(getContext(), Uri.parse(url));
|
|
293
|
+
|
|
294
|
+
call.resolve();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@PluginMethod
|
|
298
|
+
public void clearCache(PluginCall call) {
|
|
299
|
+
CookieManager cookieManager = CookieManager.getInstance();
|
|
300
|
+
cookieManager.removeAllCookies(null);
|
|
301
|
+
cookieManager.flush();
|
|
302
|
+
call.resolve();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
@PluginMethod
|
|
306
|
+
public void clearAllCookies(PluginCall call) {
|
|
307
|
+
CookieManager cookieManager = CookieManager.getInstance();
|
|
308
|
+
cookieManager.removeAllCookies(null);
|
|
309
|
+
cookieManager.flush();
|
|
310
|
+
call.resolve();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@PluginMethod
|
|
314
|
+
public void clearCookies(PluginCall call) {
|
|
315
|
+
String url = call.getString("url", currentUrl);
|
|
316
|
+
if (url == null || TextUtils.isEmpty(url)) {
|
|
317
|
+
call.reject("Invalid URL");
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
Uri uri = Uri.parse(url);
|
|
322
|
+
String host = uri.getHost();
|
|
323
|
+
if (host == null || TextUtils.isEmpty(host)) {
|
|
324
|
+
call.reject("Invalid URL (Host is null)");
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
CookieManager cookieManager = CookieManager.getInstance();
|
|
329
|
+
String cookieString = cookieManager.getCookie(url);
|
|
330
|
+
ArrayList<String> cookiesToRemove = new ArrayList<>();
|
|
331
|
+
|
|
332
|
+
if (cookieString != null) {
|
|
333
|
+
String[] cookies = cookieString.split("; ");
|
|
334
|
+
|
|
335
|
+
String domain = uri.getHost();
|
|
336
|
+
|
|
337
|
+
for (String cookie : cookies) {
|
|
338
|
+
String[] parts = cookie.split("=");
|
|
339
|
+
if (parts.length > 0) {
|
|
340
|
+
cookiesToRemove.add(parts[0].trim());
|
|
341
|
+
CookieManager.getInstance().setCookie(url, String.format("%s=del;", parts[0].trim()));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
StringBuilder scriptToRun = new StringBuilder();
|
|
347
|
+
for (String cookieToRemove : cookiesToRemove) {
|
|
348
|
+
scriptToRun.append(
|
|
349
|
+
String.format("window.cookieStore.delete('%s', {name: '%s', domain: '%s'});", cookieToRemove, cookieToRemove, url)
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
Log.i("DelCookies", String.format("Script to run:\n%s", scriptToRun));
|
|
354
|
+
|
|
355
|
+
this.getActivity().runOnUiThread(
|
|
356
|
+
new Runnable() {
|
|
357
|
+
@Override
|
|
358
|
+
public void run() {
|
|
359
|
+
try {
|
|
360
|
+
if (webViewDialog != null) {
|
|
361
|
+
webViewDialog.executeScript(scriptToRun.toString());
|
|
362
|
+
call.resolve();
|
|
363
|
+
} else {
|
|
364
|
+
call.reject("WebView is not initialized");
|
|
365
|
+
}
|
|
366
|
+
} catch (Exception e) {
|
|
367
|
+
Log.e("InAppBrowser", "Error clearing cookies: " + e.getMessage());
|
|
368
|
+
call.reject("Failed to clear cookies: " + e.getMessage());
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@PluginMethod
|
|
376
|
+
public void getCookies(PluginCall call) {
|
|
377
|
+
String url = call.getString("url");
|
|
378
|
+
if (url == null || TextUtils.isEmpty(url)) {
|
|
379
|
+
call.reject("Invalid URL");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
CookieManager cookieManager = CookieManager.getInstance();
|
|
383
|
+
String cookieString = cookieManager.getCookie(url);
|
|
384
|
+
JSObject result = new JSObject();
|
|
385
|
+
if (cookieString != null) {
|
|
386
|
+
String[] cookiePairs = cookieString.split("; ");
|
|
387
|
+
for (String cookie : cookiePairs) {
|
|
388
|
+
String[] parts = cookie.split("=", 2);
|
|
389
|
+
if (parts.length == 2) {
|
|
390
|
+
result.put(parts[0], parts[1]);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
call.resolve(result);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
@PluginMethod
|
|
398
|
+
public void openWebView(PluginCall call) {
|
|
399
|
+
String url = call.getString("url");
|
|
400
|
+
if (url == null || TextUtils.isEmpty(url)) {
|
|
401
|
+
call.reject("Invalid URL");
|
|
402
|
+
}
|
|
403
|
+
currentUrl = url;
|
|
404
|
+
final Options options = new Options();
|
|
405
|
+
options.setUrl(url);
|
|
406
|
+
options.setHeaders(call.getObject("headers"));
|
|
407
|
+
options.setCredentials(call.getObject("credentials"));
|
|
408
|
+
options.setShowReloadButton(Boolean.TRUE.equals(call.getBoolean("showReloadButton", false)));
|
|
409
|
+
options.setVisibleTitle(Boolean.TRUE.equals(call.getBoolean("visibleTitle", true)));
|
|
410
|
+
if (Boolean.TRUE.equals(options.getVisibleTitle())) {
|
|
411
|
+
options.setTitle(call.getString("title", "New Window"));
|
|
412
|
+
} else {
|
|
413
|
+
options.setTitle(call.getString("title", ""));
|
|
414
|
+
}
|
|
415
|
+
options.setToolbarColor(call.getString("toolbarColor", "#ffffff"));
|
|
416
|
+
options.setBackgroundColor(call.getString("backgroundColor", "white"));
|
|
417
|
+
options.setToolbarTextColor(call.getString("toolbarTextColor"));
|
|
418
|
+
options.setArrow(Boolean.TRUE.equals(call.getBoolean("showArrow", false)));
|
|
419
|
+
options.setIgnoreUntrustedSSLError(Boolean.TRUE.equals(call.getBoolean("ignoreUntrustedSSLError", false)));
|
|
420
|
+
|
|
421
|
+
// Set text zoom if specified in options (default is 100)
|
|
422
|
+
Integer textZoom = call.getInt("textZoom");
|
|
423
|
+
if (textZoom != null) {
|
|
424
|
+
options.setTextZoom(textZoom);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
String proxyRequestsStr = call.getString("proxyRequests");
|
|
428
|
+
if (proxyRequestsStr != null) {
|
|
429
|
+
try {
|
|
430
|
+
options.setProxyRequestsPattern(Pattern.compile(proxyRequestsStr));
|
|
431
|
+
} catch (PatternSyntaxException e) {
|
|
432
|
+
Log.e("WebViewDialog", String.format("Pattern '%s' is not a valid pattern", proxyRequestsStr));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
// Try to set buttonNearDone if present, with better error handling
|
|
438
|
+
JSObject buttonNearDoneObj = call.getObject("buttonNearDone");
|
|
439
|
+
if (buttonNearDoneObj != null) {
|
|
440
|
+
try {
|
|
441
|
+
// Provide better debugging for buttonNearDone
|
|
442
|
+
JSObject androidObj = buttonNearDoneObj.getJSObject("android");
|
|
443
|
+
if (androidObj != null) {
|
|
444
|
+
String iconType = androidObj.getString("iconType", "asset");
|
|
445
|
+
String icon = androidObj.getString("icon", "");
|
|
446
|
+
Log.d("InAppBrowser", "ButtonNearDone config - iconType: " + iconType + ", icon: " + icon);
|
|
447
|
+
|
|
448
|
+
// For vector type, verify if resource exists
|
|
449
|
+
if ("vector".equals(iconType)) {
|
|
450
|
+
int resourceId = getContext().getResources().getIdentifier(icon, "drawable", getContext().getPackageName());
|
|
451
|
+
if (resourceId == 0) {
|
|
452
|
+
Log.e("InAppBrowser", "Vector resource not found: " + icon);
|
|
453
|
+
// List available drawable resources to help debugging
|
|
454
|
+
try {
|
|
455
|
+
final StringBuilder availableResources = getStringBuilder();
|
|
456
|
+
Log.d("InAppBrowser", availableResources.toString());
|
|
457
|
+
} catch (Exception e) {
|
|
458
|
+
Log.e("InAppBrowser", "Error listing resources: " + e.getMessage());
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
Log.d("InAppBrowser", "Vector resource found with ID: " + resourceId);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Try to create the ButtonNearDone object
|
|
467
|
+
Options.ButtonNearDone buttonNearDone = Options.ButtonNearDone.generateFromPluginCall(call, getContext().getAssets());
|
|
468
|
+
options.setButtonNearDone(buttonNearDone);
|
|
469
|
+
} catch (Exception e) {
|
|
470
|
+
Log.e("InAppBrowser", "Error setting buttonNearDone: " + e.getMessage(), e);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
} catch (Exception e) {
|
|
474
|
+
Log.e("InAppBrowser", "Error processing buttonNearDone: " + e.getMessage(), e);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
options.setShareDisclaimer(call.getObject("shareDisclaimer", null));
|
|
478
|
+
options.setPreShowScript(call.getString("preShowScript", null));
|
|
479
|
+
options.setShareSubject(call.getString("shareSubject", null));
|
|
480
|
+
options.setToolbarType(call.getString("toolbarType", ""));
|
|
481
|
+
options.setPreventDeeplink(Boolean.TRUE.equals(call.getBoolean("preventDeeplink", false)));
|
|
482
|
+
|
|
483
|
+
// Validate preShowScript requires isPresentAfterPageLoad
|
|
484
|
+
if (call.getData().has("preShowScript") && !Boolean.TRUE.equals(call.getBoolean("isPresentAfterPageLoad", false))) {
|
|
485
|
+
call.reject("preShowScript requires isPresentAfterPageLoad to be true");
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Validate closeModal options
|
|
490
|
+
if (Boolean.TRUE.equals(call.getBoolean("closeModal", false))) {
|
|
491
|
+
options.setCloseModal(true);
|
|
492
|
+
options.setCloseModalTitle(call.getString("closeModalTitle", "Close"));
|
|
493
|
+
options.setCloseModalDescription(call.getString("closeModalDescription", "Are you sure ?"));
|
|
494
|
+
options.setCloseModalOk(call.getString("closeModalOk", "Ok"));
|
|
495
|
+
options.setCloseModalCancel(call.getString("closeModalCancel", "Cancel"));
|
|
496
|
+
} else {
|
|
497
|
+
// Reject if closeModal is false but closeModal options are provided
|
|
498
|
+
if (
|
|
499
|
+
call.getData().has("closeModalTitle") ||
|
|
500
|
+
call.getData().has("closeModalDescription") ||
|
|
501
|
+
call.getData().has("closeModalOk") ||
|
|
502
|
+
call.getData().has("closeModalCancel")
|
|
503
|
+
) {
|
|
504
|
+
call.reject("closeModal options require closeModal to be true");
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
options.setCloseModal(false);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Validate shareDisclaimer requires shareSubject
|
|
511
|
+
if (call.getData().has("shareDisclaimer") && !call.getData().has("shareSubject")) {
|
|
512
|
+
call.reject("shareDisclaimer requires shareSubject to be provided");
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Validate buttonNearDone compatibility with toolbar type
|
|
517
|
+
if (call.getData().has("buttonNearDone")) {
|
|
518
|
+
String toolbarType = options.getToolbarType();
|
|
519
|
+
if (
|
|
520
|
+
TextUtils.equals(toolbarType, "activity") ||
|
|
521
|
+
TextUtils.equals(toolbarType, "navigation") ||
|
|
522
|
+
TextUtils.equals(toolbarType, "blank")
|
|
523
|
+
) {
|
|
524
|
+
call.reject("buttonNearDone is not compatible with toolbarType: " + toolbarType);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
options.setActiveNativeNavigationForWebview(Boolean.TRUE.equals(call.getBoolean("activeNativeNavigationForWebview", false)));
|
|
530
|
+
options.setDisableGoBackOnNativeApplication(Boolean.TRUE.equals(call.getBoolean("disableGoBackOnNativeApplication", false)));
|
|
531
|
+
options.setPresentAfterPageLoad(Boolean.TRUE.equals(call.getBoolean("isPresentAfterPageLoad", false)));
|
|
532
|
+
options.setPluginCall(call);
|
|
533
|
+
|
|
534
|
+
// Set Material Design picker option
|
|
535
|
+
options.setMaterialPicker(Boolean.TRUE.equals(call.getBoolean("materialPicker", false)));
|
|
536
|
+
|
|
537
|
+
// Set enabledSafeBottomMargin option
|
|
538
|
+
options.setEnabledSafeMargin(Boolean.TRUE.equals(call.getBoolean("enabledSafeBottomMargin", false)));
|
|
539
|
+
|
|
540
|
+
// Use system top inset for WebView margin when explicitly enabled
|
|
541
|
+
options.setUseTopInset(Boolean.TRUE.equals(call.getBoolean("useTopInset", false)));
|
|
542
|
+
|
|
543
|
+
// options.getToolbarItemTypes().add(ToolbarItemType.RELOAD); TODO: fix this
|
|
544
|
+
options.setCallbacks(
|
|
545
|
+
new WebViewCallbacks() {
|
|
546
|
+
@Override
|
|
547
|
+
public void urlChangeEvent(String url) {
|
|
548
|
+
notifyListeners("urlChangeEvent", new JSObject().put("url", url));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
@Override
|
|
552
|
+
public void closeEvent(String url) {
|
|
553
|
+
notifyListeners("closeEvent", new JSObject().put("url", url));
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
@Override
|
|
557
|
+
public void pageLoaded() {
|
|
558
|
+
notifyListeners("browserPageLoaded", new JSObject());
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
@Override
|
|
562
|
+
public void pageLoadError() {
|
|
563
|
+
notifyListeners("pageLoadError", new JSObject());
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
@Override
|
|
567
|
+
public void buttonNearDoneClicked() {
|
|
568
|
+
notifyListeners("buttonNearDoneClick", new JSObject());
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
@Override
|
|
572
|
+
public void confirmBtnClicked(String url) {
|
|
573
|
+
notifyListeners("confirmBtnClicked", new JSObject().put("url", url));
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
@Override
|
|
577
|
+
public void javascriptCallback(String message) {
|
|
578
|
+
// Handle the message received from JavaScript
|
|
579
|
+
Log.d("WebViewDialog", "Received message from JavaScript: " + message);
|
|
580
|
+
// Process the message as needed
|
|
581
|
+
try {
|
|
582
|
+
// Parse the received message as a JSON object
|
|
583
|
+
JSONObject jsonMessage = new JSONObject(message);
|
|
584
|
+
|
|
585
|
+
// Create a new JSObject to send to the Capacitor plugin
|
|
586
|
+
JSObject jsObject = new JSObject();
|
|
587
|
+
|
|
588
|
+
// Iterate through the keys in the JSON object and add them to the JSObject
|
|
589
|
+
Iterator<String> keys = jsonMessage.keys();
|
|
590
|
+
while (keys.hasNext()) {
|
|
591
|
+
String key = keys.next();
|
|
592
|
+
jsObject.put(key, jsonMessage.get(key));
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Notify listeners with the parsed message
|
|
596
|
+
notifyListeners("messageFromWebview", jsObject);
|
|
597
|
+
} catch (JSONException e) {
|
|
598
|
+
Log.e("WebViewDialog", "Error parsing JSON message: " + e.getMessage());
|
|
599
|
+
|
|
600
|
+
// If JSON parsing fails, send the raw message as a string
|
|
601
|
+
JSObject jsObject = new JSObject();
|
|
602
|
+
jsObject.put("rawMessage", message);
|
|
603
|
+
notifyListeners("messageFromWebview", jsObject);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
JSArray jsAuthorizedLinks = call.getArray("authorizedAppLinks");
|
|
610
|
+
if (jsAuthorizedLinks != null && jsAuthorizedLinks.length() > 0) {
|
|
611
|
+
List<String> authorizedLinks = new ArrayList<>();
|
|
612
|
+
for (int i = 0; i < jsAuthorizedLinks.length(); i++) {
|
|
613
|
+
try {
|
|
614
|
+
String link = jsAuthorizedLinks.getString(i);
|
|
615
|
+
if (link != null && !link.trim().isEmpty()) {
|
|
616
|
+
authorizedLinks.add(link);
|
|
617
|
+
}
|
|
618
|
+
} catch (Exception e) {
|
|
619
|
+
Log.w("InAppBrowserPlugin", "Error reading authorized app link at index " + i, e);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
Log.d("InAppBrowserPlugin", "Parsed authorized app links: " + authorizedLinks);
|
|
623
|
+
options.setAuthorizedAppLinks(authorizedLinks);
|
|
624
|
+
} else {
|
|
625
|
+
Log.d("InAppBrowserPlugin", "No authorized app links provided.");
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
JSArray blockedHostsRaw = call.getArray("blockedHosts");
|
|
629
|
+
if (blockedHostsRaw != null && blockedHostsRaw.length() > 0) {
|
|
630
|
+
List<String> blockedHosts = new ArrayList<>();
|
|
631
|
+
for (int i = 0; i < blockedHostsRaw.length(); i++) {
|
|
632
|
+
try {
|
|
633
|
+
String host = blockedHostsRaw.getString(i);
|
|
634
|
+
if (host != null && !host.trim().isEmpty()) {
|
|
635
|
+
blockedHosts.add(host);
|
|
636
|
+
}
|
|
637
|
+
} catch (Exception e) {
|
|
638
|
+
Log.w("InAppBrowserPlugin", "Error reading blocked host at index " + i, e);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
Log.d("InAppBrowserPlugin", "Parsed blocked hosts: " + blockedHosts);
|
|
642
|
+
options.setBlockedHosts(blockedHosts);
|
|
643
|
+
} else {
|
|
644
|
+
Log.d("InAppBrowserPlugin", "No blocked hosts provided.");
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Set Google Pay support option
|
|
648
|
+
options.setEnableGooglePaySupport(Boolean.TRUE.equals(call.getBoolean("enableGooglePaySupport", false)));
|
|
649
|
+
|
|
650
|
+
// Set dimensions if provided
|
|
651
|
+
Integer width = call.getInt("width");
|
|
652
|
+
Integer height = call.getInt("height");
|
|
653
|
+
Integer x = call.getInt("x");
|
|
654
|
+
Integer y = call.getInt("y");
|
|
655
|
+
|
|
656
|
+
// Validate dimension parameters
|
|
657
|
+
if (width != null && height == null) {
|
|
658
|
+
call.reject("Height must be specified when width is provided");
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (width != null) {
|
|
663
|
+
options.setWidth(width);
|
|
664
|
+
}
|
|
665
|
+
if (height != null) {
|
|
666
|
+
options.setHeight(height);
|
|
667
|
+
}
|
|
668
|
+
if (x != null) {
|
|
669
|
+
options.setX(x);
|
|
670
|
+
}
|
|
671
|
+
if (y != null) {
|
|
672
|
+
options.setY(y);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
this.getActivity().runOnUiThread(
|
|
676
|
+
new Runnable() {
|
|
677
|
+
@Override
|
|
678
|
+
public void run() {
|
|
679
|
+
webViewDialog = new WebViewDialog(
|
|
680
|
+
getContext(),
|
|
681
|
+
android.R.style.Theme_NoTitleBar,
|
|
682
|
+
options,
|
|
683
|
+
InAppBrowserPlugin.this,
|
|
684
|
+
getBridge().getWebView()
|
|
685
|
+
);
|
|
686
|
+
webViewDialog.activity = InAppBrowserPlugin.this.getActivity();
|
|
687
|
+
webViewDialog.presentWebView();
|
|
688
|
+
call.resolve();
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
@NonNull
|
|
695
|
+
private static StringBuilder getStringBuilder() {
|
|
696
|
+
Field[] drawables = R.drawable.class.getFields();
|
|
697
|
+
StringBuilder availableResources = new StringBuilder("Available resources: ");
|
|
698
|
+
for (int i = 0; i < Math.min(10, drawables.length); i++) {
|
|
699
|
+
availableResources.append(drawables[i].getName()).append(", ");
|
|
700
|
+
}
|
|
701
|
+
if (drawables.length > 10) {
|
|
702
|
+
availableResources.append("... (").append(drawables.length - 10).append(" more)");
|
|
703
|
+
}
|
|
704
|
+
return availableResources;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
@PluginMethod
|
|
708
|
+
public void postMessage(PluginCall call) {
|
|
709
|
+
if (webViewDialog == null) {
|
|
710
|
+
call.reject("WebView is not initialized");
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
JSObject eventData = call.getObject("detail");
|
|
714
|
+
// Log event data
|
|
715
|
+
if (eventData == null) {
|
|
716
|
+
call.reject("No event data provided");
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
Log.d("InAppBrowserPlugin", "Event data: " + eventData.toString());
|
|
721
|
+
this.getActivity().runOnUiThread(
|
|
722
|
+
new Runnable() {
|
|
723
|
+
@Override
|
|
724
|
+
public void run() {
|
|
725
|
+
if (webViewDialog != null) {
|
|
726
|
+
webViewDialog.postMessageToJS(eventData);
|
|
727
|
+
call.resolve();
|
|
728
|
+
} else {
|
|
729
|
+
call.reject("WebView is not initialized");
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
@PluginMethod
|
|
737
|
+
public void executeScript(PluginCall call) {
|
|
738
|
+
String script = call.getString("code");
|
|
739
|
+
if (script == null || script.trim().isEmpty()) {
|
|
740
|
+
call.reject("Script is required");
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (webViewDialog == null) {
|
|
745
|
+
call.reject("WebView is not initialized");
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
this.getActivity().runOnUiThread(
|
|
750
|
+
new Runnable() {
|
|
751
|
+
@Override
|
|
752
|
+
public void run() {
|
|
753
|
+
try {
|
|
754
|
+
if (webViewDialog != null) {
|
|
755
|
+
webViewDialog.executeScript(script);
|
|
756
|
+
call.resolve();
|
|
757
|
+
} else {
|
|
758
|
+
call.reject("WebView is not initialized");
|
|
759
|
+
}
|
|
760
|
+
} catch (Exception e) {
|
|
761
|
+
Log.e("InAppBrowser", "Error executing script: " + e.getMessage());
|
|
762
|
+
call.reject("Failed to execute script: " + e.getMessage());
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
@PluginMethod
|
|
770
|
+
public void goBack(PluginCall call) {
|
|
771
|
+
this.getActivity().runOnUiThread(
|
|
772
|
+
new Runnable() {
|
|
773
|
+
@Override
|
|
774
|
+
public void run() {
|
|
775
|
+
if (webViewDialog != null) {
|
|
776
|
+
boolean canGoBack = webViewDialog.goBack();
|
|
777
|
+
JSObject result = new JSObject();
|
|
778
|
+
result.put("canGoBack", canGoBack);
|
|
779
|
+
call.resolve(result);
|
|
780
|
+
} else {
|
|
781
|
+
JSObject result = new JSObject();
|
|
782
|
+
result.put("canGoBack", false);
|
|
783
|
+
call.resolve(result);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
@PluginMethod
|
|
791
|
+
public void reload(PluginCall call) {
|
|
792
|
+
this.getActivity().runOnUiThread(
|
|
793
|
+
new Runnable() {
|
|
794
|
+
@Override
|
|
795
|
+
public void run() {
|
|
796
|
+
if (webViewDialog != null) {
|
|
797
|
+
webViewDialog.reload();
|
|
798
|
+
call.resolve();
|
|
799
|
+
} else {
|
|
800
|
+
call.reject("WebView is not initialized");
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
@PluginMethod
|
|
808
|
+
public void lsuakdchgbbaHandleProxiedRequest(PluginCall call) {
|
|
809
|
+
if (webViewDialog != null) {
|
|
810
|
+
Boolean ok = call.getBoolean("ok", false);
|
|
811
|
+
String id = call.getString("id");
|
|
812
|
+
if (id == null) {
|
|
813
|
+
Log.e("InAppBrowserProxy", "CRITICAL ERROR, proxy id = null");
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
if (Boolean.FALSE.equals(ok)) {
|
|
817
|
+
String result = call.getString("result", "");
|
|
818
|
+
webViewDialog.handleProxyResultError(result, id);
|
|
819
|
+
} else {
|
|
820
|
+
JSONObject object = call.getObject("result");
|
|
821
|
+
webViewDialog.handleProxyResultOk(object, id);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
call.resolve();
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
@PluginMethod
|
|
828
|
+
public void close(PluginCall call) {
|
|
829
|
+
if (webViewDialog == null) {
|
|
830
|
+
// Fallback: try to bring main activity to foreground
|
|
831
|
+
try {
|
|
832
|
+
Intent intent = new Intent(getContext(), getBridge().getActivity().getClass());
|
|
833
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
834
|
+
getContext().startActivity(intent);
|
|
835
|
+
call.resolve();
|
|
836
|
+
} catch (Exception e) {
|
|
837
|
+
Log.e("InAppBrowser", "Error bringing main activity to foreground: " + e.getMessage());
|
|
838
|
+
call.reject("WebView is not initialized and failed to restore main activity");
|
|
839
|
+
}
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
this.getActivity().runOnUiThread(
|
|
844
|
+
new Runnable() {
|
|
845
|
+
@Override
|
|
846
|
+
public void run() {
|
|
847
|
+
try {
|
|
848
|
+
if (webViewDialog != null) {
|
|
849
|
+
String currentUrl = "";
|
|
850
|
+
try {
|
|
851
|
+
currentUrl = webViewDialog.getUrl();
|
|
852
|
+
if (currentUrl == null) {
|
|
853
|
+
currentUrl = "";
|
|
854
|
+
}
|
|
855
|
+
} catch (Exception e) {
|
|
856
|
+
Log.e("InAppBrowser", "Error getting URL before close: " + e.getMessage());
|
|
857
|
+
currentUrl = "";
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Notify listeners about the close event
|
|
861
|
+
notifyListeners("closeEvent", new JSObject().put("url", currentUrl));
|
|
862
|
+
|
|
863
|
+
webViewDialog.dismiss();
|
|
864
|
+
webViewDialog = null;
|
|
865
|
+
call.resolve();
|
|
866
|
+
} else {
|
|
867
|
+
// Secondary fallback inside UI thread
|
|
868
|
+
try {
|
|
869
|
+
Intent intent = new Intent(getContext(), getBridge().getActivity().getClass());
|
|
870
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
871
|
+
getContext().startActivity(intent);
|
|
872
|
+
call.resolve();
|
|
873
|
+
} catch (Exception e) {
|
|
874
|
+
Log.e("InAppBrowser", "Error in secondary fallback: " + e.getMessage());
|
|
875
|
+
call.reject("WebView is not initialized");
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
} catch (Exception e) {
|
|
879
|
+
Log.e("InAppBrowser", "Error closing WebView: " + e.getMessage());
|
|
880
|
+
call.reject("Failed to close WebView: " + e.getMessage());
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
private Bundle getHeaders(PluginCall pluginCall) {
|
|
888
|
+
JSObject headersProvided = pluginCall.getObject("headers");
|
|
889
|
+
Bundle headers = new Bundle();
|
|
890
|
+
if (headersProvided != null) {
|
|
891
|
+
Iterator<String> keys = headersProvided.keys();
|
|
892
|
+
while (keys.hasNext()) {
|
|
893
|
+
String key = keys.next();
|
|
894
|
+
headers.putString(key, headersProvided.getString(key));
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return headers;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
protected void handleOnResume() {
|
|
901
|
+
boolean ok = CustomTabsClient.bindCustomTabsService(getContext(), CUSTOM_TAB_PACKAGE_NAME, connection);
|
|
902
|
+
if (!ok) {
|
|
903
|
+
Log.e(getLogTag(), "Error binding to custom tabs service");
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
protected void handleOnPause() {
|
|
908
|
+
getContext().unbindService(connection);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
public CustomTabsSession getCustomTabsSession() {
|
|
912
|
+
if (customTabsClient == null) {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (currentSession == null) {
|
|
917
|
+
currentSession = customTabsClient.newSession(
|
|
918
|
+
new CustomTabsCallback() {
|
|
919
|
+
@Override
|
|
920
|
+
public void onNavigationEvent(int navigationEvent, Bundle extras) {
|
|
921
|
+
// Only fire browserPageLoaded for Custom Tabs, not for WebView
|
|
922
|
+
if (navigationEvent == NAVIGATION_FINISHED && webViewDialog == null) {
|
|
923
|
+
notifyListeners("browserPageLoaded", new JSObject());
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
return currentSession;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
@Override
|
|
933
|
+
protected void handleOnDestroy() {
|
|
934
|
+
if (webViewDialog != null) {
|
|
935
|
+
try {
|
|
936
|
+
webViewDialog.dismiss();
|
|
937
|
+
} catch (Exception e) {
|
|
938
|
+
// Ignore, dialog may already be dismissed
|
|
939
|
+
}
|
|
940
|
+
webViewDialog = null;
|
|
941
|
+
}
|
|
942
|
+
currentPermissionRequest = null;
|
|
943
|
+
customTabsClient = null;
|
|
944
|
+
currentSession = null;
|
|
945
|
+
super.handleOnDestroy();
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
@PluginMethod
|
|
949
|
+
public void getPluginVersion(final PluginCall call) {
|
|
950
|
+
try {
|
|
951
|
+
final JSObject ret = new JSObject();
|
|
952
|
+
ret.put("version", this.pluginVersion);
|
|
953
|
+
call.resolve(ret);
|
|
954
|
+
} catch (final Exception e) {
|
|
955
|
+
call.reject("Could not get plugin version", e);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
@PluginMethod
|
|
960
|
+
public void updateDimensions(PluginCall call) {
|
|
961
|
+
if (webViewDialog == null) {
|
|
962
|
+
call.reject("WebView is not initialized");
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
Integer width = call.getInt("width");
|
|
967
|
+
Integer height = call.getInt("height");
|
|
968
|
+
Integer x = call.getInt("x");
|
|
969
|
+
Integer y = call.getInt("y");
|
|
970
|
+
|
|
971
|
+
this.getActivity().runOnUiThread(
|
|
972
|
+
new Runnable() {
|
|
973
|
+
@Override
|
|
974
|
+
public void run() {
|
|
975
|
+
try {
|
|
976
|
+
if (webViewDialog != null) {
|
|
977
|
+
webViewDialog.updateDimensions(width, height, x, y);
|
|
978
|
+
call.resolve();
|
|
979
|
+
} else {
|
|
980
|
+
call.reject("WebView is not initialized");
|
|
981
|
+
}
|
|
982
|
+
} catch (Exception e) {
|
|
983
|
+
Log.e("InAppBrowser", "Error updating dimensions: " + e.getMessage());
|
|
984
|
+
call.reject("Failed to update dimensions: " + e.getMessage());
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
}
|
|
238
988
|
);
|
|
239
989
|
}
|
|
240
|
-
return currentSession;
|
|
241
|
-
}
|
|
242
990
|
}
|