Revision 0fc4c33f

View differences:

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