1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/home/HomeConfigPrefsBackend.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +package org.mozilla.gecko.home; 1.10 + 1.11 +import static org.mozilla.gecko.home.HomeConfig.createBuiltinPanelConfig; 1.12 + 1.13 +import java.util.ArrayList; 1.14 +import java.util.EnumSet; 1.15 +import java.util.List; 1.16 +import java.util.Locale; 1.17 + 1.18 +import org.json.JSONArray; 1.19 +import org.json.JSONException; 1.20 +import org.json.JSONObject; 1.21 +import org.mozilla.gecko.GeckoSharedPrefs; 1.22 +import org.mozilla.gecko.home.HomeConfig.HomeConfigBackend; 1.23 +import org.mozilla.gecko.home.HomeConfig.OnReloadListener; 1.24 +import org.mozilla.gecko.home.HomeConfig.PanelConfig; 1.25 +import org.mozilla.gecko.home.HomeConfig.PanelType; 1.26 +import org.mozilla.gecko.home.HomeConfig.State; 1.27 +import org.mozilla.gecko.util.HardwareUtils; 1.28 + 1.29 +import android.content.BroadcastReceiver; 1.30 +import android.content.Context; 1.31 +import android.content.Intent; 1.32 +import android.content.IntentFilter; 1.33 +import android.content.SharedPreferences; 1.34 +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 1.35 +import android.support.v4.content.LocalBroadcastManager; 1.36 +import android.text.TextUtils; 1.37 +import android.util.Log; 1.38 + 1.39 +class HomeConfigPrefsBackend implements HomeConfigBackend { 1.40 + private static final String LOGTAG = "GeckoHomeConfigBackend"; 1.41 + 1.42 + private static final String PREFS_CONFIG_KEY = "home_panels"; 1.43 + private static final String PREFS_LOCALE_KEY = "home_locale"; 1.44 + 1.45 + private static final String RELOAD_BROADCAST = "HomeConfigPrefsBackend:Reload"; 1.46 + 1.47 + private final Context mContext; 1.48 + private ReloadBroadcastReceiver mReloadBroadcastReceiver; 1.49 + private OnReloadListener mReloadListener; 1.50 + 1.51 + public HomeConfigPrefsBackend(Context context) { 1.52 + mContext = context; 1.53 + } 1.54 + 1.55 + private SharedPreferences getSharedPreferences() { 1.56 + return GeckoSharedPrefs.forProfile(mContext); 1.57 + } 1.58 + 1.59 + private State loadDefaultConfig() { 1.60 + final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>(); 1.61 + 1.62 + panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.TOP_SITES, 1.63 + EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL))); 1.64 + 1.65 + panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS)); 1.66 + 1.67 + // We disable reader mode support on low memory devices. Hence the 1.68 + // reading list panel should not show up on such devices. 1.69 + if (!HardwareUtils.isLowMemoryPlatform()) { 1.70 + panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST)); 1.71 + } 1.72 + 1.73 + final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY); 1.74 + 1.75 + // On tablets, the history panel is the last. 1.76 + // On phones, the history panel is the first one. 1.77 + if (HardwareUtils.isTablet()) { 1.78 + panelConfigs.add(historyEntry); 1.79 + } else { 1.80 + panelConfigs.add(0, historyEntry); 1.81 + } 1.82 + 1.83 + return new State(panelConfigs, true); 1.84 + } 1.85 + 1.86 + private State loadConfigFromString(String jsonString) { 1.87 + final JSONArray jsonPanelConfigs; 1.88 + try { 1.89 + jsonPanelConfigs = new JSONArray(jsonString); 1.90 + } catch (JSONException e) { 1.91 + Log.e(LOGTAG, "Error loading the list of home panels from JSON prefs", e); 1.92 + 1.93 + // Fallback to default config 1.94 + return loadDefaultConfig(); 1.95 + } 1.96 + 1.97 + final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>(); 1.98 + 1.99 + final int count = jsonPanelConfigs.length(); 1.100 + for (int i = 0; i < count; i++) { 1.101 + try { 1.102 + final JSONObject jsonPanelConfig = jsonPanelConfigs.getJSONObject(i); 1.103 + final PanelConfig panelConfig = new PanelConfig(jsonPanelConfig); 1.104 + panelConfigs.add(panelConfig); 1.105 + } catch (Exception e) { 1.106 + Log.e(LOGTAG, "Exception loading PanelConfig from JSON", e); 1.107 + } 1.108 + } 1.109 + 1.110 + return new State(panelConfigs, false); 1.111 + } 1.112 + 1.113 + @Override 1.114 + public State load() { 1.115 + final SharedPreferences prefs = getSharedPreferences(); 1.116 + final String jsonString = prefs.getString(PREFS_CONFIG_KEY, null); 1.117 + 1.118 + final State configState; 1.119 + if (TextUtils.isEmpty(jsonString)) { 1.120 + configState = loadDefaultConfig(); 1.121 + } else { 1.122 + configState = loadConfigFromString(jsonString); 1.123 + } 1.124 + 1.125 + return configState; 1.126 + } 1.127 + 1.128 + @Override 1.129 + public void save(State configState) { 1.130 + final SharedPreferences prefs = getSharedPreferences(); 1.131 + final SharedPreferences.Editor editor = prefs.edit(); 1.132 + 1.133 + // No need to save the state to disk if it represents the default 1.134 + // HomeConfig configuration. Simply force all existing HomeConfigLoader 1.135 + // instances to refresh their contents. 1.136 + if (!configState.isDefault()) { 1.137 + final JSONArray jsonPanelConfigs = new JSONArray(); 1.138 + 1.139 + for (PanelConfig panelConfig : configState) { 1.140 + try { 1.141 + final JSONObject jsonPanelConfig = panelConfig.toJSON(); 1.142 + jsonPanelConfigs.put(jsonPanelConfig); 1.143 + } catch (Exception e) { 1.144 + Log.e(LOGTAG, "Exception converting PanelConfig to JSON", e); 1.145 + } 1.146 + } 1.147 + 1.148 + editor.putString(PREFS_CONFIG_KEY, jsonPanelConfigs.toString()); 1.149 + } 1.150 + 1.151 + editor.putString(PREFS_LOCALE_KEY, Locale.getDefault().toString()); 1.152 + editor.commit(); 1.153 + 1.154 + // Trigger reload listeners on all live backend instances 1.155 + sendReloadBroadcast(); 1.156 + } 1.157 + 1.158 + @Override 1.159 + public String getLocale() { 1.160 + final SharedPreferences prefs = getSharedPreferences(); 1.161 + 1.162 + String locale = prefs.getString(PREFS_LOCALE_KEY, null); 1.163 + if (locale == null) { 1.164 + // Initialize config with the current locale 1.165 + final String currentLocale = Locale.getDefault().toString(); 1.166 + 1.167 + final SharedPreferences.Editor editor = prefs.edit(); 1.168 + editor.putString(PREFS_LOCALE_KEY, currentLocale); 1.169 + editor.commit(); 1.170 + 1.171 + // If the user has saved HomeConfig before, return null this 1.172 + // one time to trigger a refresh and ensure we use the 1.173 + // correct locale for the saved state. For more context, 1.174 + // see HomePanelsManager.onLocaleReady(). 1.175 + if (!prefs.contains(PREFS_CONFIG_KEY)) { 1.176 + locale = currentLocale; 1.177 + } 1.178 + } 1.179 + 1.180 + return locale; 1.181 + } 1.182 + 1.183 + @Override 1.184 + public void setOnReloadListener(OnReloadListener listener) { 1.185 + if (mReloadListener != null) { 1.186 + unregisterReloadReceiver(); 1.187 + mReloadBroadcastReceiver = null; 1.188 + } 1.189 + 1.190 + mReloadListener = listener; 1.191 + 1.192 + if (mReloadListener != null) { 1.193 + mReloadBroadcastReceiver = new ReloadBroadcastReceiver(); 1.194 + registerReloadReceiver(); 1.195 + } 1.196 + } 1.197 + 1.198 + private void sendReloadBroadcast() { 1.199 + final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext); 1.200 + final Intent reloadIntent = new Intent(RELOAD_BROADCAST); 1.201 + lbm.sendBroadcast(reloadIntent); 1.202 + } 1.203 + 1.204 + private void registerReloadReceiver() { 1.205 + final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext); 1.206 + lbm.registerReceiver(mReloadBroadcastReceiver, new IntentFilter(RELOAD_BROADCAST)); 1.207 + } 1.208 + 1.209 + private void unregisterReloadReceiver() { 1.210 + final LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(mContext); 1.211 + lbm.unregisterReceiver(mReloadBroadcastReceiver); 1.212 + } 1.213 + 1.214 + private class ReloadBroadcastReceiver extends BroadcastReceiver { 1.215 + @Override 1.216 + public void onReceive(Context context, Intent intent) { 1.217 + mReloadListener.onReload(); 1.218 + } 1.219 + } 1.220 +}