WebViewApp.java 源代码


package com.unity3d.services.core.webview;

import android.os.Build;
import android.os.ConditionVariable;
import android.os.Looper;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebViewClient;
import com.unity3d.services.ads.api.AdUnit;
import com.unity3d.services.core.configuration.Configuration;
import com.unity3d.services.core.configuration.InitializeThread;
import com.unity3d.services.core.log.DeviceLog;
import com.unity3d.services.core.misc.Utilities;
import com.unity3d.services.core.misc.ViewUtilities;
import com.unity3d.services.core.properties.ClientProperties;
import com.unity3d.services.core.properties.SdkProperties;
import com.unity3d.services.core.request.SDKMetrics;
import com.unity3d.services.core.webview.bridge.CallbackStatus;
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
import com.unity3d.services.core.webview.bridge.Invocation;
import com.unity3d.services.core.webview.bridge.NativeCallback;
import com.unity3d.services.core.webview.bridge.WebViewBridge;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;
import org.json.JSONArray;
import org.json.JSONException;

public class WebViewApp implements IWebViewBridgeInvoker {
    private static final int INVOKE_JS_CHARS_LENGTH = 22;
    private static ConditionVariable _conditionVariable;
    private static WebViewApp _currentApp;
    private Configuration _configuration;
    private HashMap<String, NativeCallback> _nativeCallbacks;
    private boolean _webAppLoaded;
    private WebView _webView;
    private static AtomicReference<Boolean> _initialized = new AtomicReference<>(Boolean.FALSE);
    private static AtomicReference<String> _webAppFailureMessage = new AtomicReference<>();
    private static AtomicReference<Integer> _webAppFailureCode = new AtomicReference<>();

    private class WebAppChromeClient extends WebChromeClient {
        private WebAppChromeClient() {
        }

        @Override
        public void onConsoleMessage(String str, int i6, String str2) {
            File file;
            try {
                file = new File(str2);
            } catch (Exception e6) {
                DeviceLog.exception("Could not handle sourceId", e6);
                file = null;
            }
            if (file != null) {
                file.getName();
            }
        }
    }

    private class WebAppClient extends WebViewClient {
        private WebAppClient() {
        }

        @Override
        public void onPageFinished(android.webkit.WebView webView, String str) {
            super.onPageFinished(webView, str);
            DeviceLog.debug("onPageFinished url: " + str);
        }

        @Override
        public void onReceivedError(android.webkit.WebView webView, WebResourceRequest webResourceRequest, WebResourceError webResourceError) {
            super.onReceivedError(webView, webResourceRequest, webResourceError);
            if (webView != null) {
                DeviceLog.error("WEBVIEW_ERROR: " + webView.toString());
            }
            if (webResourceRequest != null) {
                DeviceLog.error("WEBVIEW_ERROR: " + webResourceRequest.toString());
            }
            if (webResourceError != null) {
                DeviceLog.error("WEBVIEW_ERROR: " + webResourceError.toString());
            }
        }

        @Override
        public boolean onRenderProcessGone(android.webkit.WebView webView, RenderProcessGoneDetail renderProcessGoneDetail) {
            Utilities.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (AdUnit.getAdUnitActivity() != null) {
                        AdUnit.getAdUnitActivity().finish();
                    }
                    if (WebViewApp.getCurrentApp() != null && WebViewApp.getCurrentApp().getWebView() != null) {
                        ViewUtilities.removeViewFromParent(WebViewApp.getCurrentApp().getWebView());
                    }
                    InitializeThread.reset();
                }
            });
            DeviceLog.error("UnityAds Sdk WebView onRenderProcessGone : " + renderProcessGoneDetail.toString());
            SDKMetrics.getInstance().sendEventWithTags("native_webview_render_process_gone", new HashMap<String, String>(renderProcessGoneDetail) {
                final RenderProcessGoneDetail val$detail;

                {
                    boolean didCrash;
                    int rendererPriorityAtExit;
                    this.val$detail = renderProcessGoneDetail;
                    if (Build.VERSION.SDK_INT >= 26) {
                        StringBuilder sb = new StringBuilder();
                        sb.append("");
                        didCrash = renderProcessGoneDetail.didCrash();
                        sb.append(didCrash);
                        put("dc", sb.toString());
                        StringBuilder sb2 = new StringBuilder();
                        sb2.append("");
                        rendererPriorityAtExit = renderProcessGoneDetail.rendererPriorityAtExit();
                        sb2.append(rendererPriorityAtExit);
                        put("pae", sb2.toString());
                    }
                }
            });
            return true;
        }

        @Override
        public boolean shouldOverrideUrlLoading(android.webkit.WebView webView, String str) {
            DeviceLog.debug("Trying to load url: " + str);
            return false;
        }
    }

    public static boolean create(final Configuration configuration) throws IllegalThreadStateException {
        boolean z6;
        boolean z7;
        DeviceLog.entered();
        if (!Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
            Utilities.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        WebViewApp webViewApp = new WebViewApp(Configuration.this);
                        String str = "?platform=android";
                        try {
                            if (Configuration.this.getWebViewUrl() != null) {
                                str = "?platform=android&origin=" + URLEncoder.encode(Configuration.this.getWebViewUrl(), "UTF-8");
                            }
                        } catch (UnsupportedEncodingException e6) {
                            DeviceLog.exception("Unsupported charset when encoding origin url", e6);
                        }
                        try {
                            if (Configuration.this.getWebViewVersion() != null) {
                                str = str + "&version=" + URLEncoder.encode(Configuration.this.getWebViewVersion(), "UTF-8");
                            }
                        } catch (UnsupportedEncodingException e7) {
                            DeviceLog.exception("Unsupported charset when encoding webview version", e7);
                        }
                        webViewApp.getWebView().loadDataWithBaseURL("file://" + SdkProperties.getLocalWebViewFile() + str, Configuration.this.getWebViewData(), "text/html", "UTF-8", null);
                        WebViewApp.setCurrentApp(webViewApp);
                    } catch (Exception unused) {
                        DeviceLog.error("Couldn't construct WebViewApp");
                        WebViewApp._conditionVariable.open();
                    }
                }
            });
            ConditionVariable conditionVariable = new ConditionVariable();
            _conditionVariable = conditionVariable;
            boolean block = conditionVariable.block(configuration.getWebViewAppCreateTimeout());
            boolean z8 = true;
            if (getCurrentApp() != null) {
                z6 = true;
            } else {
                z6 = false;
            }
            if (z6 && getCurrentApp().isWebAppInitialized()) {
                z7 = true;
            } else {
                z7 = false;
            }
            if (!block || !z6 || !z7) {
                z8 = false;
            }
            if (!z8) {
                SDKMetrics.getInstance().sendEventWithTags("native_webview_creation_failed", new HashMap<String, String>(block, z6, z7) {
                    final boolean val$webAppDefined;
                    final boolean val$webAppInitialized;
                    final boolean val$webViewCreateDidNotTimeout;

                    {
                        this.val$webViewCreateDidNotTimeout = block;
                        this.val$webAppDefined = z6;
                        this.val$webAppInitialized = z7;
                        StringBuilder sb = new StringBuilder();
                        sb.append("");
                        sb.append(!block);
                        put("wto", sb.toString());
                        put("wad", "" + z6);
                        put("wai", "" + z7);
                    }
                });
            }
            return z8;
        }
        throw new IllegalThreadStateException("Cannot call create() from main thread!");
    }

    public static WebViewApp getCurrentApp() {
        return _currentApp;
    }

    private void invokeJavascriptMethod(String str, String str2, JSONArray jSONArray) throws JSONException {
        String jSONArray2 = jSONArray.toString();
        StringBuilder sb = new StringBuilder(str.length() + 22 + str2.length() + jSONArray2.length());
        sb.append("javascript:window.");
        sb.append(str);
        sb.append(".");
        sb.append(str2);
        sb.append("(");
        sb.append(jSONArray2);
        sb.append(");");
        String sb2 = sb.toString();
        DeviceLog.debug("Invoking javascript: " + sb2);
        getWebView().invokeJavascript(sb2);
    }

    public static void setCurrentApp(WebViewApp webViewApp) {
        _currentApp = webViewApp;
    }

    public void addCallback(NativeCallback nativeCallback) {
        if (this._nativeCallbacks == null) {
            this._nativeCallbacks = new HashMap<>();
        }
        synchronized (this._nativeCallbacks) {
            this._nativeCallbacks.put(nativeCallback.getId(), nativeCallback);
        }
    }

    public NativeCallback getCallback(String str) {
        NativeCallback nativeCallback;
        synchronized (this._nativeCallbacks) {
            nativeCallback = this._nativeCallbacks.get(str);
        }
        return nativeCallback;
    }

    public Configuration getConfiguration() {
        return this._configuration;
    }

    public int getWebAppFailureCode() {
        return _webAppFailureCode.get().intValue();
    }

    public String getWebAppFailureMessage() {
        return _webAppFailureMessage.get();
    }

    public WebView getWebView() {
        return this._webView;
    }

    public boolean invokeCallback(Invocation invocation) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("invokeBatchCallback ignored because web app is not loaded");
            return false;
        }
        JSONArray jSONArray = new JSONArray();
        ArrayList<ArrayList<Object>> responses = invocation.getResponses();
        if (responses != null && !responses.isEmpty()) {
            Iterator<ArrayList<Object>> it = responses.iterator();
            while (it.hasNext()) {
                ArrayList<Object> next = it.next();
                CallbackStatus callbackStatus = (CallbackStatus) next.get(0);
                Enum r52 = (Enum) next.get(1);
                Object[] objArr = (Object[]) next.get(2);
                String str = (String) objArr[0];
                Object[] copyOfRange = Arrays.copyOfRange(objArr, 1, objArr.length);
                ArrayList arrayList = new ArrayList();
                arrayList.add(str);
                arrayList.add(callbackStatus.toString());
                JSONArray jSONArray2 = new JSONArray();
                if (r52 != null) {
                    jSONArray2.put(r52.name());
                }
                for (Object obj : copyOfRange) {
                    jSONArray2.put(obj);
                }
                arrayList.add(jSONArray2);
                JSONArray jSONArray3 = new JSONArray();
                Iterator it2 = arrayList.iterator();
                while (it2.hasNext()) {
                    jSONArray3.put(it2.next());
                }
                jSONArray.put(jSONArray3);
            }
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleCallback", jSONArray);
        } catch (Exception e6) {
            DeviceLog.exception("Error while invoking batch response for WebView", e6);
        }
        return true;
    }

    @Override
    public boolean invokeMethod(String str, String str2, Method method, Object... objArr) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("invokeMethod ignored because web app is not loaded");
            return false;
        }
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(str);
        jSONArray.put(str2);
        if (method != null) {
            NativeCallback nativeCallback = new NativeCallback(method);
            addCallback(nativeCallback);
            jSONArray.put(nativeCallback.getId());
        } else {
            jSONArray.put((Object) null);
        }
        if (objArr != null) {
            for (Object obj : objArr) {
                jSONArray.put(obj);
            }
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleInvocation", jSONArray);
            return true;
        } catch (Exception e6) {
            DeviceLog.exception("Error invoking javascript method", e6);
            return false;
        }
    }

    public boolean isWebAppInitialized() {
        return _initialized.get().booleanValue();
    }

    public boolean isWebAppLoaded() {
        return this._webAppLoaded;
    }

    public void removeCallback(NativeCallback nativeCallback) {
        HashMap<String, NativeCallback> hashMap = this._nativeCallbacks;
        if (hashMap == null) {
            return;
        }
        synchronized (hashMap) {
            this._nativeCallbacks.remove(nativeCallback.getId());
        }
    }

    public void resetWebViewAppInitialization() {
        this._webAppLoaded = false;
        _webAppFailureCode.set(-1);
        _webAppFailureMessage.set("");
        _initialized.set(Boolean.FALSE);
    }

    public boolean sendEvent(Enum r42, Enum r52, Object... objArr) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("sendEvent ignored because web app is not loaded");
            return false;
        }
        JSONArray jSONArray = new JSONArray();
        jSONArray.put(r42.name());
        jSONArray.put(r52.name());
        for (Object obj : objArr) {
            jSONArray.put(obj);
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleEvent", jSONArray);
            return true;
        } catch (Exception e6) {
            DeviceLog.exception("Error while sending event to WebView", e6);
            return false;
        }
    }

    public void setConfiguration(Configuration configuration) {
        this._configuration = configuration;
    }

    public void setWebAppFailureCode(int i6) {
        _webAppFailureCode.set(Integer.valueOf(i6));
    }

    public void setWebAppFailureMessage(String str) {
        _webAppFailureMessage.set(str);
    }

    public void setWebAppInitialized(boolean z6) {
        _initialized.set(Boolean.valueOf(z6));
        _conditionVariable.open();
    }

    public void setWebAppLoaded(boolean z6) {
        this._webAppLoaded = z6;
    }

    public void setWebView(WebView webView) {
        this._webView = webView;
    }

    private WebViewApp(Configuration configuration) {
        this._webAppLoaded = false;
        setConfiguration(configuration);
        WebViewBridge.setClassTable(getConfiguration().getWebAppApiClassList());
        WebView webView = new WebView(ClientProperties.getApplicationContext());
        this._webView = webView;
        webView.setWebViewClient(new WebAppClient());
        this._webView.setWebChromeClient(new WebAppChromeClient());
    }

    public WebViewApp() {
        this._webAppLoaded = false;
    }
}