Skip to content

Commit

Permalink
Merge pull request #411 from Iterable/jay/MOB-3769-allowed-protocols
Browse files Browse the repository at this point in the history
[MOB-3769] allowed protocols
  • Loading branch information
Ayyanchira authored Dec 23, 2021
2 parents f0a694a + c3d5543 commit 873708f
Show file tree
Hide file tree
Showing 13 changed files with 67 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

@RunWith(AndroidJUnit4.class)
public class IterableApiDeeplinkTest {

@Before
public void setUp() {

}

@After
Expand All @@ -30,7 +30,7 @@ public void tearDown() throws Exception {
public void testUniversalDeepLinkNoRewrite() throws Exception {
final CountDownLatch signal = new CountDownLatch(1);
try {
final String requestString = "http://links.iterable.com/u/60402396fbd5433eb35397b47ab2fb83?_e=joneng%40iterable.com&_m=93125f33ba814b13a882358f8e0852e0";
final String requestString = "https://links.iterable.com/u/60402396fbd5433eb35397b47ab2fb83?_e=joneng%40iterable.com&_m=93125f33ba814b13a882358f8e0852e0";
IterableHelper.IterableActionHandler clickCallback = new IterableHelper.IterableActionHandler() {
@Override
public void execute(String result) {
Expand All @@ -39,7 +39,7 @@ public void execute(String result) {
}
};

IterableApi.getAndTrackDeeplink(requestString, clickCallback);
IterableApi.getInstance().getAndTrackDeepLink(requestString, clickCallback);
assertTrue("callback is called", signal.await(5, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
Expand All @@ -61,7 +61,7 @@ public void execute(String result) {
}
};

IterableApi.getAndTrackDeeplink(requestString, clickCallback);
IterableApi.getInstance().getAndTrackDeepLink(requestString, clickCallback);
assertTrue("callback is called", signal.await(5, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
Expand All @@ -72,15 +72,15 @@ public void execute(String result) {
public void testEmptyRedirect() throws Exception {
final CountDownLatch signal = new CountDownLatch(1);
try {
final String requestString = "";
final String requestString = "https";
IterableHelper.IterableActionHandler clickCallback = new IterableHelper.IterableActionHandler() {
@Override
public void execute(String result) {
assertEquals(requestString, result);
signal.countDown();
}
};
IterableApi.getAndTrackDeeplink(requestString, clickCallback);
IterableApi.getInstance().getAndTrackDeepLink(requestString, clickCallback);
signal.await();
} catch (InterruptedException e) {
e.printStackTrace();
Expand All @@ -99,7 +99,7 @@ public void execute(String result) {
signal.countDown();
}
};
IterableApi.getAndTrackDeeplink(requestString, clickCallback);
IterableApi.getInstance().getAndTrackDeepLink(requestString, clickCallback);
assertTrue("callback is called", signal.await(5, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
Expand All @@ -119,7 +119,7 @@ public void execute(String result) {
signal.countDown();
}
};
IterableApi.getAndTrackDeeplink(requestString, clickCallback);
IterableApi.getInstance().getAndTrackDeepLink(requestString, clickCallback);
signal.await();
} catch (InterruptedException e) {
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"openApp": true,
"action": {
"type": "openUrl",
"data": "http://maps.apple.com/?ll=37.7828,-122.3984"
"data": "https://maps.apple.com/?ll=37.7828,-122.3984"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ boolean executeAction(@NonNull Context context, @Nullable IterableAction action,
* `false` if the handler did not handle this URL and no activity was found to open it with
*/
private boolean openUri(@NonNull Context context, @NonNull Uri uri, @NonNull IterableActionContext actionContext) {
// Handle URL: check for deep links within the app
if (!IterableUtil.isUrlOpenAllowed(uri.toString())) {
return false;
}

if (IterableApi.sharedInstance.config.urlHandler != null) {
if (IterableApi.sharedInstance.config.urlHandler.handleIterableURL(uri, actionContext)) {
return true;
Expand Down Expand Up @@ -107,5 +112,4 @@ private boolean callCustomActionIfSpecified(@NonNull IterableAction action, @Non
return false;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public class IterableApi {
//---------------------------------------------------------------------------------------
//endregion


//region Getters/Setters
//---------------------------------------------------------------------------------------

Expand Down Expand Up @@ -105,7 +104,6 @@ public String getPayloadData(@NonNull String key) {
* Retrieves all of the payload as a single Bundle Object
* @return Bundle
*/

@Nullable
public Bundle getPayloadData() {
return _payloadData;
Expand Down Expand Up @@ -252,8 +250,6 @@ public void removeDeviceAttribute(String key) {
//---------------------------------------------------------------------------------------
//endregion



//region Public Functions
//---------------------------------------------------------------------------------------

Expand Down Expand Up @@ -295,14 +291,17 @@ public static void initialize(@NonNull Context context, @NonNull String apiKey,
if (sharedInstance.config == null) {
sharedInstance.config = new IterableConfig.Builder().build();
}

sharedInstance.retrieveEmailAndUserId();

IterableActivityMonitor.getInstance().registerLifecycleCallbacks(context);
IterableActivityMonitor.getInstance().addCallback(sharedInstance.activityMonitorListener);

if (sharedInstance.inAppManager == null) {
sharedInstance.inAppManager = new IterableInAppManager(sharedInstance, sharedInstance.config.inAppHandler,
sharedInstance.config.inAppDisplayInterval);
}

loadLastSavedConfiguration(context);
IterablePushActionReceiver.processPendingAction(context);
}
Expand Down Expand Up @@ -402,7 +401,7 @@ public void setUserId(@Nullable String userId) {
* @param onCallback Calls the callback handler with the destination location
* or the original url if it is not an Iterable link.
*/
public static void getAndTrackDeeplink(@NonNull String uri, @NonNull IterableHelper.IterableActionHandler onCallback) {
public void getAndTrackDeepLink(@NonNull String uri, @NonNull IterableHelper.IterableActionHandler onCallback) {
IterableDeeplinkManager.getAndTrackDeeplink(uri, onCallback);
}

Expand All @@ -418,8 +417,9 @@ public static void getAndTrackDeeplink(@NonNull String uri, @NonNull IterableHel
* handler activity
* @return whether or not the app link was handled
*/
public static boolean handleAppLink(@NonNull String uri) {
public boolean handleAppLink(@NonNull String uri) {
IterableLogger.printInfo();

if (IterableDeeplinkManager.isIterableDeeplink(uri)) {
IterableDeeplinkManager.getAndTrackDeeplink(uri, new IterableHelper.IterableActionHandler() {
@Override
Expand Down Expand Up @@ -880,7 +880,6 @@ void trackInAppClose(@NonNull String messageId, @NonNull String clickedURL, @Non
//---------------------------------------------------------------------------------------
//endregion


//region Package-Protected Functions
//---------------------------------------------------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public class IterableConfig {
*/
final long expiringAuthTokenRefreshPeriod;

/**
* By default, the SDK allows navigation/calls to URLs with the `https` protocol (e.g. deep links or external links)
* If you'd like to allow other protocols like `http`, `tel`, etc., add them to the `allowedProtocols` array
*/
final String[] allowedProtocols;

private IterableConfig(Builder builder) {
pushIntegrationName = builder.pushIntegrationName;
urlHandler = builder.urlHandler;
Expand All @@ -75,6 +81,7 @@ private IterableConfig(Builder builder) {
inAppDisplayInterval = builder.inAppDisplayInterval;
authHandler = builder.authHandler;
expiringAuthTokenRefreshPeriod = builder.expiringAuthTokenRefreshPeriod;
allowedProtocols = builder.allowedProtocols;
}

public static class Builder {
Expand All @@ -88,6 +95,7 @@ public static class Builder {
private double inAppDisplayInterval = 30.0;
private IterableAuthHandler authHandler;
private long expiringAuthTokenRefreshPeriod = 60000L;
private String[] allowedProtocols = new String[0];
public Builder() {}

/**
Expand Down Expand Up @@ -198,6 +206,16 @@ public Builder setExpiringAuthTokenRefreshPeriod(@NonNull Long period) {
return this;
}

/**
* Set what URLs the SDK should allow to open (in addition to `https`)
* @param allowedProtocols an array/list of protocols (e.g. `http`, `tel`)
*/
@NonNull
public Builder setAllowedProtocols(@NonNull String[] allowedProtocols) {
this.allowedProtocols = allowedProtocols;
return this;
}

@NonNull
public IterableConfig build() {
return new IterableConfig(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class IterableDeeplinkManager {
*/
static void getAndTrackDeeplink(@Nullable String url, @NonNull IterableHelper.IterableActionHandler callback) {
if (url != null) {
if (!IterableUtil.isUrlOpenAllowed(url)) {
return;
}
if (isIterableDeeplink(url)) {
new RedirectTask(callback).execute(url);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ public static IterableInAppFragmentHTMLNotification createInstance(@NonNull Stri
}

public static IterableInAppFragmentHTMLNotification createInstance(@NonNull String htmlString, boolean callbackOnCancel, @NonNull IterableHelper.IterableUrlCallback clickCallback, @NonNull IterableInAppLocation location, @NonNull String messageId, @NonNull Double backgroundAlpha, @NonNull Rect padding, @NonNull boolean shouldAnimate, IterableInAppMessage.InAppBgColor inAppBgColor) {

notification = new IterableInAppFragmentHTMLNotification();
Bundle args = new Bundle();
args.putString(HTML_STRING, htmlString);
Expand Down Expand Up @@ -163,7 +162,6 @@ public void onCancel(DialogInterface dialog) {
return dialog;
}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public interface Listener {
this.displayer = displayer;
this.activityMonitor = activityMonitor;
this.activityMonitor.addCallback(this);

syncInApp();
}

Expand Down Expand Up @@ -136,7 +137,6 @@ public synchronized void setRead(@NonNull IterableInAppMessage message, boolean
notifyOnChange();
}


boolean isAutoDisplayPaused() {
return autoDisplayPaused;
}
Expand Down Expand Up @@ -232,6 +232,7 @@ public void execute(Uri url) {
if (clickCallback != null) {
clickCallback.execute(url);
}

handleInAppClick(message, url);
lastInAppShown = IterableUtil.currentTimeMillis();
scheduleProcessing();
Expand Down Expand Up @@ -264,6 +265,7 @@ public synchronized void removeMessage(@NonNull IterableInAppMessage message, @N
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void handleInAppClick(@NonNull IterableInAppMessage message, @Nullable Uri url) {
IterableLogger.printInfo();

if (url != null && !url.toString().isEmpty()) {
String urlString = url.toString();
if (urlString.startsWith(IterableConstants.URL_SCHEME_ACTION)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public void createNotificationActionButton(Context context, IterableNotification
buttonIntent.putExtra(IterableConstants.ACTION_IDENTIFIER, button.identifier);

PendingIntent pendingButtonIntent = PendingIntent.getBroadcast(context, buttonIntent.hashCode(),
buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action
.Builder(NotificationCompat.BADGE_ICON_NONE, button.title, pendingButtonIntent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public IterableNotificationBuilder createNotification(Context context, Bundle ex
}

PendingIntent notificationClickedIntent = PendingIntent.getBroadcast(context, notificationBuilder.requestCode,
pushContentIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
pushContentIntent, PendingIntent.FLAG_UPDATE_CURRENT);

notificationBuilder.setContentIntent(notificationClickedIntent);
notificationBuilder.setIsGhostPush(isGhostPush(extras));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

Expand Down Expand Up @@ -277,4 +278,20 @@ boolean writeFile(File file, String content) {
return false;
}
}

static boolean isUrlOpenAllowed(@NonNull String url) {
String urlProtocol = url.split("://")[0];
if (urlProtocol.equals("https")) {
return true;
}

for (String allowedProtocol : IterableApi.getInstance().config.allowedProtocols) {
if (urlProtocol.equals(allowedProtocol)) {
return true;
}
}

IterableLogger.d(TAG, urlProtocol + " is not in the allowed protocols");
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@ public void testHandleUniversalLinkRewrite() throws Exception {
when(urlHandlerMock.handleIterableURL(any(Uri.class), any(IterableActionContext.class))).thenReturn(true);
IterableApi.initialize(getContext(), "fake_key", new IterableConfig.Builder().setUrlHandler(urlHandlerMock).build());

String url = "http://iterable.com";
IterableApi.handleAppLink(
"http://links.iterable.com/a/60402396fbd5433eb35397b47ab2fb83?_e=joneng%40iterable.com&_m=93125f33ba814b13a882358f8e0852e0");
String url = "https://iterable.com";
IterableApi.getInstance().handleAppLink(
"https://links.iterable.com/a/60402396fbd5433eb35397b47ab2fb83?_e=joneng%40iterable.com&_m=93125f33ba814b13a882358f8e0852e0");

ArgumentCaptor<Uri> capturedUri = ArgumentCaptor.forClass(Uri.class);
ArgumentCaptor<IterableActionContext> capturedActionContext = ArgumentCaptor.forClass(IterableActionContext.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"openApp": true,
"action": {
"type": "openUrl",
"data": "http://maps.apple.com/?ll=37.7828,-122.3984"
"data": "https://maps.apple.com/?ll=37.7828,-122.3984"
}
},
{
Expand Down

0 comments on commit 873708f

Please sign in to comment.