1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.email; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.text.TextUtils; 22 import android.util.Log; 23 24 import com.android.emailcommon.Logging; 25 26 import org.json.JSONArray; 27 import org.json.JSONException; 28 29 import java.util.HashSet; 30 import java.util.UUID; 31 32 public class Preferences { 33 34 // Preferences file 35 public static final String PREFERENCES_FILE = "AndroidMail.Main"; 36 37 // Preferences field names 38 private static final String ACCOUNT_UUIDS = "accountUuids"; 39 private static final String ENABLE_DEBUG_LOGGING = "enableDebugLogging"; 40 private static final String ENABLE_EXCHANGE_LOGGING = "enableExchangeLogging"; 41 private static final String ENABLE_EXCHANGE_FILE_LOGGING = "enableExchangeFileLogging"; 42 private static final String INHIBIT_GRAPHICS_ACCELERATION = "inhibitGraphicsAcceleration"; 43 private static final String FORCE_ONE_MINUTE_REFRESH = "forceOneMinuteRefresh"; 44 private static final String ENABLE_STRICT_MODE = "enableStrictMode"; 45 private static final String DEVICE_UID = "deviceUID"; 46 private static final String ONE_TIME_INITIALIZATION_PROGRESS = "oneTimeInitializationProgress"; 47 private static final String AUTO_ADVANCE_DIRECTION = "autoAdvance"; 48 private static final String TEXT_ZOOM = "textZoom"; 49 private static final String BACKGROUND_ATTACHMENTS = "backgroundAttachments"; 50 private static final String TRUSTED_SENDERS = "trustedSenders"; 51 52 public static final int AUTO_ADVANCE_NEWER = 0; 53 public static final int AUTO_ADVANCE_OLDER = 1; 54 public static final int AUTO_ADVANCE_MESSAGE_LIST = 2; 55 // "move to older" was the behavior on older versions. 56 private static final int AUTO_ADVANCE_DEFAULT = AUTO_ADVANCE_OLDER; 57 58 // The following constants are used as offsets into TEXT_ZOOM_ARRAY (below) 59 public static final int TEXT_ZOOM_TINY = 0; 60 public static final int TEXT_ZOOM_SMALL = 1; 61 public static final int TEXT_ZOOM_NORMAL = 2; 62 public static final int TEXT_ZOOM_LARGE = 3; 63 public static final int TEXT_ZOOM_HUGE = 4; 64 // "normal" will be the default 65 public static final int TEXT_ZOOM_DEFAULT = TEXT_ZOOM_NORMAL; 66 67 // Starting something new here: 68 // REPLY_ALL is saved by the framework (CheckBoxPreference's parent, Preference). 69 // i.e. android:persistent=true in general_preferences.xml 70 public static final String REPLY_ALL = "reply_all"; 71 // Reply All Default - when changing this, be sure to update general_preferences.xml 72 public static final boolean REPLY_ALL_DEFAULT = false; 73 74 private static Preferences sPreferences; 75 76 private final SharedPreferences mSharedPreferences; 77 78 /** 79 * A set of trusted senders for whom images and external resources should automatically be 80 * loaded for. 81 * Lazilly created. 82 */ 83 private HashSet<String> mTrustedSenders = null; 84 85 private Preferences(Context context) { 86 mSharedPreferences = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE); 87 } 88 89 /** 90 * TODO need to think about what happens if this gets GCed along with the 91 * Activity that initialized it. Do we lose ability to read Preferences in 92 * further Activities? Maybe this should be stored in the Application 93 * context. 94 */ 95 public static synchronized Preferences getPreferences(Context context) { 96 if (sPreferences == null) { 97 sPreferences = new Preferences(context); 98 } 99 return sPreferences; 100 } 101 102 public static SharedPreferences getSharedPreferences(Context context) { 103 return getPreferences(context).mSharedPreferences; 104 } 105 106 public static String getLegacyBackupPreference(Context context) { 107 return getPreferences(context).mSharedPreferences.getString(ACCOUNT_UUIDS, null); 108 } 109 110 public static void clearLegacyBackupPreference(Context context) { 111 getPreferences(context).mSharedPreferences.edit().remove(ACCOUNT_UUIDS).apply(); 112 } 113 114 public void setEnableDebugLogging(boolean value) { 115 mSharedPreferences.edit().putBoolean(ENABLE_DEBUG_LOGGING, value).apply(); 116 } 117 118 public boolean getEnableDebugLogging() { 119 return mSharedPreferences.getBoolean(ENABLE_DEBUG_LOGGING, false); 120 } 121 122 public void setEnableExchangeLogging(boolean value) { 123 mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_LOGGING, value).apply(); 124 } 125 126 public boolean getEnableExchangeLogging() { 127 return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_LOGGING, false); 128 } 129 130 public void setEnableExchangeFileLogging(boolean value) { 131 mSharedPreferences.edit().putBoolean(ENABLE_EXCHANGE_FILE_LOGGING, value).apply(); 132 } 133 134 public boolean getEnableExchangeFileLogging() { 135 return mSharedPreferences.getBoolean(ENABLE_EXCHANGE_FILE_LOGGING, false); 136 } 137 138 public void setInhibitGraphicsAcceleration(boolean value) { 139 mSharedPreferences.edit().putBoolean(INHIBIT_GRAPHICS_ACCELERATION, value).apply(); 140 } 141 142 public boolean getInhibitGraphicsAcceleration() { 143 return mSharedPreferences.getBoolean(INHIBIT_GRAPHICS_ACCELERATION, false); 144 } 145 146 public void setForceOneMinuteRefresh(boolean value) { 147 mSharedPreferences.edit().putBoolean(FORCE_ONE_MINUTE_REFRESH, value).apply(); 148 } 149 150 public boolean getForceOneMinuteRefresh() { 151 return mSharedPreferences.getBoolean(FORCE_ONE_MINUTE_REFRESH, false); 152 } 153 154 public void setEnableStrictMode(boolean value) { 155 mSharedPreferences.edit().putBoolean(ENABLE_STRICT_MODE, value).apply(); 156 } 157 158 public boolean getEnableStrictMode() { 159 return mSharedPreferences.getBoolean(ENABLE_STRICT_MODE, false); 160 } 161 162 /** 163 * Generate a new "device UID". This is local to Email app only, to prevent possibility 164 * of correlation with any other user activities in any other apps. 165 * @return a persistent, unique ID 166 */ 167 public synchronized String getDeviceUID() { 168 String result = mSharedPreferences.getString(DEVICE_UID, null); 169 if (result == null) { 170 result = UUID.randomUUID().toString(); 171 mSharedPreferences.edit().putString(DEVICE_UID, result).apply(); 172 } 173 return result; 174 } 175 176 public int getOneTimeInitializationProgress() { 177 return mSharedPreferences.getInt(ONE_TIME_INITIALIZATION_PROGRESS, 0); 178 } 179 180 public void setOneTimeInitializationProgress(int progress) { 181 mSharedPreferences.edit().putInt(ONE_TIME_INITIALIZATION_PROGRESS, progress).apply(); 182 } 183 184 public int getAutoAdvanceDirection() { 185 return mSharedPreferences.getInt(AUTO_ADVANCE_DIRECTION, AUTO_ADVANCE_DEFAULT); 186 } 187 188 public void setAutoAdvanceDirection(int direction) { 189 mSharedPreferences.edit().putInt(AUTO_ADVANCE_DIRECTION, direction).apply(); 190 } 191 192 public int getTextZoom() { 193 return mSharedPreferences.getInt(TEXT_ZOOM, TEXT_ZOOM_DEFAULT); 194 } 195 196 public void setTextZoom(int zoom) { 197 mSharedPreferences.edit().putInt(TEXT_ZOOM, zoom).apply(); 198 } 199 200 public boolean getBackgroundAttachments() { 201 return mSharedPreferences.getBoolean(BACKGROUND_ATTACHMENTS, false); 202 } 203 204 public void setBackgroundAttachments(boolean allowed) { 205 mSharedPreferences.edit().putBoolean(BACKGROUND_ATTACHMENTS, allowed).apply(); 206 } 207 208 /** 209 * Determines whether or not a sender should be trusted and images should automatically be 210 * shown for messages by that sender. 211 */ 212 public boolean shouldShowImagesFor(String email) { 213 if (mTrustedSenders == null) { 214 try { 215 mTrustedSenders = parseEmailSet(mSharedPreferences.getString(TRUSTED_SENDERS, "")); 216 } catch (JSONException e) { 217 // Something went wrong, and the data is corrupt. Just clear it to be safe. 218 Log.w(Logging.LOG_TAG, "Trusted sender set corrupted. Clearing"); 219 mSharedPreferences.edit().putString(TRUSTED_SENDERS, "").apply(); 220 mTrustedSenders = new HashSet<String>(); 221 } 222 } 223 return mTrustedSenders.contains(email); 224 } 225 226 /** 227 * Marks a sender as trusted so that images from that sender will automatically be shown. 228 */ 229 public void setSenderAsTrusted(String email) { 230 if (!mTrustedSenders.contains(email)) { 231 mTrustedSenders.add(email); 232 mSharedPreferences 233 .edit() 234 .putString(TRUSTED_SENDERS, packEmailSet(mTrustedSenders)) 235 .apply(); 236 } 237 } 238 239 /** 240 * Clears all trusted senders asynchronously. 241 */ 242 public void clearTrustedSenders() { 243 mTrustedSenders = new HashSet<String>(); 244 mSharedPreferences 245 .edit() 246 .putString(TRUSTED_SENDERS, packEmailSet(mTrustedSenders)) 247 .apply(); 248 } 249 250 HashSet<String> parseEmailSet(String serialized) throws JSONException { 251 HashSet<String> result = new HashSet<String>(); 252 if (!TextUtils.isEmpty(serialized)) { 253 JSONArray arr = new JSONArray(serialized); 254 for (int i = 0, len = arr.length(); i < len; i++) { 255 result.add((String) arr.get(i)); 256 } 257 } 258 return result; 259 } 260 261 String packEmailSet(HashSet<String> set) { 262 return new JSONArray(set).toString(); 263 } 264 265 public void clear() { 266 mSharedPreferences.edit().clear().apply(); 267 } 268 269 public void dump() { 270 if (Logging.LOGD) { 271 for (String key : mSharedPreferences.getAll().keySet()) { 272 Log.v(Logging.LOG_TAG, key + " = " + mSharedPreferences.getAll().get(key)); 273 } 274 } 275 } 276 } 277