Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/customtabs/OriginVerifier.java

Issue 2970003003: customtabs: Extract a redirect endpoint, and maybe connect to it. (Closed)
Patch Set: . Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.customtabs; 5 package org.chromium.chrome.browser.customtabs;
6 6
7 import android.content.pm.PackageInfo; 7 import android.content.pm.PackageInfo;
8 import android.content.pm.PackageManager; 8 import android.content.pm.PackageManager;
9 import android.net.Uri; 9 import android.net.Uri;
10 import android.support.annotation.NonNull; 10 import android.support.annotation.NonNull;
(...skipping 12 matching lines...) Expand all
23 23
24 import java.io.ByteArrayInputStream; 24 import java.io.ByteArrayInputStream;
25 import java.io.InputStream; 25 import java.io.InputStream;
26 import java.security.MessageDigest; 26 import java.security.MessageDigest;
27 import java.security.NoSuchAlgorithmException; 27 import java.security.NoSuchAlgorithmException;
28 import java.security.cert.CertificateEncodingException; 28 import java.security.cert.CertificateEncodingException;
29 import java.security.cert.CertificateException; 29 import java.security.cert.CertificateException;
30 import java.security.cert.CertificateFactory; 30 import java.security.cert.CertificateFactory;
31 import java.security.cert.X509Certificate; 31 import java.security.cert.X509Certificate;
32 import java.util.HashMap; 32 import java.util.HashMap;
33 import java.util.HashSet;
33 import java.util.Locale; 34 import java.util.Locale;
34 import java.util.Map; 35 import java.util.Map;
36 import java.util.Set;
35 37
36 /** 38 /**
37 * Used to verify postMessage origin for a designated package name. 39 * Used to verify postMessage origin for a designated package name.
38 * 40 *
39 * Uses Digital Asset Links to confirm that the given origin is associated with the package name as 41 * Uses Digital Asset Links to confirm that the given origin is associated with the package name as
40 * a postMessage origin. It caches any origin that has been verified during the current application 42 * a postMessage origin. It caches any origin that has been verified during the current application
41 * lifecycle and reuses that without making any new network requests. 43 * lifecycle and reuses that without making any new network requests.
42 * 44 *
43 * The lifecycle of this object is governed by the owner. The owner has to call 45 * The lifecycle of this object is governed by the owner. The owner has to call
44 * {@link OriginVerifier#cleanUp()} for proper cleanup of dependencies. 46 * {@link OriginVerifier#cleanUp()} for proper cleanup of dependencies.
45 */ 47 */
46 @JNINamespace("customtabs") 48 @JNINamespace("customtabs")
47 class OriginVerifier { 49 class OriginVerifier {
48 private static final String TAG = "OriginVerifier"; 50 private static final String TAG = "OriginVerifier";
49 private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray (); 51 private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray ();
50 private static Map<String, Uri> sCachedOriginMap; 52 private static Map<String, Set<Uri>> sPackageToCachedOrigins;
51 private final OriginVerificationListener mListener; 53 private final OriginVerificationListener mListener;
52 private final String mPackageName; 54 private final String mPackageName;
53 private final String mSignatureFingerprint; 55 private final String mSignatureFingerprint;
54 private long mNativeOriginVerifier = 0; 56 private long mNativeOriginVerifier = 0;
55 private Uri mOrigin; 57 private Uri mOrigin;
56 58
57 /** 59 /** Small helper class to post a result of origin verification. */
58 * To be used for prepopulating verified origin for testing functionality. 60 private class VerifiedCallback implements Runnable {
Yusuf 2017/07/06 06:34:42 Thanks!
59 * @param packageName The package name to prepopulate for. 61 private final boolean mResult;
60 * @param origin The origin to add as verified. 62
61 */ 63 public VerifiedCallback(boolean result) {
62 @VisibleForTesting 64 this.mResult = result;
63 static void prePopulateVerifiedOriginForTesting(String packageName, Uri orig in) { 65 }
64 cacheVerifiedOriginIfNeeded(packageName, origin); 66
67 @Override
68 public void run() {
69 originVerified(mResult);
70 }
65 } 71 }
66 72
67 private static Uri getPostMessageOriginFromVerifiedOrigin( 73 private static Uri getPostMessageOriginFromVerifiedOrigin(
68 String packageName, Uri verifiedOrigin) { 74 String packageName, Uri verifiedOrigin) {
69 return Uri.parse(IntentHandler.ANDROID_APP_REFERRER_SCHEME + "://" 75 return Uri.parse(IntentHandler.ANDROID_APP_REFERRER_SCHEME + "://"
70 + verifiedOrigin.getHost() + "/" + packageName); 76 + verifiedOrigin.getHost() + "/" + packageName);
71 } 77 }
72 78
73 private static void cacheVerifiedOriginIfNeeded(String packageName, Uri orig in) { 79 /** Clears all known relations. */
74 if (sCachedOriginMap == null) sCachedOriginMap = new HashMap<>(); 80 @VisibleForTesting
75 if (!sCachedOriginMap.containsKey(packageName)) { 81 static void reset() {
76 sCachedOriginMap.put(packageName, origin); 82 ThreadUtils.assertOnUiThread();
77 } 83 sPackageToCachedOrigins.clear();
78 } 84 }
79 85
80 /** 86 /**
87 * Mark an origin as verified for a package.
88 * @param packageName The package name to prepopulate for.
89 * @param origin The origin to add as verified.
90 */
91 static void addVerifiedOriginForPackage(String packageName, Uri origin) {
92 ThreadUtils.assertOnUiThread();
93 if (sPackageToCachedOrigins == null) sPackageToCachedOrigins = new HashM ap<>();
94 Set<Uri> cachedOrigins = sPackageToCachedOrigins.get(packageName);
95 if (cachedOrigins == null) {
96 cachedOrigins = new HashSet<Uri>();
97 sPackageToCachedOrigins.put(packageName, cachedOrigins);
98 }
99 cachedOrigins.add(origin);
100 }
101
102 static boolean isValidOrigin(String packageName, Uri origin) {
Yusuf 2017/07/06 06:34:42 javadoc Maybe something around no async verificat
Benoit L 2017/07/07 11:30:56 Done.
103 ThreadUtils.assertOnUiThread();
104 if (sPackageToCachedOrigins == null) return false;
105 Set<Uri> cachedOrigins = sPackageToCachedOrigins.get(packageName);
106 if (cachedOrigins == null) return false;
107 return cachedOrigins.contains(origin);
108 }
109
110 /**
81 * Callback interface for getting verification results. 111 * Callback interface for getting verification results.
82 */ 112 */
83 public interface OriginVerificationListener { 113 public interface OriginVerificationListener {
84 /** 114 /**
85 * To be posted on the handler thread after the verification finishes. 115 * To be posted on the handler thread after the verification finishes.
86 * @param packageName The package name for the origin verification query for this result. 116 * @param packageName The package name for the origin verification query for this result.
87 * @param origin The origin that was declared on the query for this resu lt. 117 * @param origin The origin that was declared on the query for this resu lt.
88 * @param verified Whether the given origin was verified to correspond t o the given package. 118 * @param verified Whether the given origin was verified to correspond t o the given package.
89 */ 119 */
90 void onOriginVerified(String packageName, Uri origin, boolean verified); 120 void onOriginVerified(String packageName, Uri origin, boolean verified);
(...skipping 14 matching lines...) Expand all
105 /** 135 /**
106 * Verify the claimed origin for the cached package name asynchronously. Thi s will end up 136 * Verify the claimed origin for the cached package name asynchronously. Thi s will end up
107 * making a network request for non-cached origins with a URLFetcher using t he last used 137 * making a network request for non-cached origins with a URLFetcher using t he last used
108 * profile as context. 138 * profile as context.
109 * @param origin The postMessage origin the application is claiming to have. Can't be null. 139 * @param origin The postMessage origin the application is claiming to have. Can't be null.
110 */ 140 */
111 public void start(@NonNull Uri origin) { 141 public void start(@NonNull Uri origin) {
112 ThreadUtils.assertOnUiThread(); 142 ThreadUtils.assertOnUiThread();
113 mOrigin = origin; 143 mOrigin = origin;
114 if (!UrlConstants.HTTPS_SCHEME.equals(mOrigin.getScheme().toLowerCase(Lo cale.US))) { 144 if (!UrlConstants.HTTPS_SCHEME.equals(mOrigin.getScheme().toLowerCase(Lo cale.US))) {
115 ThreadUtils.postOnUiThread(new Runnable() { 145 ThreadUtils.postOnUiThread(new VerifiedCallback(false));
116 @Override
117 public void run() {
118 originVerified(false);
119 }
120 });
121 return; 146 return;
122 } 147 }
123 148
124 // If this origin is cached as verified already, use that. 149 // If this origin is cached as verified already, use that.
125 Uri cachedOrigin = getCachedOriginIfExists(); 150 if (isValidOrigin(mPackageName, origin)) {
126 if (cachedOrigin != null && cachedOrigin.equals(origin)) { 151 ThreadUtils.postOnUiThread(new VerifiedCallback(true));
127 ThreadUtils.postOnUiThread(new Runnable() {
128 @Override
129 public void run() {
130 originVerified(true);
131 }
132 });
133 return; 152 return;
134 } 153 }
135 if (mNativeOriginVerifier != 0) cleanUp(); 154 if (mNativeOriginVerifier != 0) cleanUp();
136 if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) 155 if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
137 .isStartupSuccessfullyCompleted()) { 156 .isStartupSuccessfullyCompleted()) {
138 // Early return for testing without native. 157 // Early return for testing without native.
139 return; 158 return;
140 } 159 }
141 mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOrigi nalProfile()); 160 mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOrigi nalProfile());
142 assert mNativeOriginVerifier != 0; 161 assert mNativeOriginVerifier != 0;
143 boolean success = nativeVerifyOrigin( 162 boolean success = nativeVerifyOrigin(
144 mNativeOriginVerifier, mPackageName, mSignatureFingerprint, mOri gin.toString()); 163 mNativeOriginVerifier, mPackageName, mSignatureFingerprint, mOri gin.toString());
145 if (!success) { 164 if (!success) ThreadUtils.postOnUiThread(new VerifiedCallback(false));
146 ThreadUtils.postOnUiThread(new Runnable() {
147 @Override
148 public void run() {
149 originVerified(false);
150 }
151 });
152 }
153 } 165 }
154 166
155 /** 167 /**
156 * Cleanup native dependencies on this object. 168 * Cleanup native dependencies on this object.
157 */ 169 */
158 void cleanUp() { 170 void cleanUp() {
159 if (mNativeOriginVerifier == 0) return; 171 if (mNativeOriginVerifier == 0) return;
160 nativeDestroy(mNativeOriginVerifier); 172 nativeDestroy(mNativeOriginVerifier);
161 mNativeOriginVerifier = 0; 173 mNativeOriginVerifier = 0;
162 } 174 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]); 224 hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]);
213 hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]); 225 hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]);
214 if (i < (byteArray.length - 1)) hexString.append(':'); 226 if (i < (byteArray.length - 1)) hexString.append(':');
215 } 227 }
216 return hexString.toString(); 228 return hexString.toString();
217 } 229 }
218 230
219 @CalledByNative 231 @CalledByNative
220 private void originVerified(boolean originVerified) { 232 private void originVerified(boolean originVerified) {
221 if (originVerified) { 233 if (originVerified) {
222 cacheVerifiedOriginIfNeeded(mPackageName, mOrigin); 234 addVerifiedOriginForPackage(mPackageName, mOrigin);
223 mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrig in); 235 mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrig in);
224 } 236 }
225 mListener.onOriginVerified(mPackageName, mOrigin, originVerified); 237 mListener.onOriginVerified(mPackageName, mOrigin, originVerified);
226 cleanUp(); 238 cleanUp();
227 } 239 }
228 240
229 private Uri getCachedOriginIfExists() {
230 if (sCachedOriginMap == null) return null;
231 return sCachedOriginMap.get(mPackageName);
232 }
233
234 private native long nativeInit(Profile profile); 241 private native long nativeInit(Profile profile);
235 private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName, 242 private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName,
236 String signatureFingerprint, String origin); 243 String signatureFingerprint, String origin);
237 private native void nativeDestroy(long nativeOriginVerifier); 244 private native void nativeDestroy(long nativeOriginVerifier);
238 } 245 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698