Bug 1319496 - 3. Convert prompts to BundleEventListener; r=sebastian

Convert prompts to use BundleEventListener and GeckoBundle.

DefaultDoorHanger.setOptions accepts a JSONObject argument, but if we
converted it to GeckoBundle, it would involve a lot of extra changes in
the other doorhanger code. So this patch adds GeckoBundle.fromJSONObject
and converts JSONObject to GeckoBundle within
DefaultDoorHanger.setOptions. In the future, another patch would convert
all doorhanger code to use GeckoBundle instead of JSONObject.
This commit is contained in:
Jim Chen 2016-11-29 12:25:53 -05:00
parent ba7b253f47
commit edb09e5551
11 changed files with 195 additions and 181 deletions

View File

@ -98,9 +98,11 @@ import org.mozilla.gecko.updater.PostUpdateHandler;
import org.mozilla.gecko.updater.UpdateServiceHelper;
import org.mozilla.gecko.util.ActivityUtils;
import org.mozilla.gecko.util.Clipboard;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.FloatUtils;
import org.mozilla.gecko.util.GamepadUtils;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.IntentUtils;
@ -200,7 +202,8 @@ public class BrowserApp extends GeckoApp
OnUrlOpenInBackgroundListener,
AnchoredPopup.OnVisibilityChangeListener,
ActionModeCompat.Presenter,
LayoutInflater.Factory {
LayoutInflater.Factory,
BundleEventListener {
private static final String LOGTAG = "GeckoBrowserApp";
private static final int TABS_ANIMATION_DURATION = 450;
@ -729,7 +732,6 @@ public class BrowserApp extends GeckoApp
"Menu:Update",
"LightweightTheme:Update",
"Search:Keyword",
"Prompt:ShowTop",
"Tab:Added",
"Video:Play");
@ -751,6 +753,8 @@ public class BrowserApp extends GeckoApp
"Updater:Launch",
"Website:Metadata");
getAppEventDispatcher().registerUiThreadListener(this, "Prompt:ShowTop");
final GeckoProfile profile = getProfile();
// We want to upload the telemetry core ping as soon after startup as possible. It relies on the
@ -1060,8 +1064,7 @@ public class BrowserApp extends GeckoApp
}
if (!mHasResumed) {
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
"Prompt:ShowTop");
getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
mHasResumed = true;
}
@ -1081,8 +1084,7 @@ public class BrowserApp extends GeckoApp
if (mHasResumed) {
// Register for Prompt:ShowTop so we can foreground this activity even if it's hidden.
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this,
"Prompt:ShowTop");
getAppEventDispatcher().registerUiThreadListener(this, "Prompt:ShowTop");
mHasResumed = false;
}
@ -1434,7 +1436,6 @@ public class BrowserApp extends GeckoApp
"Menu:Update",
"LightweightTheme:Update",
"Search:Keyword",
"Prompt:ShowTop",
"Tab:Added",
"Video:Play");
@ -1456,6 +1457,8 @@ public class BrowserApp extends GeckoApp
"Updater:Launch",
"Website:Metadata");
getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
if (AppConstants.MOZ_ANDROID_BEAM) {
NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
if (nfc != null) {
@ -1700,6 +1703,21 @@ public class BrowserApp extends GeckoApp
mBrowserToolbar.refresh();
}
@Override // BundleEventListener
public void handleMessage(final String event, final GeckoBundle message,
final EventCallback callback) {
switch (event) {
case "Prompt:ShowTop":
// Bring this activity to front so the prompt is visible..
Intent bringToFrontIntent = new Intent();
bringToFrontIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(bringToFrontIntent);
break;
}
}
@Override
public void handleMessage(final String event, final NativeJSObject message,
final EventCallback callback) {
@ -2111,14 +2129,6 @@ public class BrowserApp extends GeckoApp
}
break;
case "Prompt:ShowTop":
// Bring this activity to front so the prompt is visible..
Intent bringToFrontIntent = new Intent();
bringToFrontIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(bringToFrontIntent);
break;
case "Tab:Added":
if (message.getBoolean("cancelEditMode")) {
ThreadUtils.postToUiThread(new Runnable() {

View File

@ -5,8 +5,8 @@
package org.mozilla.gecko.prompts;
import org.json.JSONObject;
import org.mozilla.gecko.R;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.widget.BasicColorPicker;
import android.content.Context;
@ -21,9 +21,9 @@ public class ColorPickerInput extends PromptInput {
private final boolean mShowAdvancedButton = true;
private final int mInitialColor;
public ColorPickerInput(JSONObject obj) {
public ColorPickerInput(GeckoBundle obj) {
super(obj);
String init = obj.optString("value");
String init = obj.getString("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));

View File

@ -8,10 +8,9 @@ package org.mozilla.gecko.prompts;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ResourceDrawableUtils;
import android.content.Context;
@ -39,11 +38,12 @@ public class IconGridInput extends PromptInput implements OnItemClickListener {
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;
private final GeckoBundle[] mArray;
public IconGridInput(JSONObject obj) {
public IconGridInput(GeckoBundle obj) {
super(obj);
mArray = obj.optJSONArray("items");
final GeckoBundle[] array = obj.getBundleArray("items");
mArray = array != null ? array : new GeckoBundle[0];
}
@Override
@ -70,9 +70,9 @@ public class IconGridInput extends PromptInput implements OnItemClickListener {
final GridView view = (GridView) LayoutInflater.from(context).inflate(R.layout.icon_grid, null, false);
view.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));
final ArrayList<IconGridItem> items = new ArrayList<IconGridItem>(mArray.length);
for (int i = 0; i < mArray.length; i++) {
IconGridItem item = new IconGridItem(context, mArray[i]);
items.add(item);
if (item.selected) {
mSelected = i;
@ -151,11 +151,11 @@ public class IconGridInput extends PromptInput implements OnItemClickListener {
final boolean selected;
Drawable icon;
public IconGridItem(final Context context, final JSONObject obj) {
label = obj.optString("name");
final String iconUrl = obj.optString("iconUri");
description = obj.optString("description");
selected = obj.optBoolean("selected");
public IconGridItem(final Context context, final GeckoBundle obj) {
label = obj.getString("name");
final String iconUrl = obj.getString("iconUri");
description = obj.getString("description");
selected = obj.getBoolean("selected");
ResourceDrawableUtils.getDrawable(context, iconUrl, new ResourceDrawableUtils.BitmapLoader() {
@Override

View File

@ -11,6 +11,7 @@ import org.json.JSONObject;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
@ -78,27 +79,25 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
return view;
}
public void show(JSONObject message) {
String title = message.optString("title");
String text = message.optString("text");
mGuid = message.optString("guid");
public void show(GeckoBundle message) {
String title = message.getString("title");
String text = message.getString("text");
mGuid = message.getString("guid");
mButtons = getStringArray(message, "buttons");
mButtons = message.getStringArray("buttons");
final int buttonCount = mButtons == null ? 0 : mButtons.length;
mDoubleTapButtonType = convertIndexToButtonType(message.optInt("doubleTapButton", -1), buttonCount);
mDoubleTapButtonType = convertIndexToButtonType(message.getInt("doubleTapButton", -1), buttonCount);
mPreviousInputValue = null;
JSONArray inputs = getSafeArray(message, "inputs");
mInputs = new PromptInput[inputs.length()];
GeckoBundle[] inputs = message.getBundleArray("inputs");
mInputs = new PromptInput[inputs != null ? inputs.length : 0];
for (int i = 0; i < mInputs.length; i++) {
try {
mInputs[i] = PromptInput.getInput(inputs.getJSONObject(i));
mInputs[i].setListener(this);
} catch (Exception ex) { }
mInputs[i] = PromptInput.getInput(inputs[i]);
mInputs[i].setListener(this);
}
PromptListItem[] menuitems = PromptListItem.getArray(message.optJSONArray("listitems"));
String selected = message.optString("choiceMode");
PromptListItem[] menuitems = PromptListItem.getArray(message.getBundleArray("listitems"));
String selected = message.getString("choiceMode");
int choiceMode = ListView.CHOICE_MODE_NONE;
if ("single".equals(selected)) {
@ -107,9 +106,7 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
choiceMode = ListView.CHOICE_MODE_MULTIPLE;
}
if (message.has("tabId")) {
mTabId = message.optInt("tabId", Tabs.INVALID_TAB_ID);
}
mTabId = message.getInt("tabId", Tabs.INVALID_TAB_ID);
show(title, text, menuitems, choiceMode);
}
@ -540,41 +537,6 @@ public class Prompt implements OnClickListener, OnCancelListener, OnItemClickLis
return false;
}
private static JSONArray getSafeArray(JSONObject json, String key) {
try {
return json.getJSONArray(key);
} catch (Exception e) {
return new JSONArray();
}
}
public static String[] getStringArray(JSONObject aObject, String aName) {
JSONArray items = getSafeArray(aObject, aName);
int length = items.length();
String[] list = new String[length];
for (int i = 0; i < length; i++) {
try {
list[i] = items.getString(i);
} catch (Exception ex) { }
}
return list;
}
private static boolean[] getBooleanArray(JSONObject aObject, String aName) {
JSONArray items = new JSONArray();
try {
items = aObject.getJSONArray(aName);
} catch (Exception ex) { return null; }
int length = items.length();
boolean[] list = new boolean[length];
for (int i = 0; i < length; i++) {
try {
list[i] = items.getBoolean(i);
} catch (Exception ex) { }
}
return list;
}
public interface PromptCallback {
/**

View File

@ -9,8 +9,8 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.widget.AllCapsTextView;
import org.mozilla.gecko.widget.DateTimePicker;
@ -59,10 +59,10 @@ public abstract class PromptInput {
protected final boolean mAutofocus;
public static final String INPUT_TYPE = "textbox";
public EditInput(JSONObject object) {
public EditInput(GeckoBundle object) {
super(object);
mHint = object.optString("hint");
mAutofocus = object.optBoolean("autofocus");
mHint = object.getString("hint");
mAutofocus = object.getBoolean("autofocus");
}
@Override
@ -103,7 +103,7 @@ public abstract class PromptInput {
public static class NumberInput extends EditInput {
public static final String INPUT_TYPE = "number";
public NumberInput(JSONObject obj) {
public NumberInput(GeckoBundle obj) {
super(obj);
}
@ -120,7 +120,7 @@ public abstract class PromptInput {
public static class PasswordInput extends EditInput {
public static final String INPUT_TYPE = "password";
public PasswordInput(JSONObject obj) {
public PasswordInput(GeckoBundle obj) {
super(obj);
}
@ -138,9 +138,9 @@ public abstract class PromptInput {
public static final String INPUT_TYPE = "checkbox";
private final boolean mChecked;
public CheckboxInput(JSONObject obj) {
public CheckboxInput(GeckoBundle obj) {
super(obj);
mChecked = obj.optBoolean("checked");
mChecked = obj.getBoolean("checked");
}
@Override
@ -170,7 +170,7 @@ public abstract class PromptInput {
"month"
};
public DateTimeInput(JSONObject obj) {
public DateTimeInput(GeckoBundle obj) {
super(obj);
}
@ -265,16 +265,17 @@ 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;
private final String[] mListitems;
private final int mSelected;
public Spinner spinner;
public AllCapsTextView textView;
public MenulistInput(JSONObject obj) {
public MenulistInput(GeckoBundle obj) {
super(obj);
mListitems = Prompt.getStringArray(obj, "values");
mSelected = obj.optInt("selected");
final String[] listitems = obj.getStringArray("values");
mListitems = listitems != null ? listitems : new String[0];
mSelected = obj.getInt("selected");
}
@Override
@ -314,7 +315,7 @@ public abstract class PromptInput {
public static class LabelInput extends PromptInput {
public static final String INPUT_TYPE = "label";
public LabelInput(JSONObject obj) {
public LabelInput(GeckoBundle obj) {
super(obj);
}
@ -328,18 +329,18 @@ public abstract class PromptInput {
}
}
public PromptInput(JSONObject obj) {
mLabel = obj.optString("label");
mType = obj.optString("type");
String id = obj.optString("id");
public PromptInput(GeckoBundle obj) {
mLabel = obj.getString("label");
mType = obj.getString("type");
String id = obj.getString("id");
mId = TextUtils.isEmpty(id) ? mType : id;
mValue = obj.optString("value");
mMaxValue = obj.optString("max");
mMinValue = obj.optString("min");
mValue = obj.getString("value");
mMaxValue = obj.getString("max");
mMinValue = obj.getString("min");
}
public static PromptInput getInput(JSONObject obj) {
String type = obj.optString("type");
public static PromptInput getInput(GeckoBundle obj) {
String type = obj.getString("type");
switch (type) {
case EditInput.INPUT_TYPE:
return new EditInput(obj);

View File

@ -1,15 +1,12 @@
package org.mozilla.gecko.prompts;
import org.json.JSONException;
import org.mozilla.gecko.IntentHelper;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.ThumbnailHelper;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.widget.GeckoActionProvider;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@ -32,32 +29,32 @@ public class PromptListItem {
public boolean mSelected;
public Drawable mIcon;
PromptListItem(JSONObject aObject) {
PromptListItem(GeckoBundle aObject) {
Context context = GeckoAppShell.getContext();
label = aObject.isNull("label") ? "" : aObject.optString("label");
isGroup = aObject.optBoolean("isGroup");
inGroup = aObject.optBoolean("inGroup");
disabled = aObject.optBoolean("disabled");
id = aObject.optInt("id");
mSelected = aObject.optBoolean("selected");
label = aObject.getString("label", "");
isGroup = aObject.getBoolean("isGroup");
inGroup = aObject.getBoolean("inGroup");
disabled = aObject.getBoolean("disabled");
id = aObject.getInt("id");
mSelected = aObject.getBoolean("selected");
JSONObject obj = aObject.optJSONObject("showAsActions");
GeckoBundle obj = aObject.getBundle("showAsActions");
if (obj != null) {
showAsActions = true;
String uri = obj.isNull("uri") ? "" : obj.optString("uri");
String type = obj.isNull("type") ? GeckoActionProvider.DEFAULT_MIME_TYPE :
obj.optString("type", GeckoActionProvider.DEFAULT_MIME_TYPE);
String uri = obj.getString("uri", "");
String type = obj.getString("type", GeckoActionProvider.DEFAULT_MIME_TYPE);
mIntent = IntentHelper.getShareIntent(context, uri, type, "");
isParent = true;
} else {
mIntent = null;
showAsActions = false;
// Support both "isParent" (backwards compat for older consumers), and "menu" for the new Tabbed prompt ui.
isParent = aObject.optBoolean("isParent") || aObject.optBoolean("menu");
// Support both "isParent" (backwards compat for older consumers), and "menu"
// for the new Tabbed prompt ui.
isParent = aObject.getBoolean("isParent") || aObject.getBoolean("menu");
}
final String iconStr = aObject.optString("icon");
final String iconStr = aObject.getString("icon");
if (iconStr != null) {
final ResourceDrawableUtils.BitmapLoader loader = new ResourceDrawableUtils.BitmapLoader() {
@Override
@ -109,18 +106,16 @@ public class PromptListItem {
showAsActions = false;
}
static PromptListItem[] getArray(JSONArray items) {
static PromptListItem[] getArray(GeckoBundle[] items) {
if (items == null) {
return new PromptListItem[0];
}
int length = items.length();
int length = items.length;
List<PromptListItem> list = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
try {
PromptListItem item = new PromptListItem(items.getJSONObject(i));
list.add(item);
} catch (JSONException ex) { }
PromptListItem item = new PromptListItem(items[i]);
list.add(item);
}
return list.toArray(new PromptListItem[length]);

View File

@ -5,68 +5,46 @@
package org.mozilla.gecko.prompts;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.Context;
import android.util.Log;
public class PromptService implements GeckoEventListener {
public class PromptService implements BundleEventListener {
private static final String LOGTAG = "GeckoPromptService";
private final Context mContext;
public PromptService(Context context) {
GeckoApp.getEventDispatcher().registerGeckoThreadListener(this,
GeckoApp.getEventDispatcher().registerUiThreadListener(this,
"Prompt:Show",
"Prompt:ShowTop");
mContext = context;
}
public void destroy() {
GeckoApp.getEventDispatcher().unregisterGeckoThreadListener(this,
GeckoApp.getEventDispatcher().unregisterUiThreadListener(this,
"Prompt:Show",
"Prompt:ShowTop");
}
public void show(final String aTitle, final String aText, final PromptListItem[] aMenuList,
final int aChoiceMode, final Prompt.PromptCallback callback) {
// The dialog must be created on the UI thread.
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
Prompt p;
p = new Prompt(mContext, callback);
p.show(aTitle, aText, aMenuList, aChoiceMode);
}
});
}
// GeckoEventListener implementation
// BundleEventListener implementation
@Override
public void handleMessage(String event, final JSONObject message) {
// The dialog must be created on the UI thread.
ThreadUtils.postToUiThread(new Runnable() {
public void handleMessage(final String event, final GeckoBundle message,
final EventCallback callback) {
Prompt p;
p = new Prompt(mContext, new Prompt.PromptCallback() {
@Override
public void run() {
Prompt p;
p = new Prompt(mContext, new Prompt.PromptCallback() {
@Override
public void onPromptFinished(String jsonResult) {
try {
EventDispatcher.sendResponse(message, new JSONObject(jsonResult));
} catch (JSONException ex) {
Log.i(LOGTAG, "Error building json response", ex);
}
}
});
p.show(message);
public void onPromptFinished(String jsonResult) {
callback.sendSuccess(jsonResult);
}
});
p.show(message);
}
}

View File

@ -12,6 +12,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.R;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.Context;
@ -33,19 +34,15 @@ public class TabInput extends PromptInput implements AdapterView.OnItemClickList
private TabHost mHost;
private int mPosition;
public TabInput(JSONObject obj) {
public TabInput(GeckoBundle obj) {
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);
GeckoBundle[] tabs = obj.getBundleArray("items");
for (int i = 0; i < (tabs != null ? tabs.length : 0); i++) {
GeckoBundle tab = tabs[i];
String title = tab.getString("label");
GeckoBundle[] items = tab.getBundleArray("items");
mTabs.put(title, PromptListItem.getArray(items));
}
}

View File

@ -15,6 +15,7 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.prompts.PromptInput;
import org.mozilla.gecko.util.GeckoBundle;
import org.json.JSONArray;
import org.json.JSONException;
@ -109,7 +110,8 @@ public class DefaultDoorHanger extends DoorHanger {
for (int i = 0; i < inputs.length(); i++) {
try {
PromptInput input = PromptInput.getInput(inputs.getJSONObject(i));
PromptInput input = PromptInput.getInput(
GeckoBundle.fromJSONObject(inputs.getJSONObject(i)));
mInputs.add(input);
final int padding = mResources.getDimensionPixelSize(R.dimen.doorhanger_section_padding_medium);

View File

@ -8,10 +8,15 @@ package org.mozilla.gecko.util;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.support.v4.util.SimpleArrayMap;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
/**
@ -618,4 +623,68 @@ public final class GeckoBundle {
public int size() {
return mMap.size();
}
private static Object fromJSONValue(Object value) throws JSONException {
if (value instanceof JSONObject || value == JSONObject.NULL) {
return fromJSONObject((JSONObject) value);
}
if (value instanceof JSONArray) {
final JSONArray array = (JSONArray) value;
final int len = array.length();
if (len == 0) {
return EMPTY_BOOLEAN_ARRAY;
}
Object out = null;
for (int i = 0; i < len; i++) {
final Object element = fromJSONValue(array.opt(0));
if (element == null) {
continue;
}
if (out == null) {
Class<?> type = element.getClass();
if (type == Boolean.class) {
type = boolean.class;
} else if (type == Integer.class) {
type = int.class;
} else if (type == Double.class) {
type = double.class;
}
out = Array.newInstance(type, len);
}
Array.set(out, i, element);
}
if (out == null) {
// Treat all-null arrays as String arrays.
return new String[len];
}
return out;
}
if (value instanceof Boolean) {
return value;
}
if (value instanceof Byte || value instanceof Short || value instanceof Integer) {
return ((Number) value).intValue();
}
if (value instanceof Float || value instanceof Double || value instanceof Long) {
return ((Number) value).doubleValue();
}
return value != null ? value.toString() : null;
}
public static GeckoBundle fromJSONObject(final JSONObject obj) throws JSONException {
if (obj == null || obj == JSONObject.NULL) {
return null;
}
final String[] keys = new String[obj.length()];
final Object[] values = new String[obj.length()];
final Iterator<String> iter = obj.keys();
for (int i = 0; iter.hasNext(); i++) {
final String key = iter.next();
keys[i] = key;
values[i] = fromJSONValue(obj.opt(key));
}
return new GeckoBundle(keys, values);
}
}

View File

@ -8,7 +8,6 @@ var Cc = Components.classes;
var Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Messaging.jsm");
this.EXPORTED_SYMBOLS = ["Prompt"];
@ -176,7 +175,8 @@ Prompt.prototype = {
},
_innerShow: function() {
Messaging.sendRequestForResult(this.msg).then((data) => {
let window = Services.wm.getMostRecentWindow("navigator:browser");
window.WindowEventDispatcher.sendRequestForResult(this.msg).then((data) => {
if (this.callback)
this.callback(data);
});