Bug 1245692 - Pre: sanitise PromptInput setup r?mcomella
MozReview-Commit-ID: 8qe9JqrACfh
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/ColorPickerInput.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/ColorPickerInput.java
@@ -13,39 +13,39 @@ import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
public class ColorPickerInput extends PromptInput {
public static final String INPUT_TYPE = "color";
public static final String LOGTAG = "GeckoColorPickerInput";
- private final boolean mShowAdvancedButton = true;
private final int mInitialColor;
+ private final View mView;
- public ColorPickerInput(JSONObject obj) {
+ public ColorPickerInput(JSONObject obj, Context context) {
super(obj);
String init = obj.optString("value");
mInitialColor = Color.rgb(Integer.parseInt(init.substring(1, 3), 16),
Integer.parseInt(init.substring(3, 5), 16),
Integer.parseInt(init.substring(5, 7), 16));
- }
- @Override
- public View getView(Context context) throws UnsupportedOperationException {
LayoutInflater inflater = LayoutInflater.from(context);
mView = inflater.inflate(R.layout.basic_color_picker_dialog, null);
BasicColorPicker cp = (BasicColorPicker) mView.findViewById(R.id.colorpicker);
cp.setColor(mInitialColor);
+ }
+ @Override
+ public View getView() throws UnsupportedOperationException {
return mView;
}
- @Override
+@Override
public Object getValue() {
BasicColorPicker cp = (BasicColorPicker) mView.findViewById(R.id.colorpicker);
int color = cp.getColor();
return "#" + Integer.toHexString(color).substring(2);
}
@Override
public boolean getScrollable() {
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/IconGridInput.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/IconGridInput.java
@@ -37,23 +37,26 @@ public class IconGridInput extends Promp
private ArrayAdapter<IconGridItem> mAdapter; // An adapter holding a list of items to show in the grid
private static int mColumnWidth = -1; // The maximum width of columns
private static int mMaxColumns = -1; // The maximum number of columns to show
private static int mIconSize = -1; // Size of icons in the grid
private int mSelected; // Current selection
private final JSONArray mArray;
- public IconGridInput(JSONObject obj) {
+ private GridView mGrid;
+
+ public IconGridInput(JSONObject obj, Context context) {
super(obj);
mArray = obj.optJSONArray("items");
+
+ initView(context);
}
- @Override
- public View getView(Context context) throws UnsupportedOperationException {
+ private void initView(Context context) {
if (mColumnWidth < 0) {
// getColumnWidth isn't available on pre-ICS, so we pull it out and assign it here
mColumnWidth = context.getResources().getDimensionPixelSize(R.dimen.icongrid_columnwidth);
}
if (mIconSize < 0) {
mIconSize = GeckoAppShell.getPreferredIconSize();
}
@@ -63,41 +66,44 @@ public class IconGridInput extends Promp
}
// TODO: Dynamically handle size changes
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
final int screenWidth = display.getWidth();
int maxColumns = Math.min(mMaxColumns, screenWidth / mColumnWidth);
- final GridView view = (GridView) LayoutInflater.from(context).inflate(R.layout.icon_grid, null, false);
- view.setColumnWidth(mColumnWidth);
+ mGrid = (GridView) LayoutInflater.from(context).inflate(R.layout.icon_grid, null, false);
+ mGrid.setColumnWidth(mColumnWidth);
final ArrayList<IconGridItem> items = new ArrayList<IconGridItem>(mArray.length());
for (int i = 0; i < mArray.length(); i++) {
IconGridItem item = new IconGridItem(context, mArray.optJSONObject(i));
items.add(item);
if (item.selected) {
mSelected = i;
}
}
- view.setNumColumns(Math.min(items.size(), maxColumns));
- view.setOnItemClickListener(this);
+ mGrid.setNumColumns(Math.min(items.size(), maxColumns));
+ mGrid.setOnItemClickListener(this);
// Despite what the docs say, setItemChecked was not moved into the AbsListView class until sometime between
// Android 2.3.7 and Android 4.0.3. For other versions the item won't be visually highlighted, BUT we really only
// mSelected will still be set so that we default to its behavior.
if (Versions.feature11Plus && mSelected > -1) {
- view.setItemChecked(mSelected, true);
+ mGrid.setItemChecked(mSelected, true);
}
mAdapter = new IconGridAdapter(context, -1, items);
- view.setAdapter(mAdapter);
- mView = view;
- return mView;
+ mGrid.setAdapter(mAdapter);
+ }
+
+ @Override
+ public View getView() throws UnsupportedOperationException {
+ return mGrid;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mSelected = position;
notifyListeners(Integer.toString(position));
}
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/Prompt.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/Prompt.java
@@ -88,17 +88,17 @@ public class Prompt implements OnClickLi
final int buttonCount = mButtons == null ? 0 : mButtons.length;
mDoubleTapButtonType = convertIndexToButtonType(message.optInt("doubleTapButton", -1), buttonCount);
mPreviousInputValue = null;
JSONArray inputs = getSafeArray(message, "inputs");
mInputs = new PromptInput[inputs.length()];
for (int i = 0; i < mInputs.length; i++) {
try {
- mInputs[i] = PromptInput.getInput(inputs.getJSONObject(i));
+ mInputs[i] = PromptInput.getInput(inputs.getJSONObject(i), mContext);
mInputs[i].setListener(this);
} catch (Exception ex) { }
}
PromptListItem[] menuitems = PromptListItem.getArray(message.optJSONArray("listitems"));
String selected = message.optString("choiceMode");
int choiceMode = ListView.CHOICE_MODE_NONE;
@@ -381,17 +381,17 @@ public class Prompt implements OnClickLi
/* Wraps an input in a linearlayout. We do this so that we can set padding that appears outside the background
* drawable for the view.
*/
private View wrapInput(final PromptInput input) {
final LinearLayout linearLayout = new LinearLayout(mContext);
linearLayout.setOrientation(LinearLayout.VERTICAL);
applyInputStyle(linearLayout, input);
- linearLayout.addView(input.getView(mContext));
+ linearLayout.addView(input.getView());
return linearLayout;
}
/* Add the requested input elements to the dialog.
*
* @param builder
* the alert builder currently building this dialog.
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/PromptInput.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/PromptInput.java
@@ -38,200 +38,192 @@ import android.widget.TimePicker;
public abstract class PromptInput {
protected final String mLabel;
protected final String mType;
protected final String mId;
protected final String mValue;
protected final String mMinValue;
protected final String mMaxValue;
protected OnChangeListener mListener;
- protected View mView;
public static final String LOGTAG = "GeckoPromptInput";
public interface OnChangeListener {
void onChange(PromptInput input);
}
public void setListener(OnChangeListener listener) {
mListener = listener;
}
public static class EditInput extends PromptInput {
protected final String mHint;
protected final boolean mAutofocus;
+ protected TextInputLayout mInputLayout;
public static final String INPUT_TYPE = "textbox";
- public EditInput(JSONObject object) {
+ public EditInput(JSONObject object, final Context context) {
super(object);
mHint = object.optString("hint");
mAutofocus = object.optBoolean("autofocus");
- }
- @Override
- public View getView(final Context context) throws UnsupportedOperationException {
EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setText(mValue);
+ mInputLayout = new TextInputLayout(context);
+ mInputLayout.addView(input);
+
if (!TextUtils.isEmpty(mHint)) {
input.setHint(mHint);
}
if (mAutofocus) {
input.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(v, 0);
}
}
});
input.requestFocus();
}
+ }
- TextInputLayout inputLayout = new TextInputLayout(context);
- inputLayout.addView(input);
-
- mView = (View) inputLayout;
- return mView;
+ @Override
+ public View getView() throws UnsupportedOperationException {
+ return mInputLayout;
}
@Override
public Object getValue() {
- final TextInputLayout inputLayout = (TextInputLayout) mView;
- return inputLayout.getEditText().getText();
+ return mInputLayout.getEditText().getText();
}
}
public static class NumberInput extends EditInput {
public static final String INPUT_TYPE = "number";
- public NumberInput(JSONObject obj) {
- super(obj);
- }
+
+ public NumberInput(JSONObject obj, Context context) {
+ super(obj, context);
- @Override
- public View getView(final Context context) throws UnsupportedOperationException {
- final TextInputLayout inputLayout = (TextInputLayout) super.getView(context);
- final EditText input = inputLayout.getEditText();
- input.setRawInputType(Configuration.KEYBOARD_12KEY);
- input.setInputType(InputType.TYPE_CLASS_NUMBER |
- InputType.TYPE_NUMBER_FLAG_SIGNED);
- return input;
+ mInputLayout.getEditText().setRawInputType(Configuration.KEYBOARD_12KEY);
+ mInputLayout.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER |
+ InputType.TYPE_NUMBER_FLAG_SIGNED);
}
}
public static class PasswordInput extends EditInput {
public static final String INPUT_TYPE = "password";
- public PasswordInput(JSONObject obj) {
- super(obj);
- }
- @Override
- public View getView(Context context) throws UnsupportedOperationException {
- final TextInputLayout inputLayout = (TextInputLayout) super.getView(context);
- inputLayout.getEditText().setInputType(InputType.TYPE_CLASS_TEXT |
+ public PasswordInput(JSONObject obj, Context context) {
+ super(obj, context);
+
+ mInputLayout.getEditText().setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_VARIATION_PASSWORD |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
- return inputLayout;
}
}
public static class CheckboxInput extends PromptInput {
public static final String INPUT_TYPE = "checkbox";
- private final boolean mChecked;
+ private final CheckBox mCheckbox;
- public CheckboxInput(JSONObject obj) {
+ public CheckboxInput(JSONObject obj, Context context) {
super(obj);
- mChecked = obj.optBoolean("checked");
+ final boolean isChecked = obj.optBoolean("checked");
+
+ mCheckbox = new AppCompatCheckBox(context);
+ mCheckbox.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+ mCheckbox.setText(mLabel);
+ mCheckbox.setChecked(isChecked);
}
@Override
- public View getView(Context context) throws UnsupportedOperationException {
- final CheckBox checkbox = new AppCompatCheckBox(context);
- checkbox.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- checkbox.setText(mLabel);
- checkbox.setChecked(mChecked);
- mView = (View)checkbox;
- return mView;
+ public View getView(){
+ return mCheckbox;
}
@Override
public Object getValue() {
- CheckBox checkbox = (CheckBox)mView;
- return checkbox.isChecked() ? Boolean.TRUE : Boolean.FALSE;
+ return Boolean.valueOf(mCheckbox.isChecked());
}
}
public static class DateTimeInput extends PromptInput {
public static final String[] INPUT_TYPES = new String[] {
"date",
"week",
"time",
"datetime-local",
"datetime",
"month"
};
- public DateTimeInput(JSONObject obj) {
+ private View mView;
+
+ public DateTimeInput(JSONObject obj, Context context) {
super(obj);
- }
- @Override
- public View getView(Context context) throws UnsupportedOperationException {
if (mType.equals("date")) {
try {
DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd", mValue,
- DateTimePicker.PickersState.DATE, mMinValue, mMaxValue);
+ DateTimePicker.PickersState.DATE, mMinValue, mMaxValue);
input.toggleCalendar(true);
- mView = (View)input;
+ mView = (View) input;
} catch (UnsupportedOperationException ex) {
// We can't use our custom version of the DatePicker widget because the sdk is too old.
// But we can fallback on the native one.
DatePicker input = new DatePicker(context);
try {
if (!TextUtils.isEmpty(mValue)) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(mValue));
input.updateDate(calendar.get(Calendar.YEAR),
- calendar.get(Calendar.MONTH),
- calendar.get(Calendar.DAY_OF_MONTH));
+ calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH));
}
} catch (Exception e) {
Log.e(LOGTAG, "error parsing format string: " + e);
}
- mView = (View)input;
+ mView = (View) input;
}
} else if (mType.equals("week")) {
DateTimePicker input = new DateTimePicker(context, "yyyy-'W'ww", mValue,
- DateTimePicker.PickersState.WEEK, mMinValue, mMaxValue);
- mView = (View)input;
+ DateTimePicker.PickersState.WEEK, mMinValue, mMaxValue);
+ mView = (View) input;
} else if (mType.equals("time")) {
TimePicker input = new TimePicker(context);
input.setIs24HourView(DateFormat.is24HourFormat(context));
GregorianCalendar calendar = new GregorianCalendar();
if (!TextUtils.isEmpty(mValue)) {
try {
calendar.setTime(new SimpleDateFormat("HH:mm").parse(mValue));
- } catch (Exception e) { }
+ } catch (Exception e) {
+ }
}
input.setCurrentHour(calendar.get(GregorianCalendar.HOUR_OF_DAY));
input.setCurrentMinute(calendar.get(GregorianCalendar.MINUTE));
- mView = (View)input;
+ mView = input;
} else if (mType.equals("datetime-local") || mType.equals("datetime")) {
DateTimePicker input = new DateTimePicker(context, "yyyy-MM-dd HH:mm", mValue.replace("T", " ").replace("Z", ""),
- DateTimePicker.PickersState.DATETIME,
- mMinValue.replace("T", " ").replace("Z", ""), mMaxValue.replace("T", " ").replace("Z", ""));
+ DateTimePicker.PickersState.DATETIME,
+ mMinValue.replace("T", " ").replace("Z", ""), mMaxValue.replace("T", " ").replace("Z", ""));
input.toggleCalendar(true);
- mView = (View)input;
+ mView = (View) input;
} else if (mType.equals("month")) {
DateTimePicker input = new DateTimePicker(context, "yyyy-MM", mValue,
- DateTimePicker.PickersState.MONTH, mMinValue, mMaxValue);
- mView = (View)input;
+ DateTimePicker.PickersState.MONTH, mMinValue, mMaxValue);
+ mView = input;
}
+ }
+
+ @Override
+ public View getView() {
return mView;
}
private static String formatDateString(String dateFormat, Calendar calendar) {
return new SimpleDateFormat(dateFormat).format(calendar.getTime());
}
@Override
@@ -265,119 +257,125 @@ public abstract class PromptInput {
public static class MenulistInput extends PromptInput {
public static final String INPUT_TYPE = "menulist";
private static String[] mListitems;
private static int mSelected;
public Spinner spinner;
public AllCapsTextView textView;
+ private View mView;
- public MenulistInput(JSONObject obj) {
+ public MenulistInput(JSONObject obj, Context context) {
super(obj);
mListitems = Prompt.getStringArray(obj, "values");
mSelected = obj.optInt("selected");
- }
- @Override
- public View getView(final Context context) throws UnsupportedOperationException {
spinner = new Spinner(context, Spinner.MODE_DIALOG);
try {
if (mListitems.length > 0) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, mListitems);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setSelection(mSelected);
}
} catch (Exception ex) {
}
+ mView = spinner;
+
if (!TextUtils.isEmpty(mLabel)) {
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
textView = new AllCapsTextView(context, null);
textView.setText(mLabel);
container.addView(textView);
container.addView(spinner);
- return container;
+ mView = container;
}
+ }
- return spinner;
+ @Override
+ public View getView() throws UnsupportedOperationException {
+ return mView;
}
@Override
public Object getValue() {
return spinner.getSelectedItemPosition();
}
}
public static class LabelInput extends PromptInput {
public static final String INPUT_TYPE = "label";
- public LabelInput(JSONObject obj) {
+
+ private final TextView mText;
+
+ public LabelInput(JSONObject obj, final Context context) {
super(obj);
+
+ // not really an input, but a way to add labels and such to the dialog
+ mText = new TextView(context);
+ mText.setText(Html.fromHtml(mLabel));
}
@Override
- public View getView(Context context) throws UnsupportedOperationException {
- // not really an input, but a way to add labels and such to the dialog
- TextView view = new TextView(context);
- view.setText(Html.fromHtml(mLabel));
- mView = view;
- return mView;
+ public View getView() {
+ return mText;
}
}
public PromptInput(JSONObject obj) {
mLabel = obj.optString("label");
mType = obj.optString("type");
String id = obj.optString("id");
mId = TextUtils.isEmpty(id) ? mType : id;
mValue = obj.optString("value");
mMaxValue = obj.optString("max");
mMinValue = obj.optString("min");
}
- public static PromptInput getInput(JSONObject obj) {
+ public static PromptInput getInput(JSONObject obj, Context context) throws UnsupportedOperationException {
String type = obj.optString("type");
switch (type) {
case EditInput.INPUT_TYPE:
- return new EditInput(obj);
+ return new EditInput(obj, context);
case NumberInput.INPUT_TYPE:
- return new NumberInput(obj);
+ return new NumberInput(obj, context);
case PasswordInput.INPUT_TYPE:
- return new PasswordInput(obj);
+ return new PasswordInput(obj, context);
case CheckboxInput.INPUT_TYPE:
- return new CheckboxInput(obj);
+ return new CheckboxInput(obj, context);
case MenulistInput.INPUT_TYPE:
- return new MenulistInput(obj);
+ return new MenulistInput(obj, context);
case LabelInput.INPUT_TYPE:
- return new LabelInput(obj);
+ return new LabelInput(obj, context);
case IconGridInput.INPUT_TYPE:
- return new IconGridInput(obj);
+ return new IconGridInput(obj, context);
case ColorPickerInput.INPUT_TYPE:
- return new ColorPickerInput(obj);
+ return new ColorPickerInput(obj, context);
case TabInput.INPUT_TYPE:
- return new TabInput(obj);
+ return new TabInput(obj, context);
default:
for (String dtType : DateTimeInput.INPUT_TYPES) {
if (dtType.equals(type)) {
- return new DateTimeInput(obj);
+ return new DateTimeInput(obj, context);
}
}
break;
}
return null;
}
- public abstract View getView(Context context) throws UnsupportedOperationException;
+ public abstract View getView();
public String getId() {
return mId;
}
public Object getValue() {
return null;
}
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/TabInput.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/TabInput.java
@@ -28,34 +28,32 @@ public class TabInput extends PromptInpu
public static final String LOGTAG = "GeckoTabInput";
/* Keeping the order of this in sync with the JSON is important. */
final private LinkedHashMap<String, PromptListItem[]> mTabs;
private TabHost mHost;
private int mPosition;
- public TabInput(JSONObject obj) {
+ public TabInput(JSONObject obj, final Context context) {
super(obj);
mTabs = new LinkedHashMap<String, PromptListItem[]>();
try {
JSONArray tabs = obj.getJSONArray("items");
for (int i = 0; i < tabs.length(); i++) {
JSONObject tab = tabs.getJSONObject(i);
String title = tab.getString("label");
JSONArray items = tab.getJSONArray("items");
mTabs.put(title, PromptListItem.getArray(items));
}
} catch (JSONException ex) {
Log.e(LOGTAG, "Exception", ex);
}
- }
- @Override
- public View getView(final Context context) throws UnsupportedOperationException {
+
final LayoutInflater inflater = LayoutInflater.from(context);
mHost = (TabHost) inflater.inflate(R.layout.tab_prompt_input, null);
mHost.setup();
for (String title : mTabs.keySet()) {
final TabHost.TabSpec spec = mHost.newTabSpec(title);
spec.setContent(new TabHost.TabContentFactory() {
@Override
@@ -67,17 +65,20 @@ public class TabInput extends PromptInpu
listView.setAdapter(adapter);
return listView;
}
});
spec.setIndicator(title);
mHost.addTab(spec);
}
- mView = mHost;
+ }
+
+ @Override
+ public View getView() {
return mHost;
}
@Override
public Object getValue() {
JSONObject obj = new JSONObject();
try {
obj.put("tab", mHost.getCurrentTab());
--- a/mobile/android/base/java/org/mozilla/gecko/widget/DefaultDoorHanger.java
+++ b/mobile/android/base/java/org/mozilla/gecko/widget/DefaultDoorHanger.java
@@ -104,21 +104,21 @@ public class DefaultDoorHanger extends D
if (inputs != null) {
mInputs = new ArrayList<PromptInput>();
final ViewGroup group = (ViewGroup) findViewById(R.id.doorhanger_inputs);
group.setVisibility(VISIBLE);
for (int i = 0; i < inputs.length(); i++) {
try {
- PromptInput input = PromptInput.getInput(inputs.getJSONObject(i));
+ PromptInput input = PromptInput.getInput(inputs.getJSONObject(i), getContext());
mInputs.add(input);
final int padding = mResources.getDimensionPixelSize(R.dimen.doorhanger_section_padding_medium);
- View v = input.getView(getContext());
+ View v = input.getView();
styleInput(input, v);
v.setPadding(0, 0, 0, padding);
group.addView(v);
} catch (JSONException ex) { }
}
}
final String checkBoxText = options.optString("checkbox");