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
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 800ebc8..cb74ed6 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -147,6 +147,40 @@
}
}
+ 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 @@
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 @@
})
.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 @@
}
// 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 @@
defaultVal, res)) {
if (!canShowAlertDialog()) {
res.cancel();
- res.setReady();
+ receiver.setReady();
break;
}
final LayoutInflater factory = LayoutInflater
@@ -662,20 +699,21 @@
}
// 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 @@
})
.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 @@
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 @@
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 @@
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 @@
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 @@
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getStringResult();
+ return result.mJsResult.getStringResult();
}
public boolean onJsBeforeUnload(String url, String message) {
@@ -1397,7 +1436,7 @@
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 @@
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getResult();
+ return result.mJsResult.getResult();
}
/**
@@ -1540,7 +1579,7 @@
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 @@
Log.e(LOGTAG, Log.getStackTraceString(e));
}
}
- return result.getResult();
+ return result.mJsResult.getResult();
}
public void getVisitedHistory(ValueCallback<String[]> callback) {
diff --git a/core/java/android/webkit/JsPromptResult.java b/core/java/android/webkit/JsPromptResult.java
index 9fcd1bc..a1bf124 100644
--- a/core/java/android/webkit/JsPromptResult.java
+++ b/core/java/android/webkit/JsPromptResult.java
@@ -18,11 +18,11 @@
/**
- * 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 @@
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();
- }
}
diff --git a/core/java/android/webkit/JsResult.java b/core/java/android/webkit/JsResult.java
index e61ab21..07b686f 100644
--- a/core/java/android/webkit/JsResult.java
+++ b/core/java/android/webkit/JsResult.java
@@ -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;
/**
- * This is the caller of the prompt and is the object that is waiting.
- * @hide
+ * 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
*/
- protected final CallbackProxy mProxy;
- // This is the default value of the result.
- private final boolean mDefaultValue;
+ 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 ResultReceiver mReceiver;
/**
* Handle the result if the user cancelled the dialog.
@@ -50,36 +54,22 @@
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);
}
}