Skip to content

Commit 58b4042

Browse files
HOTFIX - Fixed issue with Smart Lock save not working on release build
1 parent 5a1d83f commit 58b4042

File tree

1 file changed

+42
-32
lines changed

1 file changed

+42
-32
lines changed

app/src/main/java/com/sakaimobile/development/sakaiclient20/networking/utilities/CASWebViewClient.java

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.sakaimobile.development.sakaiclient20.networking.utilities;
22

3-
import android.graphics.Bitmap;
43
import android.os.Build;
54
import android.webkit.CookieManager;
65
import android.webkit.WebResourceResponse;
@@ -69,12 +68,12 @@ public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
6968
// We only need to intercept once authentication is complete, as the
7069
// the cookies do not change afterwards
7170
if (url.startsWith("https://sakai.rutgers.edu/portal") && !gotHeaders)
72-
return handleRequest(url);
71+
return handleRequest(view, url);
7372

7473
return super.shouldInterceptRequest(view, url);
7574
}
7675

77-
private WebResourceResponse handleRequest(String url) {
76+
private WebResourceResponse handleRequest(WebView view, String url) {
7877
// After intercepting the request, we need to handle it
7978
// ourselves. This is done by creating an OkHttp3 Call,
8079
// which we add the Sakai cookies to. Without the cookies,
@@ -93,42 +92,53 @@ private WebResourceResponse handleRequest(String url) {
9392
return null;
9493
}
9594

96-
// After getting the response from Sakai, we can get the
97-
// headers if it has what we want. Specifically, we need
98-
// the X-Sakai-Session cookie.
99-
String sakaiSessionHeader = response.headers().get("x-sakai-session");
100-
if (sakaiSessionHeader != null && !gotHeaders) {
101-
gotHeaders = true;
102-
sakaiLoadedListener.onLoginSuccess(username, password);
103-
}
95+
// onPageStarted is not a good place to intercept credentials because
96+
// it is called too late in the release build variant. Instead, perform that
97+
// operation here. Call to post() is necessary for eval to run on the UI thread.
98+
view.post(() -> {
99+
// It is possible that we are moving away from this page,
100+
// so in case it is the login page, extract the username and password
101+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
102+
// We get both credentials as an array to prevent synchronization issues
103+
// with getting username and password separately.
104+
view.evaluateJavascript(
105+
"[document.querySelector('#username').value, document.querySelector('#password').value]",
106+
credentials -> {
107+
// JS-evaluated strings have double quotes surrounding them, necessitating
108+
// all the null and length checks, and odd substring indices.
109+
if(credentials != null && !"null".equals(credentials)
110+
&& !"undefined".equals(credentials) && credentials.length() > 7) {
111+
final String separator = "\",\"";
112+
int separatorIndex = credentials.indexOf(separator);
113+
this.username = credentials.substring(2, separatorIndex);
114+
this.password = credentials.substring(separatorIndex + separator.length(), credentials.length() - 2);
115+
}
116+
// Whether we got username and password or not, the authentication was
117+
// successful and this must be indicated to the LoginActivity
118+
tryCompleteLogin(response);
119+
}
120+
);
121+
} else {
122+
// Can't evaluate JS, just login as usual
123+
tryCompleteLogin(response);
124+
}
125+
});
104126

105127
// We need to return a WebResourceResponse, otherwise the
106128
// WebView will think that the request is hanging. The WebView
107129
// renders this response.
108130
// We do not need to modify the mimeType or encoding of the response.
109-
return new WebResourceResponse(null, null,
110-
response.body().byteStream()
111-
);
131+
return new WebResourceResponse(null, null, response.body().byteStream());
112132
}
113133

114-
@Override
115-
public void onPageStarted(WebView view, String url, Bitmap favicon) {
116-
super.onPageStarted(view, url, favicon);
117-
// It is possible that we are moving away from this page,
118-
// so in case it is the login page, extract the username and password
119-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
120-
// JS-evaluated strings have double quotes surrounding them, necessitating
121-
// all the null and length checks
122-
view.evaluateJavascript("document.querySelector('#username').value", username -> {
123-
if(username != null && !"null".equals(username) && username.length() > 2) {
124-
this.username = username.substring(1, username.length() - 1);
125-
}
126-
});
127-
view.evaluateJavascript("document.querySelector('#password').value", password -> {
128-
if(password != null && !"null".equals(password) && password.length() > 2) {
129-
this.password = password.substring(1, password.length() - 1);
130-
}
131-
});
134+
private void tryCompleteLogin(Response response) {
135+
// After getting the response from Sakai, we can get the
136+
// headers if it has what we want. Specifically, we need
137+
// the X-Sakai-Session cookie.
138+
String sakaiSessionHeader = response.headers().get("x-sakai-session");
139+
if (sakaiSessionHeader != null && !gotHeaders) {
140+
gotHeaders = true;
141+
sakaiLoadedListener.onLoginSuccess(username, password);
132142
}
133143
}
134144
}

0 commit comments

Comments
 (0)