capacitor-sso-webview 0.0.3 → 0.0.5
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.
|
@@ -16,190 +16,196 @@ import android.widget.TextView;
|
|
|
16
16
|
|
|
17
17
|
public class SSOWebView {
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
19
|
+
public interface Listener {
|
|
20
|
+
void onRedirectIntercepted(String url, String code, String state, String body);
|
|
21
|
+
|
|
22
|
+
void onCancelled();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private Dialog dialog;
|
|
26
|
+
private WebView webView;
|
|
27
|
+
private boolean alreadyRedirected = false;
|
|
28
|
+
|
|
29
|
+
public void open(
|
|
30
|
+
final Activity activity,
|
|
31
|
+
final String url,
|
|
32
|
+
final String redirectHost,
|
|
33
|
+
final String redirectPathContains,
|
|
34
|
+
final String title,
|
|
35
|
+
final Listener listener) {
|
|
36
|
+
alreadyRedirected = false;
|
|
37
|
+
|
|
38
|
+
dialog = new Dialog(activity, android.R.style.Theme_Light_NoTitleBar_Fullscreen);
|
|
39
|
+
|
|
40
|
+
LinearLayout root = new LinearLayout(activity);
|
|
41
|
+
root.setOrientation(LinearLayout.VERTICAL);
|
|
42
|
+
root.setLayoutParams(new LinearLayout.LayoutParams(
|
|
43
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
44
|
+
ViewGroup.LayoutParams.MATCH_PARENT));
|
|
45
|
+
|
|
46
|
+
/* ── Header bar ── */
|
|
47
|
+
LinearLayout header = new LinearLayout(activity);
|
|
48
|
+
header.setOrientation(LinearLayout.HORIZONTAL);
|
|
49
|
+
header.setBackgroundColor(Color.parseColor("#1A2B4A"));
|
|
50
|
+
header.setPadding(48, 72, 48, 48);
|
|
51
|
+
header.setGravity(Gravity.CENTER_VERTICAL);
|
|
52
|
+
header.setLayoutParams(new LinearLayout.LayoutParams(
|
|
53
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
54
|
+
ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
55
|
+
|
|
56
|
+
TextView tvTitle = new TextView(activity);
|
|
57
|
+
tvTitle.setText(title != null ? title : "Login");
|
|
58
|
+
tvTitle.setTextColor(Color.WHITE);
|
|
59
|
+
tvTitle.setTextSize(16);
|
|
60
|
+
tvTitle.setLayoutParams(new LinearLayout.LayoutParams(
|
|
61
|
+
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1 f));
|
|
62
|
+
|
|
63
|
+
TextView btnClose = new TextView(activity);
|
|
64
|
+
btnClose.setText("Tutup");
|
|
65
|
+
btnClose.setTextColor(Color.WHITE);
|
|
66
|
+
btnClose.setTextSize(14);
|
|
67
|
+
btnClose.setPadding(32, 16, 16, 16);
|
|
68
|
+
btnClose.setOnClickListener(v -> {
|
|
69
|
+
boolean wasRedirected = alreadyRedirected;
|
|
70
|
+
dismiss();
|
|
71
|
+
if (!wasRedirected && listener != null)
|
|
72
|
+
listener.onCancelled();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
header.addView(tvTitle);
|
|
76
|
+
header.addView(btnClose);
|
|
77
|
+
|
|
78
|
+
/* ── WebView ── */
|
|
79
|
+
webView = new WebView(activity);
|
|
80
|
+
WebSettings s = webView.getSettings();
|
|
81
|
+
s.setJavaScriptEnabled(true);
|
|
82
|
+
s.setDomStorageEnabled(true);
|
|
83
|
+
s.setDatabaseEnabled(true);
|
|
84
|
+
s.setUseWideViewPort(true);
|
|
85
|
+
s.setLoadWithOverviewMode(true);
|
|
86
|
+
s.setSupportZoom(false);
|
|
87
|
+
s.setJavaScriptCanOpenWindowsAutomatically(true);
|
|
88
|
+
|
|
89
|
+
CookieManager cm = CookieManager.getInstance();
|
|
90
|
+
cm.setAcceptCookie(true);
|
|
91
|
+
cm.setAcceptThirdPartyCookies(webView, true);
|
|
92
|
+
|
|
93
|
+
webView.setWebViewClient(new WebViewClient() {
|
|
94
|
+
|
|
95
|
+
@Override
|
|
96
|
+
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
|
97
|
+
Uri u = request.getUrl();
|
|
98
|
+
String host = u.getHost();
|
|
99
|
+
String path = u.getPath();
|
|
100
|
+
|
|
101
|
+
boolean isRedirect = host != null && host.equalsIgnoreCase(redirectHost) &&
|
|
102
|
+
path != null && path.toLowerCase()
|
|
103
|
+
.contains(redirectPathContains.toLowerCase());
|
|
104
|
+
|
|
105
|
+
if (isRedirect && !alreadyRedirected) {
|
|
106
|
+
alreadyRedirected = true;
|
|
107
|
+
/* Biarkan WebView navigate — server akan return JSON body */
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@Override
|
|
114
|
+
public void onPageFinished(WebView view, String pageUrl) {
|
|
115
|
+
super.onPageFinished(view, pageUrl);
|
|
116
|
+
|
|
117
|
+
Uri u = Uri.parse(pageUrl);
|
|
118
|
+
String host = u.getHost();
|
|
119
|
+
String path = u.getPath();
|
|
120
|
+
|
|
121
|
+
boolean isRedirectPage = host != null && host.equalsIgnoreCase(redirectHost) &&
|
|
122
|
+
path != null && path.toLowerCase()
|
|
123
|
+
.contains(redirectPathContains.toLowerCase());
|
|
124
|
+
|
|
125
|
+
if (!isRedirectPage)
|
|
126
|
+
return;
|
|
127
|
+
|
|
128
|
+
final String finalUrl = pageUrl;
|
|
129
|
+
final String finalCode = u.getQueryParameter("code") != null ?
|
|
130
|
+
u.getQueryParameter("code") :
|
|
131
|
+
"";
|
|
132
|
+
final String finalState = u.getQueryParameter("state") != null ?
|
|
133
|
+
u.getQueryParameter("state") :
|
|
134
|
+
"";
|
|
135
|
+
|
|
136
|
+
/* Delay 150ms — beri waktu body JSON ter-render ke DOM */
|
|
137
|
+
view.postDelayed(new Runnable() {
|
|
138
|
+
@Override
|
|
139
|
+
public void run() {
|
|
140
|
+
if (webView == null) return;
|
|
141
|
+
webView.evaluateJavascript(
|
|
142
|
+
"(function(){" +
|
|
143
|
+
" var t = document.body" +
|
|
144
|
+
" ? (document.body.innerText || document.body.textContent || '')" +
|
|
145
|
+
" : '';" +
|
|
146
|
+
" return t.trim();" +
|
|
147
|
+
"})()",
|
|
148
|
+
value -> {
|
|
149
|
+
String body = value;
|
|
150
|
+
if (body != null) {
|
|
151
|
+
if (body.startsWith("\"") && body.endsWith("\""))
|
|
152
|
+
body = body.substring(1, body.length() - 1);
|
|
153
|
+
body = body.replace("\\\"", "\"")
|
|
154
|
+
.replace("\\n", "\n")
|
|
155
|
+
.replace("\\r", "")
|
|
156
|
+
.replace("\\/", "/");
|
|
112
157
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private void dismiss() {
|
|
171
|
-
SSOWebView.this.dismiss();
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
webView.setLayoutParams(new LinearLayout.LayoutParams(
|
|
176
|
-
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f
|
|
177
|
-
));
|
|
178
|
-
|
|
179
|
-
root.addView(header);
|
|
180
|
-
root.addView(webView);
|
|
181
|
-
|
|
182
|
-
dialog.setContentView(root);
|
|
183
|
-
dialog.setCancelable(true);
|
|
184
|
-
dialog.setOnCancelListener(d -> {
|
|
185
|
-
if (!alreadyRedirected && listener != null) listener.onCancelled();
|
|
186
|
-
});
|
|
187
|
-
dialog.show();
|
|
188
|
-
|
|
189
|
-
webView.loadUrl(url);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
public void dismiss() {
|
|
193
|
-
try {
|
|
194
|
-
if (webView != null) {
|
|
195
|
-
webView.stopLoading();
|
|
196
|
-
webView.destroy();
|
|
197
|
-
webView = null;
|
|
198
|
-
}
|
|
199
|
-
if (dialog != null && dialog.isShowing()) {
|
|
200
|
-
dialog.dismiss();
|
|
201
|
-
}
|
|
202
|
-
dialog = null;
|
|
203
|
-
} catch (Exception ignored) {}
|
|
204
|
-
}
|
|
158
|
+
final String finalBody = (body != null) ? body : "";
|
|
159
|
+
android.util.Log.d("SSOWebView",
|
|
160
|
+
"body len=" + finalBody.length() +
|
|
161
|
+
" preview=" + finalBody.substring(
|
|
162
|
+
0, Math.min(120, finalBody.length())));
|
|
163
|
+
|
|
164
|
+
/* FIX: gunakan outer class reference */
|
|
165
|
+
activity.runOnUiThread(() -> SSOWebView.this.dismiss());
|
|
166
|
+
|
|
167
|
+
if (listener != null)
|
|
168
|
+
listener.onRedirectIntercepted(
|
|
169
|
+
finalUrl, finalCode, finalState, finalBody);
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}, 150);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private void dismiss() {
|
|
177
|
+
SSOWebView.this.dismiss();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
webView.setLayoutParams(new LinearLayout.LayoutParams(
|
|
182
|
+
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1 f));
|
|
183
|
+
|
|
184
|
+
root.addView(header);
|
|
185
|
+
root.addView(webView);
|
|
186
|
+
|
|
187
|
+
dialog.setContentView(root);
|
|
188
|
+
dialog.setCancelable(true);
|
|
189
|
+
dialog.setOnCancelListener(d -> {
|
|
190
|
+
if (!alreadyRedirected && listener != null)
|
|
191
|
+
listener.onCancelled();
|
|
192
|
+
});
|
|
193
|
+
dialog.show();
|
|
194
|
+
|
|
195
|
+
webView.loadUrl(url);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public void dismiss() {
|
|
199
|
+
try {
|
|
200
|
+
if (webView != null) {
|
|
201
|
+
webView.stopLoading();
|
|
202
|
+
webView.destroy();
|
|
203
|
+
webView = null;
|
|
204
|
+
}
|
|
205
|
+
if (dialog != null && dialog.isShowing()) {
|
|
206
|
+
dialog.dismiss();
|
|
207
|
+
}
|
|
208
|
+
dialog = null;
|
|
209
|
+
} catch (Exception ignored) {}
|
|
210
|
+
}
|
|
205
211
|
}
|
|
@@ -33,12 +33,13 @@ public class SSOWebViewPlugin extends Plugin {
|
|
|
33
33
|
title,
|
|
34
34
|
new SSOWebView.Listener() {
|
|
35
35
|
@Override
|
|
36
|
-
public void onRedirectIntercepted(String u, String code,
|
|
36
|
+
public void onRedirectIntercepted(String u, String code,
|
|
37
|
+
String state, String body) {
|
|
37
38
|
JSObject ret = new JSObject();
|
|
38
39
|
ret.put("url", u);
|
|
39
40
|
ret.put("code", code);
|
|
40
41
|
ret.put("state", state);
|
|
41
|
-
ret.put("body", body);
|
|
42
|
+
ret.put("body", body); // ← TAMBAHAN
|
|
42
43
|
notifyListeners("ssoRedirect", ret);
|
|
43
44
|
}
|
|
44
45
|
|