Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2377b99f authored by Jonathan Dixon's avatar Jonathan Dixon
Browse files

Decouple JsResult from the WebViewClassic impl

The majority  JsResult and JsPromptResult are simple data-carrying &
callback classes. Extract the WebViewClassic specific parts dealing
with WebCore thread and CallbackProxy and decouple via abstract interface.

Bug: 6238755
Change-Id: Ibafd18910725f0875e3b59c1b2078173c102cdec
parent 39edeeef
Loading
Loading
Loading
Loading
+62 −23
Original line number Diff line number Diff line
@@ -147,6 +147,40 @@ class CallbackProxy extends Handler {
        }
    }

    private class JsResultReceiver implements JsResult.ResultReceiver {
        // This prevents a user from interacting with the result before WebCore is
        // ready to handle it.
        private boolean mReady;
        // Tells us if the user tried to confirm or cancel the result before WebCore
        // is ready.
        private boolean mTriedToNotifyBeforeReady;

        public JsPromptResult mJsResult = new JsPromptResult(this);

        final void setReady() {
            mReady = true;
            if (mTriedToNotifyBeforeReady) {
                notifyCallbackProxy();
            }
        }

        /* Wake up the WebCore thread. */
        @Override
        public void onJsResultComplete(JsResult result) {
            if (mReady) {
                notifyCallbackProxy();
            } else {
                mTriedToNotifyBeforeReady = true;
            }
        }

        private void notifyCallbackProxy() {
            synchronized (CallbackProxy.this) {
                CallbackProxy.this.notify();
            }
        }
}

    /**
     * Construct a new CallbackProxy.
     */
@@ -531,14 +565,15 @@ class CallbackProxy extends Handler {

            case JS_ALERT:
                if (mWebChromeClient != null) {
                    final JsResult res = (JsResult) msg.obj;
                    final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
                    final JsResult res = receiver.mJsResult;
                    String message = msg.getData().getString("message");
                    String url = msg.getData().getString("url");
                    if (!mWebChromeClient.onJsAlert(mWebView.getWebView(), url, message,
                            res)) {
                        if (!canShowAlertDialog()) {
                            res.cancel();
                            res.setReady();
                            receiver.setReady();
                            break;
                        }
                        new AlertDialog.Builder(mContext)
@@ -561,20 +596,21 @@ class CallbackProxy extends Handler {
                                        })
                                .show();
                    }
                    res.setReady();
                    receiver.setReady();
                }
                break;

            case JS_CONFIRM:
                if (mWebChromeClient != null) {
                    final JsResult res = (JsResult) msg.obj;
                    final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
                    final JsResult res = receiver.mJsResult;
                    String message = msg.getData().getString("message");
                    String url = msg.getData().getString("url");
                    if (!mWebChromeClient.onJsConfirm(mWebView.getWebView(), url, message,
                            res)) {
                        if (!canShowAlertDialog()) {
                            res.cancel();
                            res.setReady();
                            receiver.setReady();
                            break;
                        }
                        new AlertDialog.Builder(mContext)
@@ -605,13 +641,14 @@ class CallbackProxy extends Handler {
                    }
                    // Tell the JsResult that it is ready for client
                    // interaction.
                    res.setReady();
                    receiver.setReady();
                }
                break;

            case JS_PROMPT:
                if (mWebChromeClient != null) {
                    final JsPromptResult res = (JsPromptResult) msg.obj;
                    final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
                    final JsPromptResult res = receiver.mJsResult;
                    String message = msg.getData().getString("message");
                    String defaultVal = msg.getData().getString("default");
                    String url = msg.getData().getString("url");
@@ -619,7 +656,7 @@ class CallbackProxy extends Handler {
                                defaultVal, res)) {
                        if (!canShowAlertDialog()) {
                            res.cancel();
                            res.setReady();
                            receiver.setReady();
                            break;
                        }
                        final LayoutInflater factory = LayoutInflater
@@ -662,20 +699,21 @@ class CallbackProxy extends Handler {
                    }
                    // Tell the JsResult that it is ready for client
                    // interaction.
                    res.setReady();
                    receiver.setReady();
                }
                break;

            case JS_UNLOAD:
                if (mWebChromeClient != null) {
                    final JsResult res = (JsResult) msg.obj;
                    final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
                    final JsResult res = receiver.mJsResult;
                    String message = msg.getData().getString("message");
                    String url = msg.getData().getString("url");
                    if (!mWebChromeClient.onJsBeforeUnload(mWebView.getWebView(), url,
                            message, res)) {
                        if (!canShowAlertDialog()) {
                            res.cancel();
                            res.setReady();
                            receiver.setReady();
                            break;
                        }
                        final String m = mContext.getString(
@@ -700,19 +738,20 @@ class CallbackProxy extends Handler {
                                        })
                                .show();
                    }
                    res.setReady();
                    receiver.setReady();
                }
                break;

            case JS_TIMEOUT:
                if(mWebChromeClient != null) {
                    final JsResult res = (JsResult) msg.obj;
                    final JsResultReceiver receiver = (JsResultReceiver) msg.obj;
                    final JsResult res = receiver.mJsResult;
                    if(mWebChromeClient.onJsTimeout()) {
                        res.confirm();
                    } else {
                        res.cancel();
                    }
                    res.setReady();
                    receiver.setReady();
                }
                break;

@@ -1331,7 +1370,7 @@ class CallbackProxy extends Handler {
        if (mWebChromeClient == null) {
            return;
        }
        JsResult result = new JsResult(this, false);
        JsResultReceiver result = new JsResultReceiver();
        Message alert = obtainMessage(JS_ALERT, result);
        alert.getData().putString("message", message);
        alert.getData().putString("url", url);
@@ -1352,7 +1391,7 @@ class CallbackProxy extends Handler {
        if (mWebChromeClient == null) {
            return false;
        }
        JsResult result = new JsResult(this, false);
        JsResultReceiver result = new JsResultReceiver();
        Message confirm = obtainMessage(JS_CONFIRM, result);
        confirm.getData().putString("message", message);
        confirm.getData().putString("url", url);
@@ -1365,7 +1404,7 @@ class CallbackProxy extends Handler {
                Log.e(LOGTAG, Log.getStackTraceString(e));
            }
        }
        return result.getResult();
        return result.mJsResult.getResult();
    }

    public String onJsPrompt(String url, String message, String defaultValue) {
@@ -1374,7 +1413,7 @@ class CallbackProxy extends Handler {
        if (mWebChromeClient == null) {
            return null;
        }
        JsPromptResult result = new JsPromptResult(this);
        JsResultReceiver result = new JsResultReceiver();
        Message prompt = obtainMessage(JS_PROMPT, result);
        prompt.getData().putString("message", message);
        prompt.getData().putString("default", defaultValue);
@@ -1388,7 +1427,7 @@ class CallbackProxy extends Handler {
                Log.e(LOGTAG, Log.getStackTraceString(e));
            }
        }
        return result.getStringResult();
        return result.mJsResult.getStringResult();
    }

    public boolean onJsBeforeUnload(String url, String message) {
@@ -1397,7 +1436,7 @@ class CallbackProxy extends Handler {
        if (mWebChromeClient == null) {
            return true;
        }
        JsResult result = new JsResult(this, true);
        JsResultReceiver result = new JsResultReceiver();
        Message confirm = obtainMessage(JS_UNLOAD, result);
        confirm.getData().putString("message", message);
        confirm.getData().putString("url", url);
@@ -1410,7 +1449,7 @@ class CallbackProxy extends Handler {
                Log.e(LOGTAG, Log.getStackTraceString(e));
            }
        }
        return result.getResult();
        return result.mJsResult.getResult();
    }

    /**
@@ -1540,7 +1579,7 @@ class CallbackProxy extends Handler {
        if (mWebChromeClient == null) {
            return true;
        }
        JsResult result = new JsResult(this, true);
        JsResultReceiver result = new JsResultReceiver();
        Message timeout = obtainMessage(JS_TIMEOUT, result);
        synchronized (this) {
            sendMessage(timeout);
@@ -1551,7 +1590,7 @@ class CallbackProxy extends Handler {
                Log.e(LOGTAG, Log.getStackTraceString(e));
            }
        }
        return result.getResult();
        return result.mJsResult.getResult();
    }

    public void getVisitedHistory(ValueCallback<String[]> callback) {
+14 −14
Original line number Diff line number Diff line
@@ -18,11 +18,11 @@ package android.webkit;


/**
 * Public class for handling javascript prompt requests. A
 * JsDialogHandlerInterface implentation will receive a jsPrompt call with a
 * JsPromptResult parameter. This parameter is used to return a result to
 * WebView. The client can call cancel() to cancel the dialog or confirm() with
 * the user's input to confirm the dialog.
 * Public class for handling JavaScript prompt requests. The WebChromeClient will receive a
 * {@link WebChromeClient#onJsPrompt(WebView, String, String, String, JsPromptResult)} call with a
 * JsPromptResult instance as a parameter. This parameter is used to return the result of this user
 * dialog prompt back to the WebView instance. The client can call cancel() to cancel the dialog or
 * confirm() with the user's input to confirm the dialog.
 */
public class JsPromptResult extends JsResult {
    // String result of the prompt
@@ -36,17 +36,17 @@ public class JsPromptResult extends JsResult {
        confirm();
    }

    /*package*/ JsPromptResult(CallbackProxy proxy) {
        super(proxy, /* unused */ false);
    /**
     * @hide Only for use by WebViewProvider implementations
     */
    public JsPromptResult(ResultReceiver receiver) {
        super(receiver);
    }

    /*package*/ String getStringResult() {
    /**
     * @hide Only for use by WebViewProvider implementations
     */
    public String getStringResult() {
        return mStringResult;
    }

    @Override
    /*package*/ void handleDefault() {
        mStringResult = null;
        super.handleDefault();
    }
}
+27 −37
Original line number Diff line number Diff line
@@ -16,23 +16,27 @@

package android.webkit;


/**
 * An instance of this class is passed as a parameter in various {@link WebChromeClient} action
 * notifications. The object is used as a handle onto the underlying JavaScript-originated request,
 * and provides a means for the client to indicate whether this action should proceed.
 */
public class JsResult {
    // This prevents a user from interacting with the result before WebCore is
    // ready to handle it.
    private boolean mReady;
    // Tells us if the user tried to confirm or cancel the result before WebCore
    // is ready.
    private boolean mTriedToNotifyBeforeReady;
    // This is a basic result of a confirm or prompt dialog.
    protected boolean mResult;
    /**
     * Callback interface, implemented by the WebViewProvider implementation to receive
     * notifications when the JavaScript result represented by a JsResult instance has
     * @hide Only for use by WebViewProvider implementations
     */
    public interface ResultReceiver {
        public void onJsResultComplete(JsResult result);
    }
    /**
     * This is the caller of the prompt and is the object that is waiting.
     * @hide
     */
    protected final CallbackProxy mProxy;
    // This is the default value of the result.
    private final boolean mDefaultValue;
    protected final ResultReceiver mReceiver;

    /**
     * Handle the result if the user cancelled the dialog.
@@ -50,36 +54,22 @@ public class JsResult {
        wakeUp();
    }

    /*package*/ JsResult(CallbackProxy proxy, boolean defaultVal) {
        mProxy = proxy;
        mDefaultValue = defaultVal;
    /**
     * @hide Only for use by WebViewProvider implementations
     */
    public JsResult(ResultReceiver receiver) {
        mReceiver = receiver;
    }

    /*package*/ final boolean getResult() {
    /**
     * @hide Only for use by WebViewProvider implementations
     */
    public final boolean getResult() {
        return mResult;
    }

    /*package*/ final void setReady() {
        mReady = true;
        if (mTriedToNotifyBeforeReady) {
            wakeUp();
        }
    }

    /*package*/ void handleDefault() {
        setReady();
        mResult = mDefaultValue;
        wakeUp();
    }

    /* Wake up the WebCore thread. */
    /* Notify the caller that the JsResult has completed */
    protected final void wakeUp() {
        if (mReady) {
            synchronized (mProxy) {
                mProxy.notify();
            }
        } else {
            mTriedToNotifyBeforeReady = true;
        }
        mReceiver.onJsResultComplete(this);
    }
}