| Index: chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
|
| index 99c2a0418e6c33bcb9d4d677230334e3549929bd..4e3188507cff9c14410a612f9389b0682d4a2b8c 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
|
| @@ -7,7 +7,9 @@ package org.chromium.chrome.browser.externalnav;
|
| import android.content.ActivityNotFoundException;
|
| import android.content.ComponentName;
|
| import android.content.Intent;
|
| +import android.content.pm.PackageManager;
|
| import android.content.pm.ResolveInfo;
|
| +import android.content.pm.Signature;
|
| import android.net.Uri;
|
| import android.os.SystemClock;
|
| import android.provider.Browser;
|
| @@ -28,8 +30,12 @@ import org.chromium.chrome.browser.util.UrlUtilities;
|
| import org.chromium.ui.base.PageTransition;
|
|
|
| import java.net.URI;
|
| +import java.security.MessageDigest;
|
| +import java.security.NoSuchAlgorithmException;
|
| +import java.util.Collections;
|
| import java.util.HashSet;
|
| import java.util.List;
|
| +import java.util.Set;
|
| import java.util.concurrent.TimeUnit;
|
|
|
| /**
|
| @@ -112,6 +118,69 @@ public class ExternalNavigationHandler {
|
| browserFallbackUrl = null;
|
| }
|
|
|
| + try {
|
| + //scheme
|
| + String scheme = intent.getData().getScheme();
|
| + String fragment = intent.getData().getFragment();
|
| + if (!TextUtils.isEmpty(scheme) && null != fragment && fragment.contains(";")) {
|
| + String[] parts = fragment.split(";");
|
| + String[] part = null;
|
| + Set<Set<String>> allFingerPrint256 = new HashSet<>();
|
| + String fingerPrint256 = "";
|
| + String pkgName = "";
|
| + /**
|
| + * same package name , different keystores, generated fingerprint256 set.
|
| + *
|
| + * 1.an app's signature may update and change from old, so need config and
|
| + * support new and old, but this is optional.(e.g. a.only config new fingerprint
|
| + * b. only config old fingerprint. c.config new and old fingerprint)
|
| + *
|
| + * 2.one apk itself may contain more than one keystore to sign.
|
| + *
|
| + * example: suppose apk's new signature is 3A4FXXXXXX,12XXXXXXX,and old signature
|
| + * is 1B2AXXXX. you can config the intent like "...;sha256=3A4FXXXXXX,12XXXXXXX;.."
|
| + * or "..;sha256=3A4FXXXXXX,12XXXXXXX|1B2AXXXX;.."
|
| + */
|
| + String[] fingerPrint256DifGroups;
|
| + for (String each : parts) {
|
| + part = each.split("=");
|
| + if (part[0].equals("sha256")) {
|
| + fingerPrint256 = part[1];
|
| + fingerPrint256DifGroups = fingerPrint256.split("\\|");
|
| + for (String v : fingerPrint256DifGroups) {
|
| + Set<String> fingerPrint256GroupSignKeySet = new HashSet<>();
|
| + Collections.addAll(fingerPrint256GroupSignKeySet, v.split(","));
|
| + allFingerPrint256.add(fingerPrint256GroupSignKeySet);
|
| + }
|
| + }
|
| + if (part[0].equals("package")) {
|
| + pkgName = part[1];
|
| + }
|
| + }
|
| + if (!TextUtils.isEmpty(pkgName) && !TextUtils.isEmpty(fingerPrint256)) {
|
| + PackageManager pm = mDelegate.getAssociatedActivityContext()
|
| + .getPackageManager();
|
| + Signature[] signatures = pm.getPackageInfo(pkgName,
|
| + PackageManager.GET_SIGNATURES).signatures;
|
| + HashSet<String> fingerPrint256Set = new HashSet<String>();
|
| + String fingerPrint = "";
|
| + if (signatures.length > 0) {
|
| + for (Signature each : signatures) {
|
| + fingerPrint = computeNormalizedSha256Fingerprint(each.toByteArray());
|
| + fingerPrint256Set.add(fingerPrint);
|
| + }
|
| + }
|
| + if (!allFingerPrint256.contains(fingerPrint256Set)) {
|
| + return OverrideUrlLoadingResult.NO_OVERRIDE;
|
| + }
|
| + }
|
| + }
|
| + } catch (PackageManager.NameNotFoundException e) {
|
| + return OverrideUrlLoadingResult.NO_OVERRIDE;
|
| + } catch (Exception ignore) {
|
| + //ignore the check sign miss
|
| + }
|
| +
|
| long time = SystemClock.elapsedRealtime();
|
| OverrideUrlLoadingResult result = shouldOverrideUrlLoadingInternal(
|
| params, intent, hasBrowserFallbackUrl, browserFallbackUrl);
|
| @@ -520,4 +589,37 @@ public class ExternalNavigationHandler {
|
| }
|
| return null;
|
| }
|
| +
|
| + /**
|
| + * compute normalized sha256fingerprint from signatures
|
| + *
|
| + * @return hexString of the fingerprint
|
| + */
|
| + private static String computeNormalizedSha256Fingerprint(byte[] signature) {
|
| + MessageDigest digester;
|
| + try {
|
| + digester = MessageDigest.getInstance("SHA-256");
|
| + } catch (NoSuchAlgorithmException e) {
|
| + throw new AssertionError("No SHA-256 implementation found.");
|
| + }
|
| + digester.update(signature);
|
| + return byteArrayToHexString(digester.digest());
|
| + }
|
| +
|
| + /**
|
| + * convert byteArray to String
|
| + *
|
| + * @return hexString
|
| + */
|
| + private static String byteArrayToHexString(byte[] array) {
|
| + if (array.length == 0) {
|
| + return "";
|
| + }
|
| + StringBuilder data = new StringBuilder();
|
| + for (byte anArray : array) {
|
| + data.append(Integer.toHexString((anArray >> 4) & 0x0f));
|
| + data.append(Integer.toHexString(anArray & 0x0f));
|
| + }
|
| + return data.toString().toUpperCase();
|
| + }
|
| }
|
|
|