Permalink
Browse files

Fix issue #5714517: App shortcuts can result in bad task intents

New API to let you build an Intent whose base configuration is correct,
but has an additional "selector" to pick out the specific app that you
would like launched.

Change-Id: Ide9db6dc60e2844b7696cfe09b28337fe7dd63db
  • Loading branch information...
1 parent 003c15d commit f5b8671c340f189c50b41c53622f979b6d5e0a57 Dianne Hackborn committed Dec 6, 2011
View
@@ -5334,6 +5334,7 @@ package android.content {
method public java.util.ArrayList<T> getParcelableArrayListExtra(java.lang.String);
method public T getParcelableExtra(java.lang.String);
method public java.lang.String getScheme();
+ method public android.content.Intent getSelector();
method public java.io.Serializable getSerializableExtra(java.lang.String);
method public short[] getShortArrayExtra(java.lang.String);
method public short getShortExtra(java.lang.String, short);
@@ -5346,6 +5347,7 @@ package android.content {
method public boolean hasExtra(java.lang.String);
method public boolean hasFileDescriptors();
method public static android.content.Intent makeMainActivity(android.content.ComponentName);
+ method public static android.content.Intent makeMainSelectorActivity(java.lang.String, java.lang.String);
method public static android.content.Intent makeRestartActivityTask(android.content.ComponentName);
method public static android.content.Intent parseIntent(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static android.content.Intent parseUri(java.lang.String, int) throws java.net.URISyntaxException;
@@ -5399,6 +5401,7 @@ package android.content {
method public void setExtrasClassLoader(java.lang.ClassLoader);
method public android.content.Intent setFlags(int);
method public android.content.Intent setPackage(java.lang.String);
+ method public void setSelector(android.content.Intent);
method public void setSourceBounds(android.graphics.Rect);
method public android.content.Intent setType(java.lang.String);
method public deprecated java.lang.String toURI();
@@ -5577,6 +5580,7 @@ package android.content {
field public static final int FILL_IN_COMPONENT = 8; // 0x8
field public static final int FILL_IN_DATA = 2; // 0x2
field public static final int FILL_IN_PACKAGE = 16; // 0x10
+ field public static final int FILL_IN_SELECTOR = 64; // 0x40
field public static final int FILL_IN_SOURCE_BOUNDS = 32; // 0x20
field public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 4194304; // 0x400000
field public static final int FLAG_ACTIVITY_CLEAR_TASK = 32768; // 0x8000
@@ -131,13 +131,18 @@ private void run(String[] args) throws Exception {
runScreenCompat();
} else if (op.equals("display-size")) {
runDisplaySize();
+ } else if (op.equals("to-uri")) {
+ runToUri(false);
+ } else if (op.equals("to-intent-uri")) {
+ runToUri(true);
} else {
throw new IllegalArgumentException("Unknown command: " + op);
}
}
private Intent makeIntent() throws URISyntaxException {
Intent intent = new Intent();
+ Intent baseIntent = intent;
boolean hasIntentInfo = false;
mDebugOption = false;
@@ -152,35 +157,39 @@ private Intent makeIntent() throws URISyntaxException {
while ((opt=nextOption()) != null) {
if (opt.equals("-a")) {
intent.setAction(nextArgRequired());
- hasIntentInfo = true;
+ if (intent == baseIntent) {
+ hasIntentInfo = true;
+ }
} else if (opt.equals("-d")) {
data = Uri.parse(nextArgRequired());
- hasIntentInfo = true;
+ if (intent == baseIntent) {
+ hasIntentInfo = true;
+ }
} else if (opt.equals("-t")) {
type = nextArgRequired();
- hasIntentInfo = true;
+ if (intent == baseIntent) {
+ hasIntentInfo = true;
+ }
} else if (opt.equals("-c")) {
intent.addCategory(nextArgRequired());
- hasIntentInfo = true;
+ if (intent == baseIntent) {
+ hasIntentInfo = true;
+ }
} else if (opt.equals("-e") || opt.equals("--es")) {
String key = nextArgRequired();
String value = nextArgRequired();
intent.putExtra(key, value);
- hasIntentInfo = true;
} else if (opt.equals("--esn")) {
String key = nextArgRequired();
intent.putExtra(key, (String) null);
- hasIntentInfo = true;
} else if (opt.equals("--ei")) {
String key = nextArgRequired();
String value = nextArgRequired();
intent.putExtra(key, Integer.valueOf(value));
- hasIntentInfo = true;
} else if (opt.equals("--eu")) {
String key = nextArgRequired();
String value = nextArgRequired();
intent.putExtra(key, Uri.parse(value));
- hasIntentInfo = true;
} else if (opt.equals("--eia")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -190,12 +199,10 @@ private Intent makeIntent() throws URISyntaxException {
list[i] = Integer.valueOf(strings[i]);
}
intent.putExtra(key, list);
- hasIntentInfo = true;
} else if (opt.equals("--el")) {
String key = nextArgRequired();
String value = nextArgRequired();
intent.putExtra(key, Long.valueOf(value));
- hasIntentInfo = true;
} else if (opt.equals("--ela")) {
String key = nextArgRequired();
String value = nextArgRequired();
@@ -205,18 +212,18 @@ private Intent makeIntent() throws URISyntaxException {
list[i] = Long.valueOf(strings[i]);
}
intent.putExtra(key, list);
- hasIntentInfo = true;
} else if (opt.equals("--ez")) {
String key = nextArgRequired();
String value = nextArgRequired();
intent.putExtra(key, Boolean.valueOf(value));
- hasIntentInfo = true;
} else if (opt.equals("-n")) {
String str = nextArgRequired();
ComponentName cn = ComponentName.unflattenFromString(str);
if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
intent.setComponent(cn);
- hasIntentInfo = true;
+ if (intent == baseIntent) {
+ hasIntentInfo = true;
+ }
} else if (opt.equals("-f")) {
String str = nextArgRequired();
intent.setFlags(Integer.decode(str).intValue());
@@ -264,6 +271,9 @@ private Intent makeIntent() throws URISyntaxException {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
} else if (opt.equals("--receiver-replace-pending")) {
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ } else if (opt.equals("--selector")) {
+ intent.setDataAndType(data, type);
+ intent = new Intent();
} else if (opt.equals("-D")) {
mDebugOption = true;
} else if (opt.equals("-W")) {
@@ -286,25 +296,42 @@ private Intent makeIntent() throws URISyntaxException {
}
intent.setDataAndType(data, type);
+ final boolean hasSelector = intent != baseIntent;
+ if (hasSelector) {
+ // A selector was specified; fix up.
+ baseIntent.setSelector(intent);
+ intent = baseIntent;
+ }
+
String arg = nextArg();
- if (arg != null) {
- Intent baseIntent;
- if (arg.indexOf(':') >= 0) {
- // The argument is a URI. Fully parse it, and use that result
- // to fill in any data not specified so far.
- baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
- } else if (arg.indexOf('/') >= 0) {
- // The argument is a component name. Build an Intent to launch
- // it.
- baseIntent = new Intent(Intent.ACTION_MAIN);
- baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- baseIntent.setComponent(ComponentName.unflattenFromString(arg));
- } else {
- // Assume the argument is a package name.
+ baseIntent = null;
+ if (arg == null) {
+ if (hasSelector) {
+ // If a selector has been specified, and no arguments
+ // have been supplied for the main Intent, then we can
+ // assume it is ACTION_MAIN CATEGORY_LAUNCHER; we don't
+ // need to have a component name specified yet, the
+ // selector will take care of that.
baseIntent = new Intent(Intent.ACTION_MAIN);
baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- baseIntent.setPackage(arg);
}
+ } else if (arg.indexOf(':') >= 0) {
+ // The argument is a URI. Fully parse it, and use that result
+ // to fill in any data not specified so far.
+ baseIntent = Intent.parseUri(arg, Intent.URI_INTENT_SCHEME);
+ } else if (arg.indexOf('/') >= 0) {
+ // The argument is a component name. Build an Intent to launch
+ // it.
+ baseIntent = new Intent(Intent.ACTION_MAIN);
+ baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ baseIntent.setComponent(ComponentName.unflattenFromString(arg));
+ } else {
+ // Assume the argument is a package name.
+ baseIntent = new Intent(Intent.ACTION_MAIN);
+ baseIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ baseIntent.setPackage(arg);
+ }
+ if (baseIntent != null) {
Bundle extras = intent.getExtras();
intent.replaceExtras((Bundle)null);
Bundle uriExtras = baseIntent.getExtras();
@@ -315,7 +342,7 @@ private Intent makeIntent() throws URISyntaxException {
baseIntent.removeCategory(c);
}
}
- intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT);
+ intent.fillIn(baseIntent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_SELECTOR);
if (extras == null) {
extras = uriExtras;
} else if (uriExtras != null) {
@@ -1064,6 +1091,11 @@ private void runDisplaySize() throws Exception {
}
}
+ private void runToUri(boolean intentScheme) throws Exception {
+ Intent intent = makeIntent();
+ System.out.println(intent.toUri(intentScheme ? Intent.URI_INTENT_SCHEME : 0));
+ }
+
private class IntentReceiver extends IIntentReceiver.Stub {
private boolean mFinished = false;
@@ -1233,6 +1265,8 @@ private static void showUsage() {
" am monitor [--gdb <port>]\n" +
" am screen-compat [on|off] <PACKAGE>\n" +
" am display-size [reset|MxN]\n" +
+ " am to-uri [INTENT]\n" +
+ " am to-intent-uri [INTENT]\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -1284,6 +1318,10 @@ private static void showUsage() {
"\n" +
"am display-size: override display size.\n" +
"\n" +
+ "am to-uri: print the given Intent specification as a URI.\n" +
+ "\n" +
+ "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
+ "\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
@@ -1308,6 +1346,7 @@ private static void showUsage() {
" [--activity-single-top] [--activity-clear-task]\n" +
" [--activity-task-on-home]\n" +
" [--receiver-registered-only] [--receiver-replace-pending]\n" +
+ " [--selector]\n" +
" [<URI> | <PACKAGE> | <COMPONENT>]\n"
);
}
Oops, something went wrong.

0 comments on commit f5b8671

Please sign in to comment.