Fix URL validation

Check that the URL is valid using URLUtils. If the URL is an asset URL,
check that the file path is correct.

Test: manual and unit
Bug: 256184290
Change-Id: I1ae8d9641cb4aee90f06a09c9e02e6fca2492113
diff --git a/src/com/android/phone/slice/SlicePurchaseController.java b/src/com/android/phone/slice/SlicePurchaseController.java
index f40bb69..ead6b8c 100644
--- a/src/com/android/phone/slice/SlicePurchaseController.java
+++ b/src/com/android/phone/slice/SlicePurchaseController.java
@@ -46,6 +46,7 @@
 import android.telephony.data.NetworkSlicingConfig;
 import android.text.TextUtils;
 import android.util.Log;
+import android.webkit.URLUtil;
 import android.webkit.WebView;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -54,6 +55,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -105,6 +107,10 @@
     /** Value for an invalid premium capability. */
     public static final int PREMIUM_CAPABILITY_INVALID = -1;
 
+    /** Asset URL for the slice_purchase_test.html file. */
+    public static final String SLICE_PURCHASE_TEST_FILE =
+            "file:///android_asset/slice_purchase_test.html";
+
     /** Purchasing the premium capability is no longer throttled. */
     private static final int EVENT_PURCHASE_UNTHROTTLED = 1;
     /** Slicing config changed. */
@@ -759,14 +765,8 @@
             @TelephonyManager.PremiumCapability int capability) {
         String url = getCarrierConfigs().getString(
                 CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING);
-        if (TextUtils.isEmpty(url)) {
+        if (!isUrlValid(url)) {
             return false;
-        } else {
-            try {
-                new URL(url);
-            } catch (MalformedURLException e) {
-                return false;
-            }
         }
         int[] supportedCapabilities = getCarrierConfigs().getIntArray(
                 CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY);
@@ -777,6 +777,25 @@
                 .anyMatch(supportedCapability -> supportedCapability == capability);
     }
 
+    private boolean isUrlValid(@Nullable String url) {
+        if (!URLUtil.isValidUrl(url)) {
+            loge("Invalid URL: " + url);
+            return false;
+        }
+        if (URLUtil.isAssetUrl(url) && !url.equals(SLICE_PURCHASE_TEST_FILE)) {
+            loge("Invalid asset: " + url);
+            return false;
+        }
+        try {
+            new URL(url).toURI();
+        } catch (MalformedURLException | URISyntaxException e) {
+            loge("Invalid URI: " + url);
+            return false;
+        }
+        logd("Valid URL: " + url);
+        return true;
+    }
+
     private boolean arePremiumCapabilitiesSupportedByDevice() {
         // TODO: Add more checks?
         //  Maybe device resource overlay to enable/disable in addition to carrier configs
diff --git a/tests/src/com/android/phone/SlicePurchaseControllerTest.java b/tests/src/com/android/phone/SlicePurchaseControllerTest.java
index 260bd91..ebcf15d 100644
--- a/tests/src/com/android/phone/SlicePurchaseControllerTest.java
+++ b/tests/src/com/android/phone/SlicePurchaseControllerTest.java
@@ -70,7 +70,6 @@
 @RunWith(AndroidJUnit4.class)
 public class SlicePurchaseControllerTest extends TelephonyTestBase {
     private static final String TAG = "SlicePurchaseControllerTest";
-    private static final String URL = "file:///android_asset/slice_purchase_test.html";
     private static final int PHONE_ID = 0;
     private static final long NOTIFICATION_TIMEOUT = 1000;
     private static final long PURCHASE_CONDITION_TIMEOUT = 2000;
@@ -158,7 +157,8 @@
                 .getCachedAllowedNetworkTypesBitmask();
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
         doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
 
@@ -168,6 +168,39 @@
     }
 
     @Test
+    public void testIsUrlValid() {
+        // all other conditions met
+        doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+                .getCachedAllowedNetworkTypesBitmask();
+        mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+                new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+        doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+
+        String[] invalidUrls = new String[] {
+                null,
+                "",
+                "www.google.com",
+                "htt://www.google.com",
+                "http//www.google.com",
+                "http:/www.google.com",
+                "file:///android_asset/",
+                "file:///android_asset/slice_store_test.html"
+        };
+        for (String url : invalidUrls) {
+            mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, url);
+            doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+            assertFalse(mSlicePurchaseController.isPremiumCapabilityAvailableForPurchase(
+                    TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY));
+        }
+
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+        doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+        assertTrue(mSlicePurchaseController.isPremiumCapabilityAvailableForPurchase(
+                TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY));
+    }
+
+    @Test
     public void testPurchasePremiumCapabilityResultFeatureNotSupported() {
         mSlicePurchaseController.purchasePremiumCapability(
                 TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, TAG,
@@ -202,7 +235,8 @@
         // retry after enabling carrier configs
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
 
         mSlicePurchaseController.purchasePremiumCapability(
@@ -219,7 +253,8 @@
                 .getCachedAllowedNetworkTypesBitmask();
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
 
         mSlicePurchaseController.purchasePremiumCapability(
@@ -248,7 +283,8 @@
                 .getCachedAllowedNetworkTypesBitmask();
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
         doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
 
@@ -276,7 +312,8 @@
                 .getCachedAllowedNetworkTypesBitmask();
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
         doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
         doReturn(TelephonyManager.NETWORK_TYPE_NR).when(mServiceState).getDataNetworkType();
@@ -564,7 +601,8 @@
         // carrier supported
         mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
                 new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
-        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, URL);
+        mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+                SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
         mBundle.putLong(CarrierConfigManager
                 .KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG,
                 NOTIFICATION_TIMEOUT);