diff -r 000000000000 -r 6474c204b198 mobile/android/base/OrderedBroadcastHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/OrderedBroadcastHelper.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,129 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * 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; + +import org.mozilla.gecko.background.common.GlobalConstants; +import org.mozilla.gecko.EventDispatcher; +import org.mozilla.gecko.util.GeckoEventListener; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Activity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import android.util.Log; + +/** + * Helper class to send Android Ordered Broadcasts. + */ +public final class OrderedBroadcastHelper + implements GeckoEventListener +{ + public static final String LOGTAG = "GeckoOrdBroadcast"; + + public static final String SEND_EVENT = "OrderedBroadcast:Send"; + + protected final Context mContext; + + public OrderedBroadcastHelper(Context context) { + mContext = context; + + EventDispatcher dispatcher = GeckoAppShell.getEventDispatcher(); + if (dispatcher == null) { + Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException()); + return; + } + dispatcher.registerEventListener(SEND_EVENT, this); + } + + public synchronized void uninit() { + EventDispatcher dispatcher = GeckoAppShell.getEventDispatcher(); + if (dispatcher == null) { + Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException()); + return; + } + dispatcher.unregisterEventListener(SEND_EVENT, this); + } + + @Override + public void handleMessage(String event, JSONObject message) { + if (!SEND_EVENT.equals(event)) { + Log.e(LOGTAG, "OrderedBroadcastHelper got unexpected message " + event); + return; + } + + try { + final String action = message.getString("action"); + if (action == null) { + Log.e(LOGTAG, "action must not be null"); + return; + } + + final String responseEvent = message.getString("responseEvent"); + if (responseEvent == null) { + Log.e(LOGTAG, "responseEvent must not be null"); + return; + } + + // It's fine if the caller-provided token is missing or null. + final JSONObject token = (message.has("token") && !message.isNull("token")) ? + message.getJSONObject("token") : null; + + // A missing (undefined) permission means the intent will be limited + // to the current package. A null means no permission, so any + // package can receive the intent. + final String permission = message.has("permission") ? + (message.isNull("permission") ? null : message.getString("permission")) : + GlobalConstants.PER_ANDROID_PACKAGE_PERMISSION; + + final BroadcastReceiver resultReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + int code = getResultCode(); + + if (code == Activity.RESULT_OK) { + String data = getResultData(); + + JSONObject res = new JSONObject(); + try { + res.put("action", action); + res.put("token", token); + res.put("data", data); + } catch (JSONException e) { + Log.e(LOGTAG, "Got exception in onReceive handling action " + action, e); + return; + } + + GeckoEvent event = GeckoEvent.createBroadcastEvent(responseEvent, res.toString()); + GeckoAppShell.sendEventToGecko(event); + } + } + }; + + Intent intent = new Intent(action); + // OrderedBroadcast.jsm adds its callback ID to the caller's token; + // this unwraps that wrapping. + if (token != null && token.has("data")) { + intent.putExtra("token", token.getString("data")); + } + + mContext.sendOrderedBroadcast(intent, + permission, + resultReceiver, + null, + Activity.RESULT_OK, + null, + null); + } catch (JSONException e) { + Log.e(LOGTAG, "Got exception in handleMessage handling event " + event, e); + return; + } + } +}