Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 package org.mozilla.gecko.home;
8 import static org.mozilla.gecko.home.HomeConfig.createBuiltinPanelConfig;
10 import java.util.ArrayList;
11 import java.util.EnumSet;
12 import java.util.List;
13 import java.util.Locale;
15 import org.json.JSONArray;
16 import org.json.JSONException;
17 import org.json.JSONObject;
18 import org.mozilla.gecko.GeckoSharedPrefs;
19 import org.mozilla.gecko.home.HomeConfig.HomeConfigBackend;
20 import org.mozilla.gecko.home.HomeConfig.OnReloadListener;
21 import org.mozilla.gecko.home.HomeConfig.PanelConfig;
22 import org.mozilla.gecko.home.HomeConfig.PanelType;
23 import org.mozilla.gecko.home.HomeConfig.State;
24 import org.mozilla.gecko.util.HardwareUtils;
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.SharedPreferences;
31 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
32 import android.support.v4.content.LocalBroadcastManager;
33 import android.text.TextUtils;
34 import android.util.Log;
36 class HomeConfigPrefsBackend implements HomeConfigBackend {
37 private static final String LOGTAG = "GeckoHomeConfigBackend";
39 private static final String PREFS_CONFIG_KEY = "home_panels";
40 private static final String PREFS_LOCALE_KEY = "home_locale";
42 private static final String RELOAD_BROADCAST = "HomeConfigPrefsBackend:Reload";
44 private final Context mContext;
45 private ReloadBroadcastReceiver mReloadBroadcastReceiver;
46 private OnReloadListener mReloadListener;
48 public HomeConfigPrefsBackend(Context context) {
49 mContext = context;
50 }
52 private SharedPreferences getSharedPreferences() {
53 return GeckoSharedPrefs.forProfile(mContext);
54 }
56 private State loadDefaultConfig() {
57 final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>();
59 panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.TOP_SITES,
60 EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
62 panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS));
64 // We disable reader mode support on low memory devices. Hence the
65 // reading list panel should not show up on such devices.
66 if (!HardwareUtils.isLowMemoryPlatform()) {
67 panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST));
68 }
70 final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY);
72 // On tablets, the history panel is the last.
73 // On phones, the history panel is the first one.
74 if (HardwareUtils.isTablet()) {
75 panelConfigs.add(historyEntry);
76 } else {
77 panelConfigs.add(0, historyEntry);
78 }
80 return new State(panelConfigs, true);
81 }
83 private State loadConfigFromString(String jsonString) {
84 final JSONArray jsonPanelConfigs;
85 try {
86 jsonPanelConfigs = new JSONArray(jsonString);
87 } catch (JSONException e) {
88 Log.e(LOGTAG, "Error loading the list of home panels from JSON prefs", e);
90 // Fallback to default config
91 return loadDefaultConfig();
92 }
94 final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>();
96 final int count = jsonPanelConfigs.length();
97 for (int i = 0; i < count; i++) {
98 try {
99 final JSONObject jsonPanelConfig = jsonPanelConfigs.getJSONObject(i);
100 final PanelConfig panelConfig = new PanelConfig(jsonPanelConfig);
101 panelConfigs.add(panelConfig);
102 } catch (Exception e) {
103 Log.e(LOGTAG, "Exception loading PanelConfig from JSON", e);
104 }
105 }
107 return new State(panelConfigs, false);
108 }
110 @Override
111 public State load() {
112 final SharedPreferences prefs = getSharedPreferences();
113 final String jsonString = prefs.getString(PREFS_CONFIG_KEY, null);
115 final State configState;
116 if (TextUtils.isEmpty(jsonString)) {
117 configState = loadDefaultConfig();
118 } else {
119 configState = loadConfigFromString(jsonString);
120 }
122 return configState;
123 }
125 @Override
126 public void save(State configState) {
127 final SharedPreferences prefs = getSharedPreferences();
128 final SharedPreferences.Editor editor = prefs.edit();
130 // No need to save the state to disk if it represents the default
131 // HomeConfig configuration. Simply force all existing HomeConfigLoader
132 // instances to refresh their contents.
133 if (!configState.isDefault()) {
134 final JSONArray jsonPanelConfigs = new JSONArray();
136 for (PanelConfig panelConfig : configState) {
137 try {
138 final JSONObject jsonPanelConfig = panelConfig.toJSON();
139 jsonPanelConfigs.put(jsonPanelConfig);
140 } catch (Exception e) {
141 Log.e(LOGTAG, "Exception converting PanelConfig to JSON", e);
142 }
143 }
145 editor.putString(PREFS_CONFIG_KEY, jsonPanelConfigs.toString());
146 }
148 editor.putString(PREFS_LOCALE_KEY, Locale.getDefault().toString());
149 editor.commit();
151 // Trigger reload listeners on all live backend instances
152 sendReloadBroadcast();
153 }
155 @Override
156 public String getLocale() {
157 final SharedPreferences prefs = getSharedPreferences();
159 String locale = prefs.getString(PREFS_LOCALE_KEY, null);
160 if (locale == null) {
161 // Initialize config with the current locale
162 final String currentLocale = Locale.getDefault().toString();
164 final SharedPreferences.Editor editor = prefs.edit();
165 editor.putString(PREFS_LOCALE_KEY, currentLocale);
166 editor.commit();
168 // If the user has saved HomeConfig before, return null this
169 // one time to trigger a refresh and ensure we use the
170 // correct locale for the saved state. For more context,
171 // see HomePanelsManager.onLocaleReady().
172 if (!prefs.contains(PREFS_CONFIG_KEY)) {
173 locale = currentLocale;
174 }
175 }
177 return locale;
178 }
180 @Override
181 public void setOnReloadListener(OnReloadListener listener) {
182 if (mReloadListener != null) {
183 unregisterReloadReceiver();
184 mReloadBroadcastReceiver = null;
185 }
187 mReloadListener = listener;
189 if (mReloadListener != null) {
190 mReloadBroadcastReceiver = new ReloadBroadcastReceiver();
191 registerReloadReceiver();
192 }
193 }
195 private void sendReloadBroadcast() {
196 final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext);
197 final Intent reloadIntent = new Intent(RELOAD_BROADCAST);
198 lbm.sendBroadcast(reloadIntent);
199 }
201 private void registerReloadReceiver() {
202 final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext);
203 lbm.registerReceiver(mReloadBroadcastReceiver, new IntentFilter(RELOAD_BROADCAST));
204 }
206 private void unregisterReloadReceiver() {
207 final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext);
208 lbm.unregisterReceiver(mReloadBroadcastReceiver);
209 }
211 private class ReloadBroadcastReceiver extends BroadcastReceiver {
212 @Override
213 public void onReceive(Context context, Intent intent) {
214 mReloadListener.onReload();
215 }
216 }
217 }