/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko.util; import android.content.Intent; import android.os.Bundle; import android.support.annotation.CheckResult; import android.support.annotation.NonNull; import android.text.TextUtils; import org.mozilla.gecko.mozglue.SafeIntent; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Utilities for Intents. */ public class IntentUtils { public static final String ENV_VAR_IN_AUTOMATION = "MOZ_IN_AUTOMATION"; private static final String ENV_VAR_REGEX = "(.+)=(.*)"; private IntentUtils() {} /** * Returns a list of environment variables and their values. These are parsed from an Intent extra * with the key -> value format: * env# -> ENV_VAR=VALUE * * # in env# is expected to be increasing from 0. * * @return A Map of environment variable name to value, e.g. ENV_VAR -> VALUE */ public static HashMap getEnvVarMap(@NonNull final SafeIntent intent) { // Optimization: get matcher for re-use. Pattern.matcher creates a new object every time so it'd be great // to avoid the unnecessary allocation, particularly because we expect to be called on the startup path. final Pattern envVarPattern = Pattern.compile(ENV_VAR_REGEX); final Matcher matcher = envVarPattern.matcher(""); // argument does not matter here. // This is expected to be an external intent so we should use SafeIntent to prevent crashing. final HashMap out = new HashMap<>(); int i = 0; while (true) { final String envKey = "env" + i; i += 1; if (!intent.hasExtra(envKey)) { break; } maybeAddEnvVarToEnvVarMap(out, intent, envKey, matcher); } return out; } /** * @param envVarMap the map to add the env var to * @param intent the intent from which to extract the env var * @param envKey the key at which the env var resides * @param envVarMatcher a matcher initialized with the env var pattern to extract */ private static void maybeAddEnvVarToEnvVarMap(@NonNull final HashMap envVarMap, @NonNull final SafeIntent intent, @NonNull final String envKey, @NonNull final Matcher envVarMatcher) { final String envValue = intent.getStringExtra(envKey); if (envValue == null) { return; // nothing to do here! } envVarMatcher.reset(envValue); if (envVarMatcher.matches()) { final String envVarName = envVarMatcher.group(1); final String envVarValue = envVarMatcher.group(2); envVarMap.put(envVarName, envVarValue); } } public static Bundle getBundleExtraSafe(final Intent intent, final String name) { return new SafeIntent(intent).getBundleExtra(name); } public static String getStringExtraSafe(final Intent intent, final String name) { return new SafeIntent(intent).getStringExtra(name); } public static boolean getBooleanExtraSafe(final Intent intent, final String name, final boolean defaultValue) { return new SafeIntent(intent).getBooleanExtra(name, defaultValue); } /** * Gets whether or not we're in automation from the passed in environment variables. * * We need to read environment variables from the intent string * extra because environment variables from our test harness aren't set * until Gecko is loaded, and we need to know this before then. * * The return value of this method should be used early since other * initialization may depend on its results. */ @CheckResult public static boolean getIsInAutomationFromEnvironment(final SafeIntent intent) { final HashMap envVars = IntentUtils.getEnvVarMap(intent); return !TextUtils.isEmpty(envVars.get(IntentUtils.ENV_VAR_IN_AUTOMATION)); } }