michael@0: /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.home; michael@0: michael@0: import java.util.ArrayList; michael@0: import java.util.List; michael@0: import java.util.Set; michael@0: import java.util.concurrent.atomic.AtomicInteger; michael@0: michael@0: import org.json.JSONArray; michael@0: import org.json.JSONException; michael@0: import org.json.JSONObject; michael@0: import org.mozilla.gecko.GeckoAppShell; michael@0: import org.mozilla.gecko.GeckoEvent; michael@0: import org.mozilla.gecko.home.HomeConfig.PanelConfig; michael@0: import org.mozilla.gecko.util.GeckoEventListener; michael@0: import org.mozilla.gecko.util.ThreadUtils; michael@0: michael@0: import android.util.Log; michael@0: import android.util.SparseArray; michael@0: michael@0: public class PanelInfoManager implements GeckoEventListener { michael@0: private static final String LOGTAG = "GeckoPanelInfoManager"; michael@0: michael@0: public class PanelInfo { michael@0: private final String mId; michael@0: private final String mTitle; michael@0: private final JSONObject mJSONData; michael@0: michael@0: public PanelInfo(String id, String title, JSONObject jsonData) { michael@0: mId = id; michael@0: mTitle = title; michael@0: mJSONData = jsonData; michael@0: } michael@0: michael@0: public String getId() { michael@0: return mId; michael@0: } michael@0: michael@0: public String getTitle() { michael@0: return mTitle; michael@0: } michael@0: michael@0: public PanelConfig toPanelConfig() { michael@0: try { michael@0: return new PanelConfig(mJSONData); michael@0: } catch (Exception e) { michael@0: Log.e(LOGTAG, "Failed to convert PanelInfo to PanelConfig", e); michael@0: return null; michael@0: } michael@0: } michael@0: } michael@0: michael@0: public interface RequestCallback { michael@0: public void onComplete(List panelInfos); michael@0: } michael@0: michael@0: private static AtomicInteger sRequestId = new AtomicInteger(0); michael@0: michael@0: // Stores set of pending request callbacks. michael@0: private static final SparseArray sCallbacks = new SparseArray(); michael@0: michael@0: /** michael@0: * Asynchronously fetches list of available panels from Gecko michael@0: * for the given IDs. michael@0: * michael@0: * @param ids list of panel ids to be fetched. A null value will fetch all michael@0: * available panels. michael@0: * @param callback onComplete will be called on the UI thread. michael@0: */ michael@0: public void requestPanelsById(Set ids, RequestCallback callback) { michael@0: final int requestId = sRequestId.getAndIncrement(); michael@0: michael@0: synchronized(sCallbacks) { michael@0: // If there are no pending callbacks, register the event listener. michael@0: if (sCallbacks.size() == 0) { michael@0: GeckoAppShell.getEventDispatcher().registerEventListener("HomePanels:Data", this); michael@0: } michael@0: sCallbacks.put(requestId, callback); michael@0: } michael@0: michael@0: final JSONObject message = new JSONObject(); michael@0: try { michael@0: message.put("requestId", requestId); michael@0: michael@0: if (ids != null && ids.size() > 0) { michael@0: JSONArray idsArray = new JSONArray(); michael@0: for (String id : ids) { michael@0: idsArray.put(id); michael@0: } michael@0: michael@0: message.put("ids", idsArray); michael@0: } michael@0: } catch (JSONException e) { michael@0: Log.e(LOGTAG, "Failed to build event to request panels by id", e); michael@0: return; michael@0: } michael@0: michael@0: GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("HomePanels:Get", message.toString())); michael@0: } michael@0: michael@0: /** michael@0: * Asynchronously fetches list of available panels from Gecko. michael@0: * michael@0: * @param callback onComplete will be called on the UI thread. michael@0: */ michael@0: public void requestAvailablePanels(RequestCallback callback) { michael@0: requestPanelsById(null, callback); michael@0: } michael@0: michael@0: /** michael@0: * Handles "HomePanels:Data" events. michael@0: */ michael@0: @Override michael@0: public void handleMessage(String event, JSONObject message) { michael@0: final ArrayList panelInfos = new ArrayList(); michael@0: michael@0: try { michael@0: final JSONArray panels = message.getJSONArray("panels"); michael@0: final int count = panels.length(); michael@0: for (int i = 0; i < count; i++) { michael@0: final PanelInfo panelInfo = getPanelInfoFromJSON(panels.getJSONObject(i)); michael@0: panelInfos.add(panelInfo); michael@0: } michael@0: michael@0: final RequestCallback callback; michael@0: final int requestId = message.getInt("requestId"); michael@0: michael@0: synchronized(sCallbacks) { michael@0: callback = sCallbacks.get(requestId); michael@0: sCallbacks.delete(requestId); michael@0: michael@0: // Unregister the event listener if there are no more pending callbacks. michael@0: if (sCallbacks.size() == 0) { michael@0: GeckoAppShell.getEventDispatcher().unregisterEventListener("HomePanels:Data", this); michael@0: } michael@0: } michael@0: michael@0: ThreadUtils.postToUiThread(new Runnable() { michael@0: @Override michael@0: public void run() { michael@0: callback.onComplete(panelInfos); michael@0: } michael@0: }); michael@0: } catch (JSONException e) { michael@0: Log.e(LOGTAG, "Exception handling " + event + " message", e); michael@0: } michael@0: } michael@0: michael@0: private PanelInfo getPanelInfoFromJSON(JSONObject jsonPanelInfo) throws JSONException { michael@0: final String id = jsonPanelInfo.getString("id"); michael@0: final String title = jsonPanelInfo.getString("title"); michael@0: michael@0: return new PanelInfo(id, title, jsonPanelInfo); michael@0: } michael@0: }