package io.myweb;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import io.myweb.http.Headers;
import io.myweb.http.HttpException;
import io.myweb.http.Request;
import io.myweb.http.Response;
public class MyWebViewClient extends WebViewClient {
private static final String LOG_TAG = MyWebViewClient.class.getName();
private static final String PREFIX = "http://myweb/";
private final WebContext webContext;
private final String root;
private WebViewClient delegate = new WebViewClient();
private CookieManager cookieManager;
public MyWebViewClient(WebContext ec, String packageName) {
super();
webContext = ec;
root = PREFIX + packageName;
}
public String getRootUrl() {
return root + "/";
}
public CookieManager getCookieManager(Context ctx) {
if (cookieManager == null) {
CookieSyncManager.createInstance(ctx);
cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
}
return cookieManager;
}
private WebResourceResponse createWebResponse(Response response) {
String contentType = response.getContentType();
int idx = contentType.indexOf(";");
if (idx > 0) contentType = contentType.substring(0, idx);
return new WebResourceResponse(contentType, "utf-8",
response.getBodyAsInputStream());
}
@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, final String url) {
// Log.d(LOG_TAG, "Url: " + url);
if (url.startsWith(root) && webContext != null) {
CookieManager cm = getCookieManager(view.getContext());
Request request = new Request(url.substring(root.length()));
// Issue #65786 KitKat 4.2 (calling getCookie() on IO thread blocks WebView)
// normally we would write: String cookies = cm.getCookie(url);
// but this has to be called from the main thread in KitKat
// -----------------------------------------------------------
Handler handler = new Handler(Looper.getMainLooper());
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> cookies = new AtomicReference<String>();
handler.post( new Runnable() {
@Override
public void run() {
cookies.set(CookieManager.getInstance().getCookie(url));
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {}
// -----------------------------------------------------------
request.getHeaders().update(Headers.REQUEST.COOKIE, cookies.get());
try {
// Log.d(LOG_TAG, "Request: "+request.getURI().toString());
final Response response = webContext.getRequestProcessor().processRequest(request);
// Log.d(LOG_TAG, "Response: "+response.toString());
handler.post( new Runnable() {
@Override
public void run() {
CookieManager cm = getCookieManager(view.getContext());
for (Headers.Header h: response.getHeaders().findAll(Headers.RESPONSE.SET_COOKIE)) {
cm.setCookie(h.getName(), h.getValue());
}
CookieSyncManager.getInstance().sync();
}
});
return createWebResponse(response.withIdentity());
} catch (IOException e) {
Log.e(LOG_TAG, e.getMessage(), e);
} catch (HttpException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
}
return delegate.shouldInterceptRequest(view, url);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return delegate.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
delegate.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
delegate.onPageFinished(view, url);
}
@Override
public void onLoadResource(WebView view, String url) {
delegate.onLoadResource(view, url);
}
@Override
public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) {
delegate.onTooManyRedirects(view, cancelMsg, continueMsg);
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
delegate.onReceivedError(view, errorCode, description, failingUrl);
}
@Override
public void onFormResubmission(WebView view, Message dontResend, Message resend) {
delegate.onFormResubmission(view, dontResend, resend);
}
@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
delegate.doUpdateVisitedHistory(view, url, isReload);
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
delegate.onReceivedSslError(view, handler, error);
}
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
delegate.onReceivedHttpAuthRequest(view, handler, host, realm);
}
@Override
public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
return delegate.shouldOverrideKeyEvent(view, event);
}
@Override
public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
delegate.onUnhandledKeyEvent(view, event);
}
@Override
public void onScaleChanged(WebView view, float oldScale, float newScale) {
delegate.onScaleChanged(view, oldScale, newScale);
}
@Override
public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
delegate.onReceivedLoginRequest(view, realm, account, args);
}
public void setWebViewClient(WebViewClient client) {
if (client != null) delegate = client;
}
}