
org.robolectric.shadows.ShadowWebView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
An alternative Android testing framework.
The newest version!
package org.robolectric.shadows;
import android.view.ViewGroup.LayoutParams;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.HiddenApi;
import org.robolectric.fakes.RoboWebSettings;
import org.robolectric.util.ReflectionHelpers;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"UnusedDeclaration"})
@Implements(value = WebView.class, inheritImplementationMethods = true)
public class ShadowWebView extends ShadowViewGroup {
@RealObject
private WebView realWebView;
private String lastUrl;
private Map lastAdditionalHttpHeaders;
private HashMap javascriptInterfaces = new HashMap<>();
private WebSettings webSettings = new RoboWebSettings();
private WebViewClient webViewClient = null;
private boolean runFlag = false;
private boolean clearCacheCalled = false;
private boolean clearCacheIncludeDiskFiles = false;
private boolean clearFormDataCalled = false;
private boolean clearHistoryCalled = false;
private boolean clearViewCalled = false;
private boolean destroyCalled = false;
private boolean onPauseCalled = false;
private boolean onResumeCalled = false;
private WebChromeClient webChromeClient;
private boolean canGoBack;
private int goBackInvocations = 0;
private LoadData lastLoadData;
private LoadDataWithBaseURL lastLoadDataWithBaseURL;
@HiddenApi @Implementation
public void ensureProviderCreated() {
final ClassLoader classLoader = getClass().getClassLoader();
Class> webViewProviderClass = getClassNamed("android.webkit.WebViewProvider");
Field mProvider;
try {
mProvider = WebView.class.getDeclaredField("mProvider");
mProvider.setAccessible(true);
if (mProvider.get(realView) == null) {
Object provider = Proxy.newProxyInstance(classLoader, new Class[]{webViewProviderClass}, new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getViewDelegate") || method.getName().equals("getScrollDelegate")) {
return Proxy.newProxyInstance(classLoader, new Class[]{
getClassNamed("android.webkit.WebViewProvider$ViewDelegate"),
getClassNamed("android.webkit.WebViewProvider$ScrollDelegate")
}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return nullish(method);
}
});
}
return nullish(method);
}
});
mProvider.set(realView, provider);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Implementation
public void setLayoutParams(LayoutParams params) {
ReflectionHelpers.setField(realWebView, "mLayoutParams", params);
}
private Object nullish(Method method) {
Class> returnType = method.getReturnType();
if (returnType.equals(long.class)
|| returnType.equals(double.class)
|| returnType.equals(int.class)
|| returnType.equals(float.class)
|| returnType.equals(short.class)
|| returnType.equals(byte.class)
) return 0;
if (returnType.equals(char.class)) return '\0';
if (returnType.equals(boolean.class)) return false;
return null;
}
private Class> getClassNamed(String className) {
try {
return getClass().getClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Implementation
public void loadUrl(String url) {
loadUrl(url, null);
}
@Implementation
public void loadUrl(String url, Map additionalHttpHeaders) {
lastUrl = url;
if (additionalHttpHeaders != null) {
this.lastAdditionalHttpHeaders = Collections.unmodifiableMap(additionalHttpHeaders);
} else {
this.lastAdditionalHttpHeaders = null;
}
}
@Implementation
public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {
lastLoadDataWithBaseURL = new LoadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
}
@Implementation
public void loadData(String data, String mimeType, String encoding) {
lastLoadData = new LoadData(data, mimeType, encoding);
}
/**
* @return the last loaded url
*/
public String getLastLoadedUrl() {
return lastUrl;
}
/**
* @return the additional Http headers that in the same request with last loaded url
*/
public Map getLastAdditionalHttpHeaders() {
return lastAdditionalHttpHeaders;
}
@Implementation
public WebSettings getSettings() {
return webSettings;
}
@Implementation
public void setWebViewClient(WebViewClient client) {
webViewClient = client;
}
@Implementation
public void setWebChromeClient(WebChromeClient client) {
webChromeClient = client;
}
public WebViewClient getWebViewClient() {
return webViewClient;
}
@Implementation
public void addJavascriptInterface(Object obj, String interfaceName) {
javascriptInterfaces.put(interfaceName, obj);
}
public Object getJavascriptInterface(String interfaceName) {
return javascriptInterfaces.get(interfaceName);
}
@Implementation
public void clearCache(boolean includeDiskFiles) {
clearCacheCalled = true;
clearCacheIncludeDiskFiles = includeDiskFiles;
}
public boolean wasClearCacheCalled() {
return clearCacheCalled;
}
public boolean didClearCacheIncludeDiskFiles() {
return clearCacheIncludeDiskFiles;
}
@Implementation
public void clearFormData() {
clearFormDataCalled = true;
}
public boolean wasClearFormDataCalled() {
return clearFormDataCalled;
}
@Implementation
public void clearHistory() {
clearHistoryCalled = true;
}
public boolean wasClearHistoryCalled() {
return clearHistoryCalled;
}
@Implementation
public void clearView() {
clearViewCalled = true;
}
public boolean wasClearViewCalled() {
return clearViewCalled;
}
@Implementation
public void onPause(){
onPauseCalled = true;
}
public boolean wasOnPauseCalled() {
return onPauseCalled;
}
@Implementation
public void onResume() {
onResumeCalled = true;
}
public boolean wasOnResumeCalled() {
return onResumeCalled;
}
@Implementation
public void destroy() {
destroyCalled = true;
}
public boolean wasDestroyCalled() {
return destroyCalled;
}
@Override @Implementation
public void post(Runnable action) {
action.run();
runFlag = true;
}
public boolean getRunFlag() {
return runFlag;
}
/**
* @return webChromeClient
*/
public WebChromeClient getWebChromeClient() {
return webChromeClient;
}
@Implementation
public boolean canGoBack() {
return canGoBack;
}
@Implementation
public void goBack() {
goBackInvocations++;
}
@Implementation
public static String findAddress(String addr) {
return null;
}
/**
* @return goBackInvocations the number of times {@code android.webkit.WebView#goBack()}
* was invoked
*/
public int getGoBackInvocations() {
return goBackInvocations;
}
/**
* Sets the value to return from {@code android.webkit.WebView#canGoBack()}
*
* @param canGoBack Value to return from {@code android.webkit.WebView#canGoBack()}
*/
public void setCanGoBack(boolean canGoBack) {
this.canGoBack = canGoBack;
}
public LoadData getLastLoadData() {
return lastLoadData;
}
public LoadDataWithBaseURL getLastLoadDataWithBaseURL() {
return lastLoadDataWithBaseURL;
}
public static void setWebContentsDebuggingEnabled(boolean enabled) { }
public class LoadDataWithBaseURL {
public final String baseUrl;
public final String data;
public final String mimeType;
public final String encoding;
public final String historyUrl;
public LoadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {
this.baseUrl = baseUrl;
this.data = data;
this.mimeType = mimeType;
this.encoding = encoding;
this.historyUrl = historyUrl;
}
}
public class LoadData {
public final String data;
public final String mimeType;
public final String encoding;
public LoadData(String data, String mimeType, String encoding) {
this.data = data;
this.mimeType = mimeType;
this.encoding = encoding;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy