diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index e35c9fbb1f2f..cdabaa8af7de 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -1241,64 +1241,137 @@ public class GeckoAppShell return true; } - static boolean openUriExternal(String aUriSpec, String aMimeType, String aPackageName, - String aClassName, String aAction, String aTitle) { - Intent intent = getIntentForActionString(aAction); - if (aAction.equalsIgnoreCase(Intent.ACTION_SEND)) { - Intent shareIntent = getIntentForActionString(aAction); - shareIntent.putExtra(Intent.EXTRA_TEXT, aUriSpec); - shareIntent.putExtra(Intent.EXTRA_SUBJECT, aTitle); - if (aMimeType != null && aMimeType.length() > 0) - shareIntent.setType(aMimeType); - intent = Intent.createChooser(shareIntent, GeckoApp.mAppContext.getResources().getString(R.string.share_title)); - } else if (aMimeType.length() > 0) { - intent.setDataAndType(Uri.parse(aUriSpec), aMimeType); - } else { - Uri uri = Uri.parse(aUriSpec); - if (isUriSafeForScheme(uri) == false) { - return false; - } - - final String scheme = uri.getScheme(); - if ("sms".equals(scheme)) { - // Have a special handling for the SMS, as the message body - // is not extracted from the URI automatically - final String query = uri.getEncodedQuery(); - if (query != null && query.length() > 0) { - final String[] fields = query.split("&"); - boolean foundBody = false; - String resultQuery = ""; - for (int i = 0; i < fields.length; i++) { - final String field = fields[i]; - if (field.length() > 5 && "body=".equals(field.substring(0, 5))) { - final String body = Uri.decode(field.substring(5)); - intent.putExtra("sms_body", body); - foundBody = true; - } else { - resultQuery = resultQuery.concat(resultQuery.length() > 0 ? "&" + field : field); - } - } - if (foundBody) { - // Put the query without the body field back into the URI - final String prefix = aUriSpec.substring(0, aUriSpec.indexOf('?')); - uri = Uri.parse(resultQuery.length() > 0 ? prefix + "?" + resultQuery : prefix); - } - } - } - intent.setData(uri); + /** + * Given the inputs to getOpenURIIntent, plus an optional + * package name and class name, create and fire an intent to open the + * provided URI. + * + * @param targetURI the string spec of the URI to open. + * @param mimeType an optional MIME type string. + * @param action an Android action specifier, such as + * Intent.ACTION_SEND. + * @param title the title to use in ACTION_SEND intents. + * @return true if the activity started successfully; false otherwise. + */ + static boolean openUriExternal(String targetURI, + String mimeType, + String packageName, + String className, + String action, + String title) { + final Context context = GeckoApp.mAppContext; + final Intent intent = getOpenURIIntent(context, targetURI, + mimeType, action, title); + + if (intent == null) { + return false; + } + + if (packageName.length() > 0 && className.length() > 0) { + intent.setClassName(packageName, className); } - if (aPackageName.length() > 0 && aClassName.length() > 0) - intent.setClassName(aPackageName, aClassName); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); try { - GeckoApp.mAppContext.startActivity(intent); + context.startActivity(intent); return true; - } catch(ActivityNotFoundException e) { + } catch (ActivityNotFoundException e) { return false; } } + /** + * Given a URI, a MIME type, an Android intent "action", and a title, + * produce an intent which can be used to start an activity to open + * the specified URI. + * + * @param context a Context instance. + * @param targetURI the string spec of the URI to open. + * @param mimeType an optional MIME type string. + * @param action an Android action specifier, such as + * Intent.ACTION_SEND. + * @param title the title to use in ACTION_SEND intents. + * @return an Intent, or null if none could be + * produced. + */ + static Intent getOpenURIIntent(final Context context, + final String targetURI, + final String mimeType, + final String action, + final String title) { + + if (action.equalsIgnoreCase(Intent.ACTION_SEND)) { + Intent shareIntent = getIntentForActionString(action); + shareIntent.putExtra(Intent.EXTRA_TEXT, targetURI); + shareIntent.putExtra(Intent.EXTRA_SUBJECT, title); + + if (mimeType != null && mimeType.length() > 0) { + shareIntent.setType(mimeType); + } + + return Intent.createChooser(shareIntent, + context.getResources().getString(R.string.share_title)); + } + + if (mimeType.length() > 0) { + Intent intent = getIntentForActionString(action); + intent.setDataAndType(Uri.parse(targetURI), mimeType); + return intent; + } + + final Uri uri = Uri.parse(targetURI); + if (!isUriSafeForScheme(uri)) { + return null; + } + + final String scheme = uri.getScheme(); + final Intent intent = getIntentForActionString(action); + + // Start with the original URI. If we end up modifying it, + // we'll overwrite it. + intent.setDataAndNormalize(uri); + + // Have a special handling for the SMS, as the message body + // is not extracted from the URI automatically. + if (!"sms".equals(scheme)) { + return intent; + } + + final String query = uri.getEncodedQuery(); + if (TextUtils.isEmpty(query)) { + return intent; + } + + final String[] fields = query.split("&"); + boolean foundBody = false; + String resultQuery = ""; + for (String field : fields) { + if (foundBody || !field.startsWith("body=")) { + resultQuery = resultQuery.concat(resultQuery.length() > 0 ? "&" + field : field); + continue; + } + + // Found the first body param. Put it into the intent. + final String body = Uri.decode(field.substring(5)); + intent.putExtra("sms_body", body); + foundBody = true; + } + + if (!foundBody) { + // No need to rewrite the URI, then. + return intent; + } + + // Form a new URI without the body field in the query part, and + // push that into the new Intent. + final String prefix = targetURI.substring(0, targetURI.indexOf('?')); + final String newQuery = resultQuery.length() > 0 ? "?" + resultQuery : ""; + final Uri pruned = Uri.parse(prefix + newQuery); + intent.setDataAndNormalize(pruned); + + return intent; + } + static SynchronousQueue sClipboardQueue = new SynchronousQueue(); private static String EMPTY_STRING = new String();