OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.externalnav; | 5 package org.chromium.chrome.browser.externalnav; |
6 | 6 |
7 import android.content.ActivityNotFoundException; | 7 import android.content.ActivityNotFoundException; |
8 import android.content.ComponentName; | 8 import android.content.ComponentName; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.pm.PackageManager; | |
10 import android.content.pm.ResolveInfo; | 11 import android.content.pm.ResolveInfo; |
12 import android.content.pm.Signature; | |
11 import android.net.Uri; | 13 import android.net.Uri; |
12 import android.os.SystemClock; | 14 import android.os.SystemClock; |
13 import android.provider.Browser; | 15 import android.provider.Browser; |
14 import android.text.TextUtils; | 16 import android.text.TextUtils; |
15 import android.webkit.WebView; | 17 import android.webkit.WebView; |
16 | 18 |
17 import org.chromium.base.CommandLine; | 19 import org.chromium.base.CommandLine; |
18 import org.chromium.base.Log; | 20 import org.chromium.base.Log; |
19 import org.chromium.base.VisibleForTesting; | 21 import org.chromium.base.VisibleForTesting; |
20 import org.chromium.base.metrics.RecordHistogram; | 22 import org.chromium.base.metrics.RecordHistogram; |
21 import org.chromium.chrome.browser.ChromeSwitches; | 23 import org.chromium.chrome.browser.ChromeSwitches; |
22 import org.chromium.chrome.browser.IntentHandler; | 24 import org.chromium.chrome.browser.IntentHandler; |
23 import org.chromium.chrome.browser.UrlConstants; | 25 import org.chromium.chrome.browser.UrlConstants; |
24 import org.chromium.chrome.browser.tab.Tab; | 26 import org.chromium.chrome.browser.tab.Tab; |
25 import org.chromium.chrome.browser.tab.TabRedirectHandler; | 27 import org.chromium.chrome.browser.tab.TabRedirectHandler; |
26 import org.chromium.chrome.browser.util.IntentUtils; | 28 import org.chromium.chrome.browser.util.IntentUtils; |
27 import org.chromium.chrome.browser.util.UrlUtilities; | 29 import org.chromium.chrome.browser.util.UrlUtilities; |
28 import org.chromium.ui.base.PageTransition; | 30 import org.chromium.ui.base.PageTransition; |
29 | 31 |
30 import java.net.URI; | 32 import java.net.URI; |
33 import java.security.MessageDigest; | |
34 import java.security.NoSuchAlgorithmException; | |
35 import java.util.Collections; | |
31 import java.util.HashSet; | 36 import java.util.HashSet; |
32 import java.util.List; | 37 import java.util.List; |
38 import java.util.Set; | |
33 import java.util.concurrent.TimeUnit; | 39 import java.util.concurrent.TimeUnit; |
34 | 40 |
35 /** | 41 /** |
36 * Logic related to the URL overriding/intercepting functionality. | 42 * Logic related to the URL overriding/intercepting functionality. |
37 * This feature allows Chrome to convert certain navigations to Android Intents allowing | 43 * This feature allows Chrome to convert certain navigations to Android Intents allowing |
38 * applications like Youtube to direct users clicking on a http(s) link to their native app. | 44 * applications like Youtube to direct users clicking on a http(s) link to their native app. |
39 */ | 45 */ |
40 public class ExternalNavigationHandler { | 46 public class ExternalNavigationHandler { |
41 private static final String TAG = "UrlHandler"; | 47 private static final String TAG = "UrlHandler"; |
42 private static final String SCHEME_WTAI = "wtai://wp/"; | 48 private static final String SCHEME_WTAI = "wtai://wp/"; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 boolean hasBrowserFallbackUrl = false; | 111 boolean hasBrowserFallbackUrl = false; |
106 String browserFallbackUrl = | 112 String browserFallbackUrl = |
107 IntentUtils.safeGetStringExtra(intent, EXTRA_BROWSER_FALLBACK_UR L); | 113 IntentUtils.safeGetStringExtra(intent, EXTRA_BROWSER_FALLBACK_UR L); |
108 if (browserFallbackUrl != null | 114 if (browserFallbackUrl != null |
109 && UrlUtilities.isValidForIntentFallbackNavigation(browserFallba ckUrl)) { | 115 && UrlUtilities.isValidForIntentFallbackNavigation(browserFallba ckUrl)) { |
110 hasBrowserFallbackUrl = true; | 116 hasBrowserFallbackUrl = true; |
111 } else { | 117 } else { |
112 browserFallbackUrl = null; | 118 browserFallbackUrl = null; |
113 } | 119 } |
114 | 120 |
121 try { | |
122 //scheme | |
123 String scheme = intent.getData().getScheme(); | |
124 String fragment = intent.getData().getFragment(); | |
125 if (!TextUtils.isEmpty(scheme) && null != fragment && fragment.conta ins(";")) { | |
126 String[] parts = fragment.split(";"); | |
127 String[] part = null; | |
palmer
2016/07/20 18:53:48
Declare this where it's used (line 146).
| |
128 Set<Set<String>> allFingerPrint256 = new HashSet<>(); | |
129 String fingerPrint256 = ""; | |
palmer
2016/07/20 18:53:48
Declare this where it's used (line 148).
| |
130 String pkgName = ""; | |
131 /** | |
132 * same package name , different keystores, generated fingerprin t256 set. | |
133 * | |
134 * 1.an app's signature may update and change from old, so need config and | |
135 * support new and old, but this is optional.(e.g. a.only config new fingerprint | |
136 * b. only config old fingerprint. c.config new and old fingerpr int) | |
137 * | |
138 * 2.one apk itself may contain more than one keystore to sign. | |
139 * | |
140 * example: suppose apk's new signature is 3A4FXXXXXX,12XXXXXXX, and old signature | |
141 * is 1B2AXXXX. you can config the intent like "...;sha256=3A4FX XXXXX,12XXXXXXX;.." | |
142 * or "..;sha256=3A4FXXXXXX,12XXXXXXX|1B2AXXXX;.." | |
143 */ | |
144 String[] fingerPrint256DifGroups; | |
145 for (String each : parts) { | |
146 part = each.split("="); | |
147 if (part[0].equals("sha256")) { | |
148 fingerPrint256 = part[1]; | |
149 fingerPrint256DifGroups = fingerPrint256.split("\\|"); | |
150 for (String v : fingerPrint256DifGroups) { | |
151 Set<String> fingerPrint256GroupSignKeySet = new Hash Set<>(); | |
152 Collections.addAll(fingerPrint256GroupSignKeySet, v. split(",")); | |
153 allFingerPrint256.add(fingerPrint256GroupSignKeySet) ; | |
154 } | |
155 } | |
156 if (part[0].equals("package")) { | |
157 pkgName = part[1]; | |
158 } | |
159 } | |
160 if (!TextUtils.isEmpty(pkgName) && !TextUtils.isEmpty(fingerPrin t256)) { | |
161 PackageManager pm = mDelegate.getAssociatedActivityContext() | |
162 .getPackageManager(); | |
163 Signature[] signatures = pm.getPackageInfo(pkgName, | |
164 PackageManager.GET_SIGNATURES).signatures; | |
165 HashSet<String> fingerPrint256Set = new HashSet<String>(); | |
166 String fingerPrint = ""; | |
palmer
2016/07/20 18:53:48
Declare this where it's used (line 169).
| |
167 if (signatures.length > 0) { | |
168 for (Signature each : signatures) { | |
169 fingerPrint = computeNormalizedSha256Fingerprint(eac h.toByteArray()); | |
170 fingerPrint256Set.add(fingerPrint); | |
171 } | |
172 } | |
173 if (!allFingerPrint256.contains(fingerPrint256Set)) { | |
174 return OverrideUrlLoadingResult.NO_OVERRIDE; | |
175 } | |
176 } | |
177 } | |
178 } catch (PackageManager.NameNotFoundException e) { | |
179 return OverrideUrlLoadingResult.NO_OVERRIDE; | |
180 } catch (Exception ignore) { | |
181 //ignore the check sign miss | |
palmer
2016/07/20 18:53:48
Why?
| |
182 } | |
183 | |
115 long time = SystemClock.elapsedRealtime(); | 184 long time = SystemClock.elapsedRealtime(); |
116 OverrideUrlLoadingResult result = shouldOverrideUrlLoadingInternal( | 185 OverrideUrlLoadingResult result = shouldOverrideUrlLoadingInternal( |
117 params, intent, hasBrowserFallbackUrl, browserFallbackUrl); | 186 params, intent, hasBrowserFallbackUrl, browserFallbackUrl); |
118 RecordHistogram.recordTimesHistogram("Android.StrictMode.OverrideUrlLoad ingTime", | 187 RecordHistogram.recordTimesHistogram("Android.StrictMode.OverrideUrlLoad ingTime", |
119 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS); | 188 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS); |
120 | 189 |
121 if (result == OverrideUrlLoadingResult.NO_OVERRIDE && hasBrowserFallback Url | 190 if (result == OverrideUrlLoadingResult.NO_OVERRIDE && hasBrowserFallback Url |
122 && (params.getRedirectHandler() == null | 191 && (params.getRedirectHandler() == null |
123 // For instance, if this is a chained fallback URL, we i gnore it. | 192 // For instance, if this is a chained fallback URL, we i gnore it. |
124 || !params.getRedirectHandler().shouldNotOverrideUrlLoad ing())) { | 193 || !params.getRedirectHandler().shouldNotOverrideUrlLoad ing())) { |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 String defaultSmsPackageName = mDelegate.getDefaultSmsPackageName(); | 582 String defaultSmsPackageName = mDelegate.getDefaultSmsPackageName(); |
514 if (defaultSmsPackageName == null) return null; | 583 if (defaultSmsPackageName == null) return null; |
515 // Makes sure that the default SMS app actually resolves the intent. | 584 // Makes sure that the default SMS app actually resolves the intent. |
516 for (ResolveInfo resolveInfo : resolvingComponentNames) { | 585 for (ResolveInfo resolveInfo : resolvingComponentNames) { |
517 if (defaultSmsPackageName.equals(resolveInfo.activityInfo.packageNam e)) { | 586 if (defaultSmsPackageName.equals(resolveInfo.activityInfo.packageNam e)) { |
518 return defaultSmsPackageName; | 587 return defaultSmsPackageName; |
519 } | 588 } |
520 } | 589 } |
521 return null; | 590 return null; |
522 } | 591 } |
592 | |
593 /** | |
594 * compute normalized sha256fingerprint from signatures | |
595 * | |
596 * @return hexString of the fingerprint | |
597 */ | |
598 private static String computeNormalizedSha256Fingerprint(byte[] signature) { | |
palmer
2016/07/20 18:53:48
Although this is for Android package signatures, i
| |
599 MessageDigest digester; | |
600 try { | |
601 digester = MessageDigest.getInstance("SHA-256"); | |
602 } catch (NoSuchAlgorithmException e) { | |
603 throw new AssertionError("No SHA-256 implementation found."); | |
604 } | |
605 digester.update(signature); | |
606 return byteArrayToHexString(digester.digest()); | |
607 } | |
608 | |
609 /** | |
610 * convert byteArray to String | |
611 * | |
612 * @return hexString | |
613 */ | |
614 private static String byteArrayToHexString(byte[] array) { | |
palmer
2016/07/20 18:53:48
Is there not already a function that does this som
| |
615 if (array.length == 0) { | |
616 return ""; | |
617 } | |
618 StringBuilder data = new StringBuilder(); | |
619 for (byte anArray : array) { | |
palmer
2016/07/20 18:53:47
Use more concise names:
for (byte b : bytes)
| |
620 data.append(Integer.toHexString((anArray >> 4) & 0x0f)); | |
621 data.append(Integer.toHexString(anArray & 0x0f)); | |
622 } | |
623 return data.toString().toUpperCase(); | |
624 } | |
523 } | 625 } |
OLD | NEW |