CB-4858 - Run IAB methods on the UI thread.

This commit is contained in:
Andrew Grieve 2013-10-10 12:40:27 -04:00
parent 8a6bc01814
commit 5ef5171003

View File

@ -48,11 +48,11 @@ import android.widget.RelativeLayout;
import org.apache.cordova.CallbackContext; import org.apache.cordova.CallbackContext;
import org.apache.cordova.Config; import org.apache.cordova.Config;
import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.apache.cordova.LOG; import org.apache.cordova.LOG;
import org.apache.cordova.PluginResult; import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -95,115 +95,114 @@ public class InAppBrowser extends CordovaPlugin {
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message. * @return A PluginResult object with a status and message.
*/ */
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
try { if (action.equals("open")) {
if (action.equals("open")) { this.callbackContext = callbackContext;
this.callbackContext = callbackContext; final String url = args.getString(0);
String url = args.getString(0); String t = args.optString(1);
String target = args.optString(1); if (t == null || t.equals("") || t.equals(NULL)) {
if (target == null || target.equals("") || target.equals(NULL)) { t = SELF;
target = SELF; }
} final String target = t;
HashMap<String, Boolean> features = parseFeature(args.optString(2)); final HashMap<String, Boolean> features = parseFeature(args.optString(2));
Log.d(LOG_TAG, "target = " + target); Log.d(LOG_TAG, "target = " + target);
url = updateUrl(url); this.cordova.getActivity().runOnUiThread(new Runnable() {
String result = ""; @Override
public void run() {
// SELF String result = "";
if (SELF.equals(target)) { // SELF
Log.d(LOG_TAG, "in self"); if (SELF.equals(target)) {
// load in webview Log.d(LOG_TAG, "in self");
if (url.startsWith("file://") || url.startsWith("javascript:") // load in webview
|| Config.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.startsWith("javascript:")
this.webView.loadUrl(url); || Config.isUrlWhiteListed(url)) {
} webView.loadUrl(url);
//Load the dialer }
else if (url.startsWith(WebView.SCHEME_TEL)) //Load the dialer
{ else if (url.startsWith(WebView.SCHEME_TEL))
try { {
Intent intent = new Intent(Intent.ACTION_DIAL); try {
intent.setData(Uri.parse(url)); Intent intent = new Intent(Intent.ACTION_DIAL);
this.cordova.getActivity().startActivity(intent); intent.setData(Uri.parse(url));
} catch (android.content.ActivityNotFoundException e) { cordova.getActivity().startActivity(intent);
LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString()); } catch (android.content.ActivityNotFoundException e) {
LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
}
}
// load in InAppBrowser
else {
result = showWebPage(url, features);
} }
} }
// load in InAppBrowser // SYSTEM
else if (SYSTEM.equals(target)) {
Log.d(LOG_TAG, "in system");
result = openExternal(url);
}
// BLANK - or anything else
else { else {
result = this.showWebPage(url, features); Log.d(LOG_TAG, "in blank");
result = showWebPage(url, features);
} }
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
pluginResult.setKeepCallback(true);
callbackContext.sendPluginResult(pluginResult);
} }
// SYSTEM });
else if (SYSTEM.equals(target)) { }
Log.d(LOG_TAG, "in system"); else if (action.equals("close")) {
result = this.openExternal(url); closeDialog();
}
else if (action.equals("injectScriptCode")) {
String jsWrapper = null;
if (args.getBoolean(1)) {
jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId());
}
injectDeferredObject(args.getString(0), jsWrapper);
}
else if (action.equals("injectScriptFile")) {
String jsWrapper;
if (args.getBoolean(1)) {
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 {
jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
}
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 if (action.equals("show")) {
this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.show();
} }
// BLANK - or anything else });
else { PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
Log.d(LOG_TAG, "in blank"); pluginResult.setKeepCallback(true);
result = this.showWebPage(url, features); this.callbackContext.sendPluginResult(pluginResult);
} }
else {
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result); return false;
pluginResult.setKeepCallback(true);
this.callbackContext.sendPluginResult(pluginResult);
}
else if (action.equals("close")) {
closeDialog();
}
else if (action.equals("injectScriptCode")) {
String jsWrapper = null;
if (args.getBoolean(1)) {
jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId());
}
injectDeferredObject(args.getString(0), jsWrapper);
}
else if (action.equals("injectScriptFile")) {
String jsWrapper;
if (args.getBoolean(1)) {
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 {
jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
}
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 if (action.equals("show")) {
Runnable runnable = new Runnable() {
@Override
public void run() {
dialog.show();
}
};
this.cordova.getActivity().runOnUiThread(runnable);
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
pluginResult.setKeepCallback(true);
this.callbackContext.sendPluginResult(pluginResult);
}
else {
return false;
}
} catch (JSONException e) {
this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
} }
return true; return true;
} }
@ -251,8 +250,14 @@ public class InAppBrowser extends CordovaPlugin {
} else { } else {
scriptToInject = source; scriptToInject = source;
} }
final String finalScriptToInject = scriptToInject;
// This action will have the side-effect of blurring the currently focused element // This action will have the side-effect of blurring the currently focused element
this.inAppWebView.loadUrl("javascript:" + scriptToInject); this.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
inAppWebView.loadUrl("javascript:" + finalScriptToInject);
}
});
} }
/** /**
@ -284,20 +289,6 @@ public class InAppBrowser extends CordovaPlugin {
} }
} }
/**
* Convert relative URL to full path
*
* @param url
* @return
*/
private String updateUrl(String url) {
Uri newUrl = Uri.parse(url);
if (newUrl.isRelative()) {
url = this.webView.getUrl().substring(0, this.webView.getUrl().lastIndexOf("/")+1) + url;
}
return url;
}
/** /**
* Display a new browser with the specified URL. * Display a new browser with the specified URL.
* *
@ -328,27 +319,23 @@ public class InAppBrowser extends CordovaPlugin {
if (childView == null) { if (childView == null) {
return; return;
} }
try { this.cordova.getActivity().runOnUiThread(new Runnable() {
Runnable runnable = new Runnable() { @Override
@Override public void run() {
public void run() { childView.loadUrl("about:blank");
childView.loadUrl("about:blank"); if (dialog != null) {
dialog.dismiss();
} }
}
}; });
try {
this.cordova.getActivity().runOnUiThread(runnable);
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("type", EXIT_EVENT); obj.put("type", EXIT_EVENT);
sendUpdate(obj, false); sendUpdate(obj, false);
} catch (JSONException ex) { } catch (JSONException ex) {
Log.d(LOG_TAG, "Should never happen"); Log.d(LOG_TAG, "Should never happen");
} }
if (dialog != null) {
dialog.dismiss();
}
} }
/** /**