package com.mopub.mobileads;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Handler;
import android.webkit.JavascriptInterface;
import com.mopub.common.AdReport;
import static com.mopub.common.util.VersionCode.HONEYCOMB;
import static com.mopub.common.util.VersionCode.currentApiLevel;
import static com.mopub.mobileads.CustomEventInterstitial.CustomEventInterstitialListener;
public class HtmlInterstitialWebView extends BaseHtmlWebView {
private Handler mHandler;
protected static final String MOPUB_JS_INTERFACE_NAME = "mopubUriInterface";
interface MoPubUriJavascriptFireFinishLoadListener {
abstract void onInterstitialLoaded();
}
public HtmlInterstitialWebView(Context context, AdReport adReport) {
super(context, adReport);
mHandler = new Handler();
}
public void init(final CustomEventInterstitialListener customEventInterstitialListener, boolean isScrollable, String redirectUrl, String clickthroughUrl) {
super.init(isScrollable);
HtmlInterstitialWebViewListener htmlInterstitialWebViewListener = new HtmlInterstitialWebViewListener(customEventInterstitialListener);
HtmlWebViewClient htmlWebViewClient = new HtmlWebViewClient(htmlInterstitialWebViewListener, this, clickthroughUrl, redirectUrl);
setWebViewClient(htmlWebViewClient);
addMoPubUriJavascriptInterface(new MoPubUriJavascriptFireFinishLoadListener() {
@Override
public void onInterstitialLoaded() {
if (!mIsDestroyed) {
customEventInterstitialListener.onInterstitialLoaded();
}
}
});
}
private void postHandlerRunnable(Runnable r) {
mHandler.post(r);
}
/*
* XXX (2/15/12): This is a workaround for a problem on ICS devices where
* WebViews with layout height WRAP_CONTENT can mysteriously render with
* zero height. This seems to happen when calling loadData() with HTML that
* sets window.location during its "onload" event. We use loadData() when
* displaying interstitials, and our creatives use window.location to
* communicate ad loading status to AdViews. This results in zero-height
* interstitials. We counteract this by using a Javascript interface object
* to signal loading status, rather than modifying window.location.
*/
void addMoPubUriJavascriptInterface(final MoPubUriJavascriptFireFinishLoadListener moPubUriJavascriptFireFinishLoadListener) {
final class MoPubUriJavascriptInterface {
// This method appears to be unused, since it will only be called from JavaScript.
@SuppressWarnings("unused")
@JavascriptInterface
public boolean fireFinishLoad() {
HtmlInterstitialWebView.this.postHandlerRunnable(new Runnable() {
@Override
public void run() {
moPubUriJavascriptFireFinishLoadListener.onInterstitialLoaded();
}
});
return true;
}
}
addJavascriptInterface(new MoPubUriJavascriptInterface(), MOPUB_JS_INTERFACE_NAME);
}
@TargetApi(11)
@Override
public void destroy() {
if (currentApiLevel().isAtLeast(HONEYCOMB)) {
removeJavascriptInterface(MOPUB_JS_INTERFACE_NAME);
}
super.destroy();
}
static class HtmlInterstitialWebViewListener implements HtmlWebViewListener {
private final CustomEventInterstitialListener mCustomEventInterstitialListener;
public HtmlInterstitialWebViewListener(CustomEventInterstitialListener customEventInterstitialListener) {
mCustomEventInterstitialListener = customEventInterstitialListener;
}
@Override
public void onLoaded(BaseHtmlWebView mHtmlWebView) {
mCustomEventInterstitialListener.onInterstitialLoaded();
}
@Override
public void onFailed(MoPubErrorCode errorCode) {
mCustomEventInterstitialListener.onInterstitialFailed(errorCode);
}
@Override
public void onClicked() {
mCustomEventInterstitialListener.onInterstitialClicked();
}
@Override
public void onCollapsed() {
// Ignored
}
}
}