Slice purchase app get URL from intent

Get the purchase URL from the intent sent by SlicePurchaseController
instead of querying CarrierConfigManager directly.

Test: manual
Test: SlicePurchaseBroadcastReceiverTest, SlicePurchaseActivityTest
Bug: 259498920
Change-Id: I163ecb44026486798e4d26dec23f2aa4aa6fbd56
This commit is contained in:
Sarah Chin
2022-12-13 12:26:55 -08:00
parent f8fb10ff1f
commit f09e5e1cc8
4 changed files with 88 additions and 47 deletions

View File

@@ -22,17 +22,14 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.URLUtil;
import android.webkit.WebView;
import com.android.phone.slice.SlicePurchaseController;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
@@ -61,37 +58,29 @@ public class SlicePurchaseActivity extends Activity {
@NonNull private WebView mWebView;
@NonNull private Context mApplicationContext;
@NonNull private Intent mIntent;
@Nullable private URL mUrl;
private int mSubId;
@NonNull private URL mUrl;
@TelephonyManager.PremiumCapability protected int mCapability;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIntent = getIntent();
mSubId = mIntent.getIntExtra(SlicePurchaseController.EXTRA_SUB_ID,
int subId = mIntent.getIntExtra(SlicePurchaseController.EXTRA_SUB_ID,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mCapability = mIntent.getIntExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
SlicePurchaseController.PREMIUM_CAPABILITY_INVALID);
String url = mIntent.getStringExtra(SlicePurchaseController.EXTRA_PURCHASE_URL);
mApplicationContext = getApplicationContext();
mUrl = getUrl();
logd("onCreate: subId=" + mSubId + ", capability="
+ TelephonyManager.convertPremiumCapabilityToString(mCapability)
+ ", url=" + mUrl);
logd("onCreate: subId=" + subId + ", capability="
+ TelephonyManager.convertPremiumCapabilityToString(mCapability) + ", url=" + url);
// Cancel network boost notification
SlicePurchaseBroadcastReceiver.cancelNotification(mApplicationContext, mCapability);
// Verify intent and values are valid
if (!SlicePurchaseBroadcastReceiver.isIntentValid(mIntent)) {
loge("Not starting SlicePurchaseActivity with an invalid Intent: " + mIntent);
SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponse(
mIntent, SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED);
finishAndRemoveTask();
return;
}
// Verify purchase URL is valid
mUrl = SlicePurchaseBroadcastReceiver.getPurchaseUrl(url);
if (mUrl == null) {
String error = "Unable to create a URL from carrier configs.";
String error = "Unable to create a purchase URL.";
loge(error);
Intent data = new Intent();
data.putExtra(SlicePurchaseController.EXTRA_FAILURE_CODE,
@@ -102,9 +91,20 @@ public class SlicePurchaseActivity extends Activity {
finishAndRemoveTask();
return;
}
if (mSubId != SubscriptionManager.getDefaultSubscriptionId()) {
// Verify intent is valid
if (!SlicePurchaseBroadcastReceiver.isIntentValid(mIntent)) {
loge("Not starting SlicePurchaseActivity with an invalid Intent: " + mIntent);
SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponse(
mIntent, SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED);
finishAndRemoveTask();
return;
}
// Verify sub ID is valid
if (subId != SubscriptionManager.getDefaultSubscriptionId()) {
loge("Unable to start the slice purchase application on the non-default data "
+ "subscription: " + mSubId);
+ "subscription: " + subId);
SlicePurchaseBroadcastReceiver.sendSlicePurchaseAppResponse(
mIntent, SlicePurchaseController.EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION);
finishAndRemoveTask();
@@ -159,24 +159,6 @@ public class SlicePurchaseActivity extends Activity {
super.onDestroy();
}
@Nullable private URL getUrl() {
String url = mApplicationContext.getSystemService(CarrierConfigManager.class)
.getConfigForSubId(mSubId).getString(
CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING);
boolean isUrlValid = URLUtil.isValidUrl(url);
if (URLUtil.isAssetUrl(url)) {
isUrlValid = url.equals(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
}
if (isUrlValid) {
try {
return new URL(url);
} catch (MalformedURLException ignored) {
}
}
loge("Invalid URL: " + url);
return null;
}
private void setupWebView() {
// Create WebView
mWebView = new WebView(this);

View File

@@ -16,6 +16,7 @@
package com.android.carrierdefaultapp;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -35,11 +36,15 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.URLUtil;
import android.webkit.WebView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.phone.slice.SlicePurchaseController;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
@@ -140,7 +145,7 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
* Check whether the Intent is valid and can be used to complete purchases in the slice purchase
* application. This checks that all necessary extras exist and that the values are valid.
*
* @param intent The intent to check
* @param intent The intent to check.
* @return {@code true} if the intent is valid and {@code false} otherwise.
*/
public static boolean isIntentValid(@NonNull Intent intent) {
@@ -165,6 +170,12 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
return false;
}
String purchaseUrl = intent.getStringExtra(SlicePurchaseController.EXTRA_PURCHASE_URL);
if (getPurchaseUrl(purchaseUrl) == null) {
loge("isIntentValid: invalid purchase URL: " + purchaseUrl);
return false;
}
String appName = intent.getStringExtra(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME);
if (TextUtils.isEmpty(appName)) {
loge("isIntentValid: empty requesting application name: " + appName);
@@ -181,6 +192,30 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN);
}
/**
* Get the {@link URL} from the given purchase URL String, if it is valid.
*
* @param purchaseUrl The purchase URL String to use to create the URL.
* @return The purchase URL from the given String or {@code null} if it is invalid.
*/
@Nullable public static URL getPurchaseUrl(@Nullable String purchaseUrl) {
if (!URLUtil.isValidUrl(purchaseUrl)) {
return null;
}
if (URLUtil.isAssetUrl(purchaseUrl)
&& !purchaseUrl.equals(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE)) {
return null;
}
URL url = null;
try {
url = new URL(purchaseUrl);
url.toURI();
} catch (MalformedURLException | URISyntaxException e) {
loge("Invalid purchase URL: " + purchaseUrl + ", " + e);
}
return url;
}
private static boolean isPendingIntentValid(@NonNull Intent intent, @NonNull String extra) {
String intentType = getPendingIntentType(extra);
PendingIntent pendingIntent = intent.getParcelableExtra(extra, PendingIntent.class);

View File

@@ -39,7 +39,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.phone.slice.SlicePurchaseController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -94,6 +93,8 @@ public class SlicePurchaseActivityTest extends ActivityUnitTestCase<SlicePurchas
SubscriptionManager.getDefaultDataSubscriptionId());
intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
intent.putExtra(SlicePurchaseController.EXTRA_PURCHASE_URL,
SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
intent.putExtra(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME, TAG);
Intent spiedIntent = spy(intent);
@@ -110,12 +111,6 @@ public class SlicePurchaseActivityTest extends ActivityUnitTestCase<SlicePurchas
mSlicePurchaseActivity = startActivity(spiedIntent, null, null);
}
@After
public void tearDown() throws Exception {
mSlicePurchaseActivity.onDestroy();
super.tearDown();
}
@Test
public void testOnPurchaseSuccessful() throws Exception {
int duration = 5 * 60 * 1000; // 5 minutes

View File

@@ -18,6 +18,7 @@ package com.android.carrierdefaultapp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
@@ -55,6 +56,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.net.URL;
import java.util.Locale;
@RunWith(AndroidJUnit4.class)
@@ -132,6 +134,8 @@ public class SlicePurchaseBroadcastReceiverTest {
eq(SlicePurchaseController.EXTRA_SUB_ID), anyInt());
doReturn(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY).when(mIntent).getIntExtra(
eq(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY), anyInt());
doReturn(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_PURCHASE_URL));
doReturn(TAG).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME));
assertFalse(SlicePurchaseBroadcastReceiver.isIntentValid(mIntent));
@@ -144,6 +148,29 @@ public class SlicePurchaseBroadcastReceiverTest {
assertTrue(SlicePurchaseBroadcastReceiver.isIntentValid(mIntent));
}
@Test
public void testGetPurchaseUrl() {
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) {
URL purchaseUrl = SlicePurchaseBroadcastReceiver.getPurchaseUrl(url);
assertNull(purchaseUrl);
}
assertEquals(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE,
SlicePurchaseBroadcastReceiver.getPurchaseUrl(
SlicePurchaseController.SLICE_PURCHASE_TEST_FILE).toString());
}
@Test
public void testDisplayNetworkBoostNotification() throws Exception {
displayNetworkBoostNotification();
@@ -200,6 +227,8 @@ public class SlicePurchaseBroadcastReceiverTest {
eq(SlicePurchaseController.EXTRA_SUB_ID), anyInt());
doReturn(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY).when(mIntent).getIntExtra(
eq(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY), anyInt());
doReturn(SlicePurchaseController.SLICE_PURCHASE_TEST_FILE).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_PURCHASE_URL));
doReturn(TAG).when(mIntent).getStringExtra(
eq(SlicePurchaseController.EXTRA_REQUESTING_APP_NAME));
mSlicePurchaseBroadcastReceiver.onReceive(mContext, mIntent);