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

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: Typo. 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 {
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 if (sPackageToCachedOrigins != null) 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 /**
103 * Returns whether an origin is first-party relative to a given package name .
104 *
105 * This only returns data from previously cached relations, and does not
106 * trigger an asynchronous validation.
107 *
108 * @param packageName The package name
109 * @param origin The origin to verify
110 */
111 static boolean isValidOrigin(String packageName, Uri origin) {
112 ThreadUtils.assertOnUiThread();
113 if (sPackageToCachedOrigins == null) return false;
114 Set<Uri> cachedOrigins = sPackageToCachedOrigins.get(packageName);
115 if (cachedOrigins == null) return false;
116 return cachedOrigins.contains(origin);
117 }
118
119 /**
81 * Callback interface for getting verification results. 120 * Callback interface for getting verification results.
82 */ 121 */
83 public interface OriginVerificationListener { 122 public interface OriginVerificationListener {
84 /** 123 /**
85 * To be posted on the handler thread after the verification finishes. 124 * 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. 125 * @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. 126 * @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. 127 * @param verified Whether the given origin was verified to correspond t o the given package.
89 */ 128 */
90 void onOriginVerified(String packageName, Uri origin, boolean verified); 129 void onOriginVerified(String packageName, Uri origin, boolean verified);
(...skipping 14 matching lines...) Expand all
105 /** 144 /**
106 * Verify the claimed origin for the cached package name asynchronously. Thi s will end up 145 * 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 146 * making a network request for non-cached origins with a URLFetcher using t he last used
108 * profile as context. 147 * profile as context.
109 * @param origin The postMessage origin the application is claiming to have. Can't be null. 148 * @param origin The postMessage origin the application is claiming to have. Can't be null.
110 */ 149 */
111 public void start(@NonNull Uri origin) { 150 public void start(@NonNull Uri origin) {
112 ThreadUtils.assertOnUiThread(); 151 ThreadUtils.assertOnUiThread();
113 mOrigin = origin; 152 mOrigin = origin;
114 if (!UrlConstants.HTTPS_SCHEME.equals(mOrigin.getScheme().toLowerCase(Lo cale.US))) { 153 if (!UrlConstants.HTTPS_SCHEME.equals(mOrigin.getScheme().toLowerCase(Lo cale.US))) {
115 ThreadUtils.postOnUiThread(new Runnable() { 154 ThreadUtils.runOnUiThread(new VerifiedCallback(false));
116 @Override
117 public void run() {
118 originVerified(false);
119 }
120 });
121 return; 155 return;
122 } 156 }
123 157
124 // If this origin is cached as verified already, use that. 158 // If this origin is cached as verified already, use that.
125 Uri cachedOrigin = getCachedOriginIfExists(); 159 if (isValidOrigin(mPackageName, origin)) {
126 if (cachedOrigin != null && cachedOrigin.equals(origin)) { 160 ThreadUtils.runOnUiThread(new VerifiedCallback(true));
127 ThreadUtils.postOnUiThread(new Runnable() {
128 @Override
129 public void run() {
130 originVerified(true);
131 }
132 });
133 return; 161 return;
134 } 162 }
135 if (mNativeOriginVerifier != 0) cleanUp(); 163 if (mNativeOriginVerifier != 0) cleanUp();
136 if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) 164 if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
137 .isStartupSuccessfullyCompleted()) { 165 .isStartupSuccessfullyCompleted()) {
138 // Early return for testing without native. 166 // Early return for testing without native.
139 return; 167 return;
140 } 168 }
141 mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOrigi nalProfile()); 169 mNativeOriginVerifier = nativeInit(Profile.getLastUsedProfile().getOrigi nalProfile());
142 assert mNativeOriginVerifier != 0; 170 assert mNativeOriginVerifier != 0;
143 boolean success = nativeVerifyOrigin( 171 boolean success = nativeVerifyOrigin(
144 mNativeOriginVerifier, mPackageName, mSignatureFingerprint, mOri gin.toString()); 172 mNativeOriginVerifier, mPackageName, mSignatureFingerprint, mOri gin.toString());
145 if (!success) { 173 if (!success) ThreadUtils.runOnUiThread(new VerifiedCallback(false));
146 ThreadUtils.postOnUiThread(new Runnable() {
147 @Override
148 public void run() {
149 originVerified(false);
150 }
151 });
152 }
153 } 174 }
154 175
155 /** 176 /**
156 * Cleanup native dependencies on this object. 177 * Cleanup native dependencies on this object.
157 */ 178 */
158 void cleanUp() { 179 void cleanUp() {
159 if (mNativeOriginVerifier == 0) return; 180 if (mNativeOriginVerifier == 0) return;
160 nativeDestroy(mNativeOriginVerifier); 181 nativeDestroy(mNativeOriginVerifier);
161 mNativeOriginVerifier = 0; 182 mNativeOriginVerifier = 0;
162 } 183 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]); 233 hexString.append(HEX_CHAR_LOOKUP[(byteArray[i] & 0xf0) >>> 4]);
213 hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]); 234 hexString.append(HEX_CHAR_LOOKUP[byteArray[i] & 0xf]);
214 if (i < (byteArray.length - 1)) hexString.append(':'); 235 if (i < (byteArray.length - 1)) hexString.append(':');
215 } 236 }
216 return hexString.toString(); 237 return hexString.toString();
217 } 238 }
218 239
219 @CalledByNative 240 @CalledByNative
220 private void originVerified(boolean originVerified) { 241 private void originVerified(boolean originVerified) {
221 if (originVerified) { 242 if (originVerified) {
222 cacheVerifiedOriginIfNeeded(mPackageName, mOrigin); 243 addVerifiedOriginForPackage(mPackageName, mOrigin);
223 mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrig in); 244 mOrigin = getPostMessageOriginFromVerifiedOrigin(mPackageName, mOrig in);
224 } 245 }
225 mListener.onOriginVerified(mPackageName, mOrigin, originVerified); 246 mListener.onOriginVerified(mPackageName, mOrigin, originVerified);
226 cleanUp(); 247 cleanUp();
227 } 248 }
228 249
229 private Uri getCachedOriginIfExists() {
230 if (sCachedOriginMap == null) return null;
231 return sCachedOriginMap.get(mPackageName);
232 }
233
234 private native long nativeInit(Profile profile); 250 private native long nativeInit(Profile profile);
235 private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName, 251 private native boolean nativeVerifyOrigin(long nativeOriginVerifier, String packageName,
236 String signatureFingerprint, String origin); 252 String signatureFingerprint, String origin);
237 private native void nativeDestroy(long nativeOriginVerifier); 253 private native void nativeDestroy(long nativeOriginVerifier);
238 } 254 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698