feat: Android - add first request headers and cookies as options

This commit is contained in:
Ramo, Davide 2023-09-26 08:13:35 +02:00
parent 6f85408ec4
commit c80e74f238

View File

@ -24,6 +24,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Parcelable;
import android.provider.Browser;
import android.content.res.Resources;
@ -35,6 +37,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.InputType;
import android.util.Base64;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
@ -63,6 +66,9 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.Config;
import org.apache.cordova.CordovaArgs;
@ -80,9 +86,12 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;
@SuppressLint("SetJavaScriptEnabled")
public class InAppBrowser extends CordovaPlugin {
@ -120,8 +129,10 @@ public class InAppBrowser extends CordovaPlugin {
private static final String FULLSCREEN = "fullscreen";
private static final int TOOLBAR_HEIGHT = 48;
private static final String COOKIES = "cookies";
private static final String HEADERS = "headers";
private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR, COOKIES, HEADERS);
private InAppBrowserDialog dialog;
private WebView inAppWebView;
@ -152,6 +163,12 @@ public class InAppBrowser extends CordovaPlugin {
private String[] allowedSchemes;
private InAppBrowserClient currentClient;
@Nullable
private Map<String, String> headers;
@Nullable
private Map<String, String> cookies;
/**
* Executes the request and returns PluginResult.
*
@ -715,6 +732,16 @@ public class InAppBrowser extends CordovaPlugin {
if (fullscreenSet != null) {
fullscreen = fullscreenSet.equals("yes") ? true : false;
}
String headersSet = features.get(HEADERS);
if (headersSet != null) {
headers = deserializeMapOption(headersSet);
}
String cookiesSet = features.get(COOKIES);
if (cookiesSet != null) {
cookies = deserializeMapOption(cookiesSet);
}
}
final CordovaWebView thatWebView = this.webView;
@ -948,30 +975,30 @@ public class InAppBrowser extends CordovaPlugin {
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setBuiltInZoomControls(showZoomControls);
settings.setPluginState(android.webkit.WebSettings.PluginState.ON);
// download event
inAppWebView.setDownloadListener(
new DownloadListener(){
public void onDownloadStart(
String url, String userAgent, String contentDisposition, String mimetype, long contentLength
){
try{
JSONObject succObj = new JSONObject();
succObj.put("type", DOWNLOAD_EVENT);
succObj.put("url",url);
succObj.put("userAgent",userAgent);
succObj.put("contentDisposition",contentDisposition);
succObj.put("mimetype",mimetype);
succObj.put("contentLength",contentLength);
sendUpdate(succObj, true);
}
catch(Exception e){
LOG.e(LOG_TAG,e.getMessage());
new DownloadListener(){
public void onDownloadStart(
String url, String userAgent, String contentDisposition, String mimetype, long contentLength
){
try{
JSONObject succObj = new JSONObject();
succObj.put("type", DOWNLOAD_EVENT);
succObj.put("url",url);
succObj.put("userAgent",userAgent);
succObj.put("contentDisposition",contentDisposition);
succObj.put("mimetype",mimetype);
succObj.put("contentLength",contentLength);
sendUpdate(succObj, true);
}
catch(Exception e){
LOG.e(LOG_TAG,e.getMessage());
}
}
}
}
);
);
// Add postMessage interface
class JsObject {
@ -1011,16 +1038,10 @@ public class InAppBrowser extends CordovaPlugin {
}
settings.setDomStorageEnabled(true);
if (clearAllCache) {
CookieManager.getInstance().removeAllCookie();
} else if (clearSessionCache) {
CookieManager.getInstance().removeSessionCookie();
}
// Enable Thirdparty Cookies
CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
inAppWebView.loadUrl(url);
inAppWebView.loadUrl(url, headers);
inAppWebView.setId(Integer.valueOf(6));
inAppWebView.getSettings().setLoadWithOverviewMode(true);
inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);
@ -1071,10 +1092,109 @@ public class InAppBrowser extends CordovaPlugin {
}
}
};
setCookies(clearAllCache, clearSessionCache, cookies);
this.cordova.getActivity().runOnUiThread(runnable);
return "";
}
private void setCookies(boolean clearAllCache,
boolean clearSessionCache,
@Nullable Map<String, String> cookies) {
int operations = 0;
if (clearAllCache) {
operations++;
}
if (clearSessionCache) {
operations++;
}
if (cookies != null) {
operations += cookies.size();
}
CountDownLatch cookiesCountdown = new CountDownLatch(operations);
Runnable cookiesRunnable = cookiesRunnable(
cookiesCountdown,
clearAllCache,
clearSessionCache,
cookies);
//CookieManager setCookie needs a background Looper to await completion
HandlerThread handlerThread = new HandlerThread("backgroundThread");
if (!handlerThread.isAlive())
handlerThread.start();
Handler threadHandler = new Handler(handlerThread.getLooper());
threadHandler.post(cookiesRunnable); //runs on main thread
try {
cookiesCountdown.await();
} catch (InterruptedException e) {
LOG.e(LOG_TAG, "cookies set was interrupted by timeout.", e);
}
handlerThread.quitSafely();
}
@NonNull
private Runnable cookiesRunnable(
CountDownLatch cookiesCountdown,
boolean clearAllCache,
boolean clearSessionCache,
@Nullable Map<String, String> cookies) {
return () -> {
if (clearAllCache) {
CookieManager.getInstance().removeAllCookies(value -> {
if (!value) {
LOG.e(LOG_TAG, "unable to removeAllCookies in CookieManager!");
}
cookiesCountdown.countDown();
});
} else if (clearSessionCache) {
CookieManager.getInstance().removeSessionCookies(value -> {
if (!value) {
LOG.e(LOG_TAG, "unable to removeSessionCookies in CookieManager!");
}
cookiesCountdown.countDown();
});
}
//Set all cookies from options
if (cookies != null && cookies.size() > 0) {
for (String cookieKey : cookies.keySet()) {
CookieManager.getInstance().setCookie(cookieKey, cookies.get(cookieKey), value -> {
if (!value) {
LOG.e(LOG_TAG, "unable to set the cookie in CookieManager!");
}
cookiesCountdown.countDown();
});
}
}
};
}
@Nullable
private Map<String, String> deserializeMapOption(@NonNull String serializedMapOption) {
Map<String, String> result = new HashMap<>();
String base64 = serializedMapOption.replace("@", "=");
String json = new String(Base64.decode(base64, Base64.DEFAULT));
try {
JSONObject jsonObject = new JSONObject(json);
for (Iterator<String> keys = jsonObject.keys(); keys.hasNext(); ) {
String key = keys.next();
result.put(key, jsonObject.getString(key));
}
} catch (JSONException e) {
LOG.e(LOG_TAG, "headers options are not serialized as a valid json.", e);
return null;
}
return result;
}
/**
* Create a new plugin success result and send it back to JavaScript
*