Revision 0fc4c33f
trustedintents/src/info/guardianproject/trustedintents/TrustedIntents.java | ||
---|---|---|
13 | 13 |
import android.content.pm.ResolveInfo; |
14 | 14 |
import android.content.pm.Signature; |
15 | 15 |
import android.text.TextUtils; |
16 |
import android.util.Log; |
|
16 | 17 |
|
17 | 18 |
import java.lang.reflect.Constructor; |
18 | 19 |
import java.security.cert.CertificateException; |
... | ... | |
93 | 94 |
} |
94 | 95 |
|
95 | 96 |
/** |
96 |
* Check if an {@link Intent} is from a trusted sender. |
|
97 |
* |
|
98 |
* @param intent the {@code Intent} to check |
|
99 |
* @return boolean whether {@code intent} is from a trusted sender |
|
100 |
* @see #addTrustedSigner(Class) |
|
101 |
*/ |
|
102 |
public boolean isIntentFromTrustedSender(Intent intent) { |
|
103 |
if (!isIntentSane(intent)) { |
|
104 |
return false; |
|
105 |
} |
|
106 |
String packageName = intent.getPackage(); |
|
107 |
if (TextUtils.isEmpty(packageName)) { |
|
108 |
packageName = intent.getComponent().getPackageName(); |
|
109 |
} |
|
110 |
if (TextUtils.isEmpty(packageName)) { |
|
111 |
return false; |
|
112 |
} |
|
113 |
return isPackageNameTrusted(packageName); |
|
114 |
} |
|
115 |
|
|
116 |
/** |
|
117 | 97 |
* Returns an {@link Intent} if the sending app is signed by one of |
118 | 98 |
* the trusted signing keys as set in {@link #addTrustedSigner(Class)}. |
119 | 99 |
* |
... | ... | |
123 | 103 |
*/ |
124 | 104 |
public Intent getIntentFromTrustedSender(Activity activity) { |
125 | 105 |
Intent intent = activity.getIntent(); |
126 |
if (isIntentFromTrustedSender(intent)) { |
|
106 |
String packageName = getCallingPackageName(activity); |
|
107 |
if (TextUtils.isEmpty(packageName)) { |
|
108 |
return null; |
|
109 |
} |
|
110 |
if (isPackageNameTrusted(packageName)) { |
|
127 | 111 |
return intent; |
128 | 112 |
} |
129 | 113 |
return null; |
130 | 114 |
} |
131 | 115 |
|
116 |
/** |
|
117 |
* Get the package name of the {@link Activity} that sent the |
|
118 |
* {@link Intent} that started this {@code Activity}. |
|
119 |
* <p/> |
|
120 |
* <strong>WARNING</strong>: If the {@code Activity} has |
|
121 |
* {@code android:launchMode="singleInstance"} or {@code "singleTask"}, then |
|
122 |
* this method will not disconnect because it is not possible to get the |
|
123 |
* calling {@code Activity}, as set by |
|
124 |
* {@link Activity#startActivityForResult(Intent, int)} |
|
125 |
* |
|
126 |
* @param activity the {@code Activity} to check for the {@code Intent} |
|
127 |
* @return the package of the sending app or {@code null} if it was not a |
|
128 |
* {@code ACTION_CONNECT Intent} or the {@code Intent} was not sent |
|
129 |
* with {@link Activity#startActivityForResult(Intent, int)} |
|
130 |
*/ |
|
131 |
public static String getCallingPackageName(Activity activity) { |
|
132 |
// getCallingPackage() was unstable until android-18, use this |
|
133 |
ComponentName componentName = activity.getCallingActivity(); |
|
134 |
if (componentName == null) |
|
135 |
return null; |
|
136 |
String packageName = componentName.getPackageName(); |
|
137 |
if (TextUtils.isEmpty(packageName)) { |
|
138 |
Log.e(activity.getClass().getSimpleName(), |
|
139 |
"Received Intent without sender! The Intent must be sent using startActivityForResult() and received without launchMode singleTask or singleInstance!"); |
|
140 |
} |
|
141 |
return packageName; |
|
142 |
} |
|
143 |
|
|
144 |
/** |
|
145 |
* This is used to check whether an {@link Intent} that will be sent is |
|
146 |
* complete. It should <strong>not</strong> be used with {@code Intent}s |
|
147 |
* that have been received already. |
|
148 |
*/ |
|
132 | 149 |
private boolean isIntentSane(Intent intent) { |
133 | 150 |
if (intent == null) |
134 | 151 |
return false; |
Also available in: Unified diff