mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-22 00:32:55 +08:00
[CB-2654] Delay executeScript/insertCSS callback until resources have loaded; pass JS results to callback
This commit is contained in:
parent
1fa63300aa
commit
1782111d45
@ -51,6 +51,7 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebChromeClient;
|
||||||
import android.webkit.GeolocationPermissions.Callback;
|
import android.webkit.GeolocationPermissions.Callback;
|
||||||
|
import android.webkit.JsPromptResult;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebStorage;
|
import android.webkit.WebStorage;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
@ -94,10 +95,10 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
||||||
PluginResult.Status status = PluginResult.Status.OK;
|
PluginResult.Status status = PluginResult.Status.OK;
|
||||||
String result = "";
|
String result = "";
|
||||||
this.callbackContext = callbackContext;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (action.equals("open")) {
|
if (action.equals("open")) {
|
||||||
|
this.callbackContext = callbackContext;
|
||||||
String url = args.getString(0);
|
String url = args.getString(0);
|
||||||
String target = args.optString(1);
|
String target = args.optString(1);
|
||||||
if (target == null || target.equals("") || target.equals(NULL)) {
|
if (target == null || target.equals("") || target.equals(NULL)) {
|
||||||
@ -143,8 +144,12 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
Log.d(LOG_TAG, "in blank");
|
Log.d(LOG_TAG, "in blank");
|
||||||
result = this.showWebPage(url, features);
|
result = this.showWebPage(url, features);
|
||||||
}
|
}
|
||||||
|
PluginResult pluginResult = new PluginResult(status, result);
|
||||||
|
pluginResult.setKeepCallback(true);
|
||||||
|
this.callbackContext.sendPluginResult(pluginResult);
|
||||||
}
|
}
|
||||||
else if (action.equals("close")) {
|
else if (action.equals("close")) {
|
||||||
|
this.callbackContext = callbackContext;
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
|
||||||
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
|
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
|
||||||
@ -152,32 +157,82 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
this.callbackContext.sendPluginResult(pluginResult);
|
this.callbackContext.sendPluginResult(pluginResult);
|
||||||
}
|
}
|
||||||
else if (action.equals("injectScriptCode")) {
|
else if (action.equals("injectScriptCode")) {
|
||||||
String source = args.getString(0);
|
String jsWrapper = null;
|
||||||
|
if (args.getBoolean(1)) {
|
||||||
org.json.JSONArray jsonEsc = new org.json.JSONArray();
|
jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId());
|
||||||
jsonEsc.put(source);
|
}
|
||||||
String jsonRepr = jsonEsc.toString();
|
injectDeferredObject(args.getString(0), jsWrapper);
|
||||||
String jsonSourceString = jsonRepr.substring(1, jsonRepr.length()-1);
|
}
|
||||||
String scriptEnclosure = "(function(d){var c=d.createElement('script');c.type='text/javascript';c.innerText="
|
else if (action.equals("injectScriptFile")) {
|
||||||
+ jsonSourceString
|
String jsWrapper;
|
||||||
+ ";d.getElementsByTagName('head')[0].appendChild(c);})(document)";
|
if (args.getBoolean(1)) {
|
||||||
this.inAppWebView.loadUrl("javascript:" + scriptEnclosure);
|
jsWrapper = String.format("(function(d) { var c = d.createElement('script'); c.src = %%s; c.onload = function() { prompt('', 'gap-iab://%s'); }; d.body.appendChild(c); })(document)", callbackContext.getCallbackId());
|
||||||
|
} else {
|
||||||
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
|
jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
|
||||||
this.callbackContext.sendPluginResult(pluginResult);
|
}
|
||||||
|
injectDeferredObject(args.getString(0), jsWrapper);
|
||||||
|
}
|
||||||
|
else if (action.equals("injectStyleCode")) {
|
||||||
|
String jsWrapper;
|
||||||
|
if (args.getBoolean(1)) {
|
||||||
|
jsWrapper = String.format("(function(d) { var c = d.createElement('style'); c.innerHTML = %%s; d.body.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
|
||||||
|
} else {
|
||||||
|
jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document)";
|
||||||
|
}
|
||||||
|
injectDeferredObject(args.getString(0), jsWrapper);
|
||||||
|
}
|
||||||
|
else if (action.equals("injectStyleFile")) {
|
||||||
|
String jsWrapper;
|
||||||
|
if (args.getBoolean(1)) {
|
||||||
|
jsWrapper = String.format("(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%s; d.head.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
|
||||||
|
} else {
|
||||||
|
jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document)";
|
||||||
|
}
|
||||||
|
injectDeferredObject(args.getString(0), jsWrapper);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = PluginResult.Status.INVALID_ACTION;
|
status = PluginResult.Status.INVALID_ACTION;
|
||||||
|
PluginResult pluginResult = new PluginResult(status, result);
|
||||||
|
pluginResult.setKeepCallback(true);
|
||||||
|
this.callbackContext.sendPluginResult(pluginResult);
|
||||||
}
|
}
|
||||||
PluginResult pluginResult = new PluginResult(status, result);
|
|
||||||
pluginResult.setKeepCallback(true);
|
|
||||||
this.callbackContext.sendPluginResult(pluginResult);
|
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
|
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject an object (script or style) into the InAppBrowser WebView.
|
||||||
|
*
|
||||||
|
* This is a helper method for the inject{Script|Style}{Code|File} API calls, which
|
||||||
|
* provides a consistent method for injecting JavaScript code into the document.
|
||||||
|
*
|
||||||
|
* If a wrapper string is supplied, then the source string will be JSON-encoded (adding
|
||||||
|
* quotes) and wrapped using string formatting. (The wrapper string should have a single
|
||||||
|
* '%s' marker)
|
||||||
|
*
|
||||||
|
* @param source The source object (filename or script/style text) to inject into
|
||||||
|
* the document.
|
||||||
|
* @param jsWrapper A JavaScript string to wrap the source string in, so that the object
|
||||||
|
* is properly injected, or null if the source string is JavaScript text
|
||||||
|
* which should be executed directly.
|
||||||
|
*/
|
||||||
|
private void injectDeferredObject(String source, String jsWrapper) {
|
||||||
|
String scriptToInject;
|
||||||
|
if (jsWrapper != null) {
|
||||||
|
org.json.JSONArray jsonEsc = new org.json.JSONArray();
|
||||||
|
jsonEsc.put(source);
|
||||||
|
String jsonRepr = jsonEsc.toString();
|
||||||
|
String jsonSourceString = jsonRepr.substring(1, jsonRepr.length()-1);
|
||||||
|
scriptToInject = String.format(jsWrapper, jsonSourceString);
|
||||||
|
} else {
|
||||||
|
scriptToInject = source;
|
||||||
|
}
|
||||||
|
// This action will have the side-effect of blurring the currently focused element
|
||||||
|
this.inAppWebView.loadUrl("javascript:" + scriptToInject);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put the list of features into a hash map
|
* Put the list of features into a hash map
|
||||||
*
|
*
|
||||||
@ -444,7 +499,7 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
// WebView
|
// WebView
|
||||||
inAppWebView = new WebView(cordova.getActivity());
|
inAppWebView = new WebView(cordova.getActivity());
|
||||||
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||||
inAppWebView.setWebChromeClient(new InAppChromeClient());
|
inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView));
|
||||||
WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
|
WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
|
||||||
inAppWebView.setWebViewClient(client);
|
inAppWebView.setWebViewClient(client);
|
||||||
WebSettings settings = inAppWebView.getSettings();
|
WebSettings settings = inAppWebView.getSettings();
|
||||||
@ -527,8 +582,15 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
result.setKeepCallback(keepCallback);
|
result.setKeepCallback(keepCallback);
|
||||||
this.callbackContext.sendPluginResult(result);
|
this.callbackContext.sendPluginResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InAppChromeClient extends WebChromeClient {
|
public class InAppChromeClient extends WebChromeClient {
|
||||||
|
|
||||||
|
private CordovaWebView webView;
|
||||||
|
|
||||||
|
public InAppChromeClient(CordovaWebView webView) {
|
||||||
|
super();
|
||||||
|
this.webView = webView;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Handle database quota exceeded notification.
|
* Handle database quota exceeded notification.
|
||||||
*
|
*
|
||||||
@ -571,6 +633,57 @@ public class InAppBrowser extends CordovaPlugin {
|
|||||||
super.onGeolocationPermissionsShowPrompt(origin, callback);
|
super.onGeolocationPermissionsShowPrompt(origin, callback);
|
||||||
callback.invoke(origin, true, false);
|
callback.invoke(origin, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the client to display a prompt dialog to the user.
|
||||||
|
* If the client returns true, WebView will assume that the client will
|
||||||
|
* handle the prompt dialog and call the appropriate JsPromptResult method.
|
||||||
|
*
|
||||||
|
* The prompt bridge provided for the InAppBrowser is capable of executing any
|
||||||
|
* oustanding callback belonging to the InAppBrowser plugin. Care has been
|
||||||
|
* taken that other callbacks cannot be triggered, and that no other code
|
||||||
|
* execution is possible.
|
||||||
|
*
|
||||||
|
* To trigger the bridge, the prompt default value should be of the form:
|
||||||
|
*
|
||||||
|
* gap-iab://<callbackId>
|
||||||
|
*
|
||||||
|
* where <callbackId> is the string id of the callback to trigger (something
|
||||||
|
* like "InAppBrowser0123456789")
|
||||||
|
*
|
||||||
|
* If present, the prompt message is expected to be a JSON-encoded value to
|
||||||
|
* pass to the callback. A JSON_EXCEPTION is returned if the JSON is invalid.
|
||||||
|
*
|
||||||
|
* @param view
|
||||||
|
* @param url
|
||||||
|
* @param message
|
||||||
|
* @param defaultValue
|
||||||
|
* @param result
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
|
||||||
|
// See if the prompt string uses the 'gap-iab' protocol. If so, the remainder should be the id of a callback to execute.
|
||||||
|
if (defaultValue != null && defaultValue.startsWith("gap-iab://")) {
|
||||||
|
PluginResult scriptResult;
|
||||||
|
String scriptCallbackId = defaultValue.substring(10);
|
||||||
|
if (scriptCallbackId.startsWith("InAppBrowser")) {
|
||||||
|
if(message == null || message.length() == 0) {
|
||||||
|
scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray());
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray(message));
|
||||||
|
} catch(JSONException e) {
|
||||||
|
scriptResult = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.webView.sendPluginResult(scriptResult, scriptCallbackId);
|
||||||
|
result.confirm("");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user