diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index 339ed5d396b1..2667ca2d49e0 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -8,14 +8,12 @@ package org.mozilla.gecko; import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.content.res.Configuration; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; @@ -53,12 +51,11 @@ public class GeckoPreferences protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); - registerEventListener("Preferences:Data"); registerEventListener("Sanitize:Finished"); - } + } - @Override - public void onWindowFocusChanged(boolean hasFocus) { + @Override + public void onWindowFocusChanged(boolean hasFocus) { if (!hasFocus) return; @@ -71,16 +68,12 @@ public class GeckoPreferences @Override protected void onDestroy() { super.onDestroy(); - unregisterEventListener("Preferences:Data"); unregisterEventListener("Sanitize:Finished"); } public void handleMessage(String event, JSONObject message) { try { - if (event.equals("Preferences:Data")) { - JSONArray jsonPrefs = message.getJSONArray("preferences"); - refresh(jsonPrefs); - } else if (event.equals("Sanitize:Finished")) { + if (event.equals("Sanitize:Finished")) { boolean success = message.getBoolean("success"); final int stringRes = success ? R.string.private_data_success : R.string.private_data_fail; final Context context = this; @@ -95,14 +88,6 @@ public class GeckoPreferences } } - // Initialize preferences by sending the "Preferences:Get" command to Gecko - private void initValues() { - JSONArray jsonPrefs = new JSONArray(mPreferencesList); - - GeckoEvent event = GeckoEvent.createBroadcastEvent("Preferences:Get", jsonPrefs.toString()); - GeckoAppShell.sendEventToGecko(event); - } - private void initGroups(PreferenceGroup preferences) { final int count = preferences.getPreferenceCount(); for (int i = 0; i < count; i++) { @@ -158,7 +143,9 @@ public class GeckoPreferences setCharEncodingState(((String) newValue).equals("true")); } - setPreference(prefName, newValue); + if (!TextUtils.isEmpty(prefName)) { + PrefsHelper.setPref(prefName, newValue); + } if (preference instanceof ListPreference) { // We need to find the entry for the new value int newIndex = ((ListPreference)preference).findIndexOfValue((String) newValue); @@ -266,18 +253,7 @@ public class GeckoPreferences .setView((View)linearLayout) .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { - try { - JSONObject jsonPref = new JSONObject(); - jsonPref.put("name", "privacy.masterpassword.enabled"); - jsonPref.put("type", "string"); - jsonPref.put("value", input.getText().toString()); - - GeckoEvent event = GeckoEvent.createBroadcastEvent("Preferences:Set", jsonPref.toString()); - GeckoAppShell.sendEventToGecko(event); - } catch(Exception ex) { - Log.e(LOGTAG, "Error setting masterpassword", ex); - } - return; + PrefsHelper.setPref("privacy.masterpassword.enabled", input.getText().toString()); } }) .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { @@ -299,42 +275,35 @@ public class GeckoPreferences return dialog; } - private void refresh(JSONArray jsonPrefs) { - // enable all preferences once we have them from gecko - GeckoAppShell.getMainHandler().post(new Runnable() { - public void run() { - mPreferenceScreen.setEnabled(true); + // Initialize preferences by requesting the preference values from Gecko + private void initValues() { + JSONArray jsonPrefs = new JSONArray(mPreferencesList); + PrefsHelper.getPrefs(jsonPrefs, new PrefsHelper.PrefHandlerBase() { + private Preference getField(String prefName) { + return (mPreferenceScreen == null ? null : mPreferenceScreen.findPreference(prefName)); } - }); - try { - if (mPreferenceScreen == null) - return; - - final int length = jsonPrefs.length(); - for (int i = 0; i < length; i++) { - JSONObject jPref = jsonPrefs.getJSONObject(i); - final String prefName = jPref.getString("name"); - final String prefType = jPref.getString("type"); - final Preference pref = mPreferenceScreen.findPreference(prefName); - - if (pref instanceof CheckBoxPreference && "bool".equals(prefType)) { - final boolean value = jPref.getBoolean("value"); + @Override public void prefValue(String prefName, final boolean value) { + final Preference pref = getField(prefName); + if (pref instanceof CheckBoxPreference) { GeckoAppShell.getMainHandler().post(new Runnable() { public void run() { if (((CheckBoxPreference)pref).isChecked() != value) ((CheckBoxPreference)pref).setChecked(value); } }); - } else if (pref instanceof EditTextPreference && "string".equals(prefType)) { - final String value = jPref.getString("value"); + } + } + + @Override public void prefValue(String prefName, final String value) { + final Preference pref = getField(prefName); + if (pref instanceof EditTextPreference) { GeckoAppShell.getMainHandler().post(new Runnable() { public void run() { ((EditTextPreference)pref).setText(value); } }); - } else if (pref instanceof ListPreference && "string".equals(prefType)) { - final String value = jPref.getString("value"); + } else if (pref instanceof ListPreference) { GeckoAppShell.getMainHandler().post(new Runnable() { public void run() { ((ListPreference)pref).setValue(value); @@ -345,8 +314,7 @@ public class GeckoPreferences }); } else if (pref instanceof FontSizePreference) { final FontSizePreference fontSizePref = (FontSizePreference) pref; - final String twipValue = jPref.getString("value"); - fontSizePref.setSavedFontSize(twipValue); + fontSizePref.setSavedFontSize(value); final String fontSizeName = fontSizePref.getSavedFontSizeName(); GeckoAppShell.getMainHandler().post(new Runnable() { public void run() { @@ -354,39 +322,17 @@ public class GeckoPreferences } }); } - - } - } catch (JSONException e) { - Log.e(LOGTAG, "Problem parsing preferences response: ", e); - } - } - - // send the Preferences:Set message to Gecko - public static void setPreference(String pref, Object value) { - if (pref == null || pref.length() == 0) - return; - - try { - JSONObject jsonPref = new JSONObject(); - jsonPref.put("name", pref); - if (value instanceof Boolean) { - jsonPref.put("type", "bool"); - jsonPref.put("value", ((Boolean)value).booleanValue()); - } - else if (value instanceof Integer) { - jsonPref.put("type", "int"); - jsonPref.put("value", ((Integer)value).intValue()); - } - else { - jsonPref.put("type", "string"); - jsonPref.put("value", String.valueOf(value)); } - GeckoEvent event = GeckoEvent.createBroadcastEvent("Preferences:Set", jsonPref.toString()); - GeckoAppShell.sendEventToGecko(event); - } catch (JSONException e) { - Log.e(LOGTAG, "JSON exception: ", e); - } + @Override public void finish() { + // enable all preferences once we have them from gecko + GeckoAppShell.getMainHandler().post(new Runnable() { + public void run() { + mPreferenceScreen.setEnabled(true); + } + }); + } + }); } private void registerEventListener(String event) { diff --git a/mobile/android/base/GeckoScreenOrientationListener.java b/mobile/android/base/GeckoScreenOrientationListener.java index 1bd88c90ff93..0e0a47f7601f 100644 --- a/mobile/android/base/GeckoScreenOrientationListener.java +++ b/mobile/android/base/GeckoScreenOrientationListener.java @@ -11,15 +11,9 @@ import android.view.OrientationEventListener; import android.view.Surface; import java.util.Arrays; -import java.util.ArrayList; import java.util.List; -import org.json.JSONArray; -import org.json.JSONObject; - -import org.mozilla.gecko.util.GeckoEventListener; - -public class GeckoScreenOrientationListener implements GeckoEventListener { +public class GeckoScreenOrientationListener { private static final String LOGTAG = "GeckoScreenOrientationListener"; static class OrientationEventListenerImpl extends OrientationEventListener { @@ -61,12 +55,12 @@ public class GeckoScreenOrientationListener implements GeckoEventListener { private GeckoScreenOrientationListener() { mListener = new OrientationEventListenerImpl(GeckoApp.mAppContext); - ArrayList prefs = new ArrayList(); - prefs.add(DEFAULT_ORIENTATION_PREF); - JSONArray jsonPrefs = new JSONArray(prefs); - GeckoAppShell.registerEventListener("Preferences:Data", this); - GeckoEvent event = GeckoEvent.createBroadcastEvent("Preferences:Get", jsonPrefs.toString()); - GeckoAppShell.sendEventToGecko(event); + PrefsHelper.getPref(DEFAULT_ORIENTATION_PREF, new PrefsHelper.PrefHandlerBase() { + @Override public void prefValue(String pref, String value) { + mDefaultOrientation = orientationFromStringArray(value); + unlockScreenOrientation(); + } + }); mDefaultOrientation = DEFAULT_ORIENTATION; } @@ -121,30 +115,6 @@ public class GeckoScreenOrientationListener implements GeckoEventListener { mListener.disable(); } - public void handleMessage(String event, JSONObject message) { - try { - if ("Preferences:Data".equals(event)) { - JSONArray jsonPrefs = message.getJSONArray("preferences"); - final int length = jsonPrefs.length(); - for (int i = 0; i < length; i++) { - JSONObject jPref = jsonPrefs.getJSONObject(i); - final String prefName = jPref.getString("name"); - - if (DEFAULT_ORIENTATION_PREF.equals(prefName)) { - final String value = jPref.getString("value"); - mDefaultOrientation = orientationFromStringArray(value); - unlockScreenOrientation(); - - // this is the only pref we care about. unregister after we receive it - GeckoAppShell.unregisterEventListener("Preferences:Data", this); - } - } - } - } catch (Exception e) { - Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); - } - } - private short orientationFromStringArray(String val) { List orientations = Arrays.asList(val.split(",")); // if nothing is listed, return unspecified diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 5a6259e2ef31..75de44e60290 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -96,6 +96,7 @@ FENNEC_JAVA_FILES = \ NSSBridge.java \ CustomEditText.java \ OnInterceptTouchListener.java \ + PrefsHelper.java \ PrivateDataPreference.java \ PropertyAnimator.java \ ProfileMigrator.java \ diff --git a/mobile/android/base/PrefsHelper.java b/mobile/android/base/PrefsHelper.java new file mode 100644 index 000000000000..57d2236698d4 --- /dev/null +++ b/mobile/android/base/PrefsHelper.java @@ -0,0 +1,168 @@ +/* -*- 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.util.GeckoEventListener; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; + +/** + * Helper class to get/set gecko prefs. + */ +public final class PrefsHelper { + private static final String LOGTAG = "GeckoPrefsHelper"; + + private static boolean sRegistered = false; + private static final Map sCallbacks = new HashMap(); + private static int sUniqueRequestId = 1; + + public static void getPref(String prefName, PrefHandler callback) { + JSONArray prefs = new JSONArray(); + prefs.put(prefName); + getPrefs(prefs, callback); + } + + public static void getPrefs(String[] prefNames, PrefHandler callback) { + JSONArray prefs = new JSONArray(); + for (String p : prefNames) { + prefs.put(p); + } + getPrefs(prefs, callback); + } + + public static void getPrefs(JSONArray prefNames, PrefHandler callback) { + int requestId; + synchronized (PrefsHelper.class) { + ensureRegistered(); + + requestId = sUniqueRequestId++; + sCallbacks.put(requestId, callback); + } + + GeckoEvent event; + try { + JSONObject message = new JSONObject(); + message.put("requestId", requestId); + message.put("preferences", prefNames); + event = GeckoEvent.createBroadcastEvent("Preferences:Get", message.toString()); + GeckoAppShell.sendEventToGecko(event); + } catch (Exception e) { + Log.e(LOGTAG, "Error while composing Preferences:Get message", e); + + // if we failed to send the message, drop our reference to the callback because + // otherwise it will leak since we will never get the response + synchronized (PrefsHelper.class) { + sCallbacks.remove(requestId); + } + } + } + + private static void ensureRegistered() { + if (sRegistered) { + return; + } + + GeckoAppShell.getEventDispatcher().registerEventListener("Preferences:Data", new GeckoEventListener() { + @Override public void handleMessage(String event, JSONObject message) { + try { + PrefHandler callback; + synchronized (PrefsHelper.class) { + try { + callback = sCallbacks.remove(message.getInt("requestId")); + } catch (Exception e) { + callback = null; + } + } + if (callback == null) { + Log.d(LOGTAG, "Preferences:Data message had an unknown requestId; ignoring"); + return; + } + + JSONArray jsonPrefs = message.getJSONArray("preferences"); + for (int i = 0; i < jsonPrefs.length(); i++) { + JSONObject pref = jsonPrefs.getJSONObject(i); + String name = pref.getString("name"); + String type = pref.getString("type"); + try { + if ("bool".equals(type)) { + callback.prefValue(name, pref.getBoolean("value")); + } else if ("int".equals(type)) { + callback.prefValue(name, pref.getInt("value")); + } else if ("string".equals(type)) { + callback.prefValue(name, pref.getString("value")); + } else { + Log.e(LOGTAG, "Unknown pref value type [" + type + "] for pref [" + name + "]"); + } + } catch (Exception e) { + Log.e(LOGTAG, "Handler for preference [" + name + "] threw exception", e); + } + } + callback.finish(); + } catch (Exception e) { + Log.e(LOGTAG, "Error handling Preferences:Data message", e); + } + } + }); + sRegistered = true; + } + + public static void setPref(String pref, Object value) { + if (pref == null || pref.length() == 0) { + throw new IllegalArgumentException("Pref name must be non-empty"); + } + + try { + JSONObject jsonPref = new JSONObject(); + jsonPref.put("name", pref); + if (value instanceof Boolean) { + jsonPref.put("type", "bool"); + jsonPref.put("value", ((Boolean)value).booleanValue()); + } else if (value instanceof Integer) { + jsonPref.put("type", "int"); + jsonPref.put("value", ((Integer)value).intValue()); + } else { + jsonPref.put("type", "string"); + jsonPref.put("value", String.valueOf(value)); + } + + GeckoEvent event = GeckoEvent.createBroadcastEvent("Preferences:Set", jsonPref.toString()); + GeckoAppShell.sendEventToGecko(event); + } catch (JSONException e) { + Log.e(LOGTAG, "Error setting pref [" + pref + "]", e); + } + } + + public interface PrefHandler { + void prefValue(String pref, boolean value); + void prefValue(String pref, int value); + void prefValue(String pref, String value); + void finish(); + } + + public static abstract class PrefHandlerBase implements PrefHandler { + public void prefValue(String pref, boolean value) { + Log.w(LOGTAG, "Unhandled boolean value for pref [" + pref + "]"); + } + + public void prefValue(String pref, int value) { + Log.w(LOGTAG, "Unhandled int value for pref [" + pref + "]"); + } + + public void prefValue(String pref, String value) { + Log.w(LOGTAG, "Unhandled String value for pref [" + pref + "]"); + } + + public void finish() { + } + } +} diff --git a/mobile/android/base/ProfileMigrator.java b/mobile/android/base/ProfileMigrator.java index d9d5b8850577..d95aea73458a 100644 --- a/mobile/android/base/ProfileMigrator.java +++ b/mobile/android/base/ProfileMigrator.java @@ -13,11 +13,6 @@ import org.mozilla.gecko.sqlite.SQLiteBridge; import org.mozilla.gecko.sqlite.SQLiteBridgeException; import org.mozilla.gecko.sync.setup.SyncAccounts; import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; -import org.mozilla.gecko.util.GeckoEventListener; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; import android.accounts.Account; import android.content.ContentProviderOperation; @@ -532,39 +527,26 @@ public class ProfileMigrator { } } - private class SyncTask implements Runnable, GeckoEventListener { - private List mSyncSettingsList; + private class SyncTask implements Runnable { private Map mSyncSettingsMap; - // Initialize preferences by sending the "Preferences:Get" command to Gecko protected void requestValues() { - mSyncSettingsList = Arrays.asList(SYNC_SETTINGS_LIST); mSyncSettingsMap = new HashMap(); - JSONArray jsonPrefs = new JSONArray(mSyncSettingsList); - Log.d(LOGTAG, "Sending: " + jsonPrefs.toString()); - GeckoEvent event = - GeckoEvent.createBroadcastEvent("Preferences:Get", - jsonPrefs.toString()); - GeckoAppShell.sendEventToGecko(event); - } + PrefsHelper.getPrefs(SYNC_SETTINGS_LIST, new PrefsHelper.PrefHandlerBase() { + @Override public void prefValue(String pref, boolean value) { + mSyncSettingsMap.put(pref, value ? "1" : "0"); + } - // Receive settings reply from Gecko, do the rest of the setup - public void handleMessage(String event, JSONObject message) { - Log.d(LOGTAG, "Received event: " + event); - try { - if (event.equals("Preferences:Data")) { - // Receive most settings from Gecko's service. - // This includes personal info, so don't log. - // Log.d(LOGTAG, "Message: " + message.toString()); - JSONArray jsonPrefs = message.getJSONArray("preferences"); - - // Check that the batch of preferences we got notified of are in - // the ones we requested and not those requested by other java code. - if (!parsePrefs(jsonPrefs)) - return; - - unregisterEventListener("Preferences:Data", this); + @Override public void prefValue(String pref, String value) { + if (!TextUtils.isEmpty(value)) { + mSyncSettingsMap.put(pref, value); + } else { + Log.w(LOGTAG, "Could not recover setting for = " + pref); + mSyncSettingsMap.put(pref, null); + } + } + @Override public void finish() { // Now call the password provider to fill in the rest. for (String location: SYNC_REALM_LIST) { Log.d(LOGTAG, "Checking: " + location); @@ -581,9 +563,7 @@ public class ProfileMigrator { // Call Sync and transfer settings. configureSync(); } - } catch (Exception e) { - Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); - } + }); } protected String getPassword(String realm) { @@ -619,41 +599,6 @@ public class ProfileMigrator { return result; } - // Returns true if we sucessfully got the preferences we requested. - protected boolean parsePrefs(JSONArray jsonPrefs) { - try { - final int length = jsonPrefs.length(); - for (int i = 0; i < length; i++) { - JSONObject jPref = jsonPrefs.getJSONObject(i); - final String prefName = jPref.getString("name"); - - // Check to make sure we're working with preferences we requested. - if (!mSyncSettingsList.contains(prefName)) - return false; - - final String prefType = jPref.getString("type"); - if ("bool".equals(prefType)) { - final boolean value = jPref.getBoolean("value"); - mSyncSettingsMap.put(prefName, value ? "1" : "0"); - } else { - final String value = jPref.getString("value"); - if (!TextUtils.isEmpty(value)) { - mSyncSettingsMap.put(prefName, value); - } else { - Log.w(LOGTAG, "Could not recover setting for = " + prefName); - mSyncSettingsMap.put(prefName, null); - } - } - } - } catch (JSONException e) { - Log.e(LOGTAG, "Exception handling preferences answer: " - + e.getMessage()); - return false; - } - - return true; - } - protected void configureSync() { final String userName = mSyncSettingsMap.get("services.sync.account"); final String syncKey = mSyncSettingsMap.get("Mozilla Services Encryption Passphrase"); @@ -692,7 +637,6 @@ public class ProfileMigrator { protected void registerAndRequest() { GeckoAppShell.getHandler().post(new Runnable() { public void run() { - registerEventListener("Preferences:Data", SyncTask.this); requestValues(); } }); @@ -718,14 +662,6 @@ public class ProfileMigrator { } }.execute(mContext); } - - private void registerEventListener(String event, GeckoEventListener listener) { - GeckoAppShell.getEventDispatcher().registerEventListener(event, listener); - } - - private void unregisterEventListener(String event, GeckoEventListener listener) { - GeckoAppShell.getEventDispatcher().unregisterEventListener(event, listener); - } } private class MiscTask implements Runnable { diff --git a/mobile/android/base/gfx/DisplayPortCalculator.java b/mobile/android/base/gfx/DisplayPortCalculator.java index 81ce8c3276c0..2218e7edbae5 100644 --- a/mobile/android/base/gfx/DisplayPortCalculator.java +++ b/mobile/android/base/gfx/DisplayPortCalculator.java @@ -6,6 +6,7 @@ package org.mozilla.gecko.gfx; import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.util.FloatUtils; import org.json.JSONArray; @@ -15,6 +16,7 @@ import android.graphics.RectF; import android.util.FloatMath; import android.util.Log; +import java.util.HashMap; import java.util.Map; final class DisplayPortCalculator { @@ -58,7 +60,8 @@ final class DisplayPortCalculator { sStrategy.resetPageState(); } - static void addPrefNames(JSONArray prefs) { + static void initPrefs() { + JSONArray prefs = new JSONArray(); prefs.put(PREF_DISPLAYPORT_STRATEGY); prefs.put(PREF_DISPLAYPORT_FM_MULTIPLIER); prefs.put(PREF_DISPLAYPORT_FM_DANGER_X); @@ -71,6 +74,18 @@ final class DisplayPortCalculator { prefs.put(PREF_DISPLAYPORT_VB_DANGER_X_INCR); prefs.put(PREF_DISPLAYPORT_VB_DANGER_Y_INCR); prefs.put(PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD); + + PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() { + private Map mValues = new HashMap(); + + @Override public void prefValue(String pref, int value) { + mValues.put(pref, value); + } + + @Override public void finish() { + setStrategy(mValues); + } + }); } /** diff --git a/mobile/android/base/gfx/GeckoLayerClient.java b/mobile/android/base/gfx/GeckoLayerClient.java index bb55311902d8..b3e4f8ab4a2f 100644 --- a/mobile/android/base/gfx/GeckoLayerClient.java +++ b/mobile/android/base/gfx/GeckoLayerClient.java @@ -15,7 +15,6 @@ import org.mozilla.gecko.ui.PanZoomTarget; import org.mozilla.gecko.util.EventDispatcher; import org.mozilla.gecko.util.GeckoEventResponder; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -130,17 +129,14 @@ public class GeckoLayerClient registerEventListener("Viewport:PageSize"); registerEventListener("Viewport:CalculateDisplayPort"); registerEventListener("Checkerboard:Toggle"); - registerEventListener("Preferences:Data"); mView.setListener(this); mView.setLayerRenderer(mLayerRenderer); sendResizeEventIfNecessary(true); - JSONArray prefs = new JSONArray(); - DisplayPortCalculator.addPrefNames(prefs); - PluginLayer.addPrefNames(prefs); - GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Preferences:Get", prefs.toString())); + DisplayPortCalculator.initPrefs(); + PluginLayer.initPrefs(); } public void destroy() { @@ -149,7 +145,6 @@ public class GeckoLayerClient unregisterEventListener("Viewport:PageSize"); unregisterEventListener("Viewport:CalculateDisplayPort"); unregisterEventListener("Checkerboard:Toggle"); - unregisterEventListener("Preferences:Data"); } private void registerEventListener(String event) { @@ -362,25 +357,6 @@ public class GeckoLayerClient mReturnDisplayPort = DisplayPortCalculator.calculate(newMetrics, null); } else if ("Checkerboard:Toggle".equals(event)) { mView.setCheckerboardShouldShowChecks(message.getBoolean("value")); - } else if ("Preferences:Data".equals(event)) { - JSONArray jsonPrefs = message.getJSONArray("preferences"); - Map prefValues = new HashMap(); - for (int i = jsonPrefs.length() - 1; i >= 0; i--) { - JSONObject pref = jsonPrefs.getJSONObject(i); - String name = pref.getString("name"); - try { - prefValues.put(name, pref.getInt("value")); - } catch (JSONException je) { - // the pref value couldn't be parsed as an int. drop this pref - // and continue with the rest - } - } - // check return value from setStrategy to make sure that this is the - // right batch of prefs, since other java code may also have sent requests - // for prefs. - if (DisplayPortCalculator.setStrategy(prefValues) && PluginLayer.setUsePlaceholder(prefValues)) { - unregisterEventListener("Preferences:Data"); - } } } catch (JSONException e) { Log.e(LOGTAG, "Error decoding JSON in " + event + " handler", e); diff --git a/mobile/android/base/gfx/PluginLayer.java b/mobile/android/base/gfx/PluginLayer.java index bbd61cb7352d..8d195949d45e 100644 --- a/mobile/android/base/gfx/PluginLayer.java +++ b/mobile/android/base/gfx/PluginLayer.java @@ -6,11 +6,10 @@ package org.mozilla.gecko.gfx; import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.SurfaceBits; import org.mozilla.gecko.util.FloatUtils; -import org.json.JSONArray; - import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; @@ -22,7 +21,6 @@ import android.view.View; import android.widget.AbsoluteLayout; import java.nio.FloatBuffer; -import java.util.Map; public class PluginLayer extends TileLayer { private static final String LOGTAG = "PluginLayer"; @@ -68,19 +66,13 @@ public class PluginLayer extends TileLayer { mLayoutParams = new PluginLayoutParams(rect, maxDimension); } - static void addPrefNames(JSONArray prefs) { - prefs.put(PREF_PLUGIN_USE_PLACEHOLDER); - } - - static boolean setUsePlaceholder(Map prefs) { - Integer usePlaceholder = prefs.get(PREF_PLUGIN_USE_PLACEHOLDER); - if (usePlaceholder == null) { - return false; - } - - sUsePlaceholder = (int)usePlaceholder == 1 ? true : false; - Log.i(LOGTAG, "Using plugin placeholder: " + sUsePlaceholder); - return true; + static void initPrefs() { + PrefsHelper.getPref(PREF_PLUGIN_USE_PLACEHOLDER, new PrefsHelper.PrefHandlerBase() { + @Override public void prefValue(String pref, int value) { + sUsePlaceholder = (value == 1); + Log.i(LOGTAG, "Using plugin placeholder: " + sUsePlaceholder); + } + }); } public void setVisible(boolean newVisible) { diff --git a/mobile/android/base/tests/testPasswordEncrypt.java.in b/mobile/android/base/tests/testPasswordEncrypt.java.in index 317bd5b911b3..e155a1c411e3 100644 --- a/mobile/android/base/tests/testPasswordEncrypt.java.in +++ b/mobile/android/base/tests/testPasswordEncrypt.java.in @@ -129,21 +129,26 @@ public class testPasswordEncrypt extends BaseTest { jsonPref.put("type", "string"); jsonPref.put("value", passwd); mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString()); + + // Wait for confirmation of the pref change before proceeding with the test. + JSONArray getPrefData = new JSONArray(); + getPrefData.put("privacy.masterpassword.enabled"); + JSONObject message = new JSONObject(); + message.put("requestId", "testPasswordEncrypt"); + message.put("preferences", getPrefData); + Actions.RepeatedEventExpecter contentEventExpecter = mActions.expectGeckoEvent("Preferences:Data"); + mActions.sendGeckoEvent("Preferences:Get", message.toString()); + // Receiving a Preferences:Data event is not conclusive evidence that *our* + // preference has been set -- another component may be changing preferences + // at the same time. Mitigate this risk by waiting for a Preference:Data + // and then waiting for a period of time in which no more Preference:Data + // events are received. + // TODO: add a new expectGeckoEvent function that listens for a Preferences:Data + // message with a specific requestId + contentEventExpecter.blockUntilClear(2000); } catch (Exception ex) { mAsserter.ok(false, "exception in toggleMasterPassword", ex.toString()); } - - // Wait for confirmation of the pref change before proceeding with the test. - JSONArray getPrefData = new JSONArray(); - getPrefData.put("privacy.masterpassword.enabled"); - Actions.RepeatedEventExpecter contentEventExpecter = mActions.expectGeckoEvent("Preferences:Data"); - mActions.sendGeckoEvent("Preferences:Get", getPrefData.toString()); - // Receiving a Preferences:Data event is not conclusive evidence that *our* - // preference has been set -- another component may be changing preferences - // at the same time. Mitigate this risk by waiting for a Preference:Data - // and then waiting for a period of time in which no more Preference:Data - // events are received. - contentEventExpecter.blockUntilClear(2000); } public void tearDown() throws Exception { diff --git a/mobile/android/base/ui/Axis.java b/mobile/android/base/ui/Axis.java index 9829cbefba77..425713e9a70d 100644 --- a/mobile/android/base/ui/Axis.java +++ b/mobile/android/base/ui/Axis.java @@ -5,6 +5,7 @@ package org.mozilla.gecko.ui; +import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.util.FloatUtils; import org.json.JSONArray; @@ -12,6 +13,7 @@ import org.json.JSONArray; import android.util.Log; import android.view.View; +import java.util.HashMap; import java.util.Map; /** @@ -61,7 +63,8 @@ abstract class Axis { return (value == null || value < 0 ? defaultValue : value); } - static void addPrefNames(JSONArray prefs) { + static void initPrefs() { + JSONArray prefs = new JSONArray(); prefs.put(PREF_SCROLLING_FRICTION_FAST); prefs.put(PREF_SCROLLING_FRICTION_SLOW); prefs.put(PREF_SCROLLING_VELOCITY_THRESHOLD); @@ -69,6 +72,18 @@ abstract class Axis { prefs.put(PREF_SCROLLING_OVERSCROLL_DECEL_RATE); prefs.put(PREF_SCROLLING_OVERSCROLL_SNAP_LIMIT); prefs.put(PREF_SCROLLING_MIN_SCROLLABLE_DISTANCE); + + PrefsHelper.getPrefs(prefs, new PrefsHelper.PrefHandlerBase() { + Map mPrefs = new HashMap(); + + @Override public void prefValue(String name, int value) { + mPrefs.put(name, value); + } + + @Override public void finish() { + setPrefs(mPrefs); + } + }); } static void setPrefs(Map prefs) { diff --git a/mobile/android/base/ui/PanZoomController.java b/mobile/android/base/ui/PanZoomController.java index 3178baf9448c..9194f69dd269 100644 --- a/mobile/android/base/ui/PanZoomController.java +++ b/mobile/android/base/ui/PanZoomController.java @@ -8,6 +8,7 @@ package org.mozilla.gecko.ui; import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; +import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.PointUtils; @@ -16,8 +17,6 @@ import org.mozilla.gecko.util.EventDispatcher; import org.mozilla.gecko.util.FloatUtils; import org.mozilla.gecko.util.GeckoEventListener; -import org.json.JSONArray; -import org.json.JSONException; import org.json.JSONObject; import android.graphics.PointF; @@ -28,8 +27,6 @@ import android.view.GestureDetector; import android.view.MotionEvent; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.StringTokenizer; import java.util.Timer; import java.util.TimerTask; @@ -48,8 +45,6 @@ public class PanZoomController private static String MESSAGE_ZOOM_RECT = "Browser:ZoomToRect"; private static String MESSAGE_ZOOM_PAGE = "Browser:ZoomToPageWidth"; - private static String MESSAGE_PREFS_GET = "Preferences:Get"; - private static String MESSAGE_PREFS_DATA = "Preferences:Data"; private static final String PREF_ZOOM_ANIMATION_FRAMES = "ui.zooming.animation_frames"; @@ -139,18 +134,18 @@ public class PanZoomController mEventDispatcher = eventDispatcher; registerEventListener(MESSAGE_ZOOM_RECT); registerEventListener(MESSAGE_ZOOM_PAGE); - registerEventListener(MESSAGE_PREFS_DATA); - JSONArray prefs = new JSONArray(); - prefs.put(PREF_ZOOM_ANIMATION_FRAMES); - Axis.addPrefNames(prefs); - GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(MESSAGE_PREFS_GET, prefs.toString())); + PrefsHelper.getPref(PREF_ZOOM_ANIMATION_FRAMES, new PrefsHelper.PrefHandlerBase() { + @Override public void prefValue(String pref, String value) { + setZoomAnimationFrames(value); + } + }); + Axis.initPrefs(); } public void destroy() { unregisterEventListener(MESSAGE_ZOOM_RECT); unregisterEventListener(MESSAGE_ZOOM_PAGE); - unregisterEventListener(MESSAGE_PREFS_DATA); mSubscroller.destroy(); } @@ -213,32 +208,6 @@ public class PanZoomController animatedZoomTo(r); } }); - } else if (MESSAGE_PREFS_DATA.equals(event)) { - JSONArray jsonPrefs = message.getJSONArray("preferences"); - Map axisPrefs = new HashMap(); - String zoomAnimationFrames = null; - for (int i = jsonPrefs.length() - 1; i >= 0; i--) { - JSONObject pref = jsonPrefs.getJSONObject(i); - String name = pref.getString("name"); - if (PREF_ZOOM_ANIMATION_FRAMES.equals(name)) { - zoomAnimationFrames = pref.getString("value"); - } else { - try { - axisPrefs.put(name, pref.getInt("value")); - } catch (JSONException je) { - // the value could not be parsed as an int. ignore this - // pref and continue - } - } - } - // check for null to make sure the batch of preferences we got notified - // of are in the fact the ones we requested and not those requested by - // other java code - if (zoomAnimationFrames != null) { - setZoomAnimationFrames(zoomAnimationFrames); - Axis.setPrefs(axisPrefs); - unregisterEventListener(MESSAGE_PREFS_DATA); - } } } catch (Exception e) { Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e); diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 58e62dce7d0f..a83bb564d798 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -811,7 +811,7 @@ var BrowserApp = { let json = JSON.parse(aPrefNames); let prefs = []; - for each (let prefName in json) { + for each (let prefName in json.preferences) { let pref = { name: prefName }; @@ -880,6 +880,7 @@ var BrowserApp = { sendMessageToJava({ gecko: { type: "Preferences:Data", + requestId: json.requestId, // opaque request identifier, can be any string/int/whatever preferences: prefs } });