package com.sensorberg.sdk.action; import android.net.Uri; import android.webkit.URLUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.sensorberg.sdk.Logger; import com.sensorberg.sdk.model.ISO8601TypeAdapter; import org.json.JSONException; import java.util.Date; import java.util.UUID; public class ActionFactory { private static Gson gson; public interface ServerType { int URL_MESSAGE = 1; int VISIT_WEBSITE = 2; int IN_APP = 3; int SILENT = 4; } private static final String SUBJECT = "subject"; private static final String BODY = "body"; private static final String URL = "url"; private static final String PAYLOAD = "payload"; public static Action getAction(int actionType, JsonObject message, UUID actionUUID, long delay) throws JSONException { String instanceUuid = UUID.randomUUID().toString(); if (actionType == ServerType.SILENT){ return new SilentAction(actionUUID, instanceUuid); } if (message == null) { return null; } Action value = null; String payload = null; JsonElement payloadElement = message.get(PAYLOAD); if (payloadElement != null && !payloadElement.isJsonNull()) { if (payloadElement.isJsonArray() || payloadElement.isJsonObject()) { payload = getGson().toJson(message.get(PAYLOAD)); } else { payload = payloadElement.getAsString(); } } JsonElement subjectJsonElement = message.get(SUBJECT); String subject = subjectJsonElement == null || subjectJsonElement.isJsonNull() ? null : subjectJsonElement.getAsString(); JsonElement bodyJsonElement = message.get(BODY); String body = bodyJsonElement == null || bodyJsonElement.isJsonNull() ? null : bodyJsonElement.getAsString(); String url = getUriFromJson(message.get(URL), actionType); switch (actionType) { case ServerType.URL_MESSAGE: { value = new UriMessageAction( actionUUID, subject, body, url, payload, delay, instanceUuid ); break; } case ServerType.VISIT_WEBSITE: { value = new VisitWebsiteAction( actionUUID, subject, body, Uri.parse(url), payload, delay, instanceUuid ); break; } case ServerType.IN_APP: { value = new InAppAction( actionUUID, subject, body, payload, Uri.parse(url), delay, instanceUuid ); break; } } return value; } private static Gson getGson() { //TODO see how to inject this statically with dagger! if (gson == null) { gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .registerTypeAdapter(Date.class, ISO8601TypeAdapter.DATE_ADAPTER) .setLenient() .create(); } return gson; } /** * Gets URL parameter from JSON and validates it. * * @param jsonElement - JsonElement that contains the url string. * @param messageType - Message type. * @return - Returns the verified URI string. If not valid or empty will return an empty string. */ public static String getUriFromJson(JsonElement jsonElement, int messageType) { String urlToCheck = jsonElement == null || jsonElement.isJsonNull() ? "" : jsonElement.getAsString(); String returnUrl = ""; //we allow deep links for in app actions and URL messages; we enforce valid network URLs // for the visit website action if ((messageType == ServerType.IN_APP && validatedUrl(urlToCheck)) || (messageType == ServerType.URL_MESSAGE && validatedUrl(urlToCheck)) || URLUtil.isNetworkUrl(urlToCheck)) { returnUrl = urlToCheck; } if (returnUrl.isEmpty()) { Logger.log.logError("URL is invalid, please change in the campaign settings."); } return returnUrl; } //this allows for deep links, we just check for URL syntax conformity public static boolean validatedUrl(String urlToCheck) { Uri uri; try { uri = Uri.parse(urlToCheck); } catch (Exception e) { uri = Uri.parse(""); } return uri.getScheme() != null || uri.getPath() != null; } }