chromium/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.support_lib_glue;

import static org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.recordApiCall;

import org.chromium.android_webview.AwProxyController;
import org.chromium.android_webview.WebViewChromiumRunQueue;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import org.chromium.support_lib_boundary.ProxyControllerBoundaryInterface;
import org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.ApiCall;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

/** Adapter between AwProxyController and ProxyControllerBoundaryInterface. */
public class SupportLibProxyControllerAdapter implements ProxyControllerBoundaryInterface {
    private final WebViewChromiumRunQueue mRunQueue;
    private final AwProxyController mProxyController;

    public SupportLibProxyControllerAdapter(
            WebViewChromiumRunQueue runQueue, AwProxyController proxyController) {
        mRunQueue = runQueue;
        mProxyController = proxyController;
    }

    @Override
    public void setProxyOverride(
            String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) {
        setProxyOverride(proxyRules, bypassRules, listener, executor, false);
    }

    @Override
    public void setProxyOverride(
            String[][] proxyRules,
            String[] bypassRules,
            Runnable listener,
            Executor executor,
            boolean reverseBypass) {
        try (TraceEvent event =
                TraceEvent.scoped(
                        "WebView.APICall.AndroidX.SET_PROXY_OVERRIDE_OR_REVERSE_BYPASS")) {
            recordApiCall(
                    reverseBypass
                            ? ApiCall.SET_PROXY_OVERRIDE
                            : ApiCall.SET_PROXY_OVERRIDE_REVERSE_BYPASS);
            if (checkNeedsPost()) {
                RuntimeException exception =
                        mRunQueue.runOnUiThreadBlocking(
                                () -> {
                                    try {
                                        mProxyController.setProxyOverride(
                                                proxyRules,
                                                bypassRules,
                                                listener,
                                                executor,
                                                reverseBypass);
                                    } catch (RuntimeException e) {
                                        return e;
                                    }
                                    return null;
                                });
                maybeThrowUnwrappedException(exception);
            } else {
                mProxyController.setProxyOverride(
                        proxyRules, bypassRules, listener, executor, reverseBypass);
            }
        }
    }

    @Override
    public void clearProxyOverride(Runnable listener, Executor executor) {
        try (TraceEvent event =
                TraceEvent.scoped("WebView.APICall.AndroidX.CLEAR_PROXY_OVERRIDE")) {
            recordApiCall(ApiCall.CLEAR_PROXY_OVERRIDE);
            if (checkNeedsPost()) {
                RuntimeException exception =
                        mRunQueue.runOnUiThreadBlocking(
                                () -> {
                                    try {
                                        mProxyController.clearProxyOverride(listener, executor);
                                    } catch (RuntimeException e) {
                                        return e;
                                    }
                                    return null;
                                });
                maybeThrowUnwrappedException(exception);
            } else {
                mProxyController.clearProxyOverride(listener, executor);
            }
        }
    }

    private void maybeThrowUnwrappedException(RuntimeException exception) {
        if (exception != null) {
            Throwable cause = exception.getCause();
            if (cause instanceof ExecutionException) cause = cause.getCause();
            if (cause instanceof RuntimeException) throw (RuntimeException) cause;
            throw exception;
        }
    }

    private static boolean checkNeedsPost() {
        return !ThreadUtils.runningOnUiThread();
    }
}