1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/sync/config/activities/SelectEnginesActivity.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,210 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.sync.config.activities; 1.9 + 1.10 +import java.util.HashMap; 1.11 +import java.util.Map; 1.12 +import java.util.Map.Entry; 1.13 +import java.util.Set; 1.14 + 1.15 +import org.mozilla.gecko.R; 1.16 +import org.mozilla.gecko.background.common.log.Logger; 1.17 +import org.mozilla.gecko.sync.SyncConfiguration; 1.18 +import org.mozilla.gecko.sync.ThreadPool; 1.19 +import org.mozilla.gecko.sync.setup.SyncAccounts; 1.20 +import org.mozilla.gecko.sync.syncadapter.SyncAdapter; 1.21 + 1.22 +import android.accounts.Account; 1.23 +import android.accounts.AccountManager; 1.24 +import android.app.Activity; 1.25 +import android.app.AlertDialog; 1.26 +import android.content.Context; 1.27 +import android.content.DialogInterface; 1.28 +import android.content.DialogInterface.OnDismissListener; 1.29 +import android.content.SharedPreferences; 1.30 +import android.os.Bundle; 1.31 +import android.widget.ListView; 1.32 +import android.widget.Toast; 1.33 + 1.34 +/** 1.35 + * Provides a user-facing interface for selecting engines to sync. This activity 1.36 + * can be launched from the Sync Settings preferences screen, and will save the 1.37 + * selected engines to the 1.38 + * <code>SyncConfiguration.PREF_USER_SELECTED_ENGINES_TO_SYNC</code> pref. 1.39 + * 1.40 + * On launch, it displays the engines stored in the saved pref if it exists, or 1.41 + * <code>SyncConfiguration.enabledEngineNames()</code> if it doesn't, defaulting 1.42 + * to <code>SyncConfiguration.validEngineNames()</code> if neither exists. 1.43 + * 1.44 + * During a sync, the 1.45 + * <code>SyncConfiguration.PREF_USER_SELECTED_ENGINES_TO_SYNC</code> pref will 1.46 + * be cleared after the engine changes are applied to meta/global. 1.47 + */ 1.48 + 1.49 +public class SelectEnginesActivity extends Activity implements 1.50 + DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener { 1.51 + public final static String LOG_TAG = "SelectEnginesAct"; 1.52 + 1.53 + protected AccountManager mAccountManager; 1.54 + protected Context mContext; 1.55 + 1.56 + // Collections names corresponding to displayed (localized) engine options. 1.57 + final String[] _collectionsNames = new String[] { 1.58 + "bookmarks", 1.59 + "passwords", 1.60 + "history", 1.61 + "tabs" 1.62 + }; 1.63 + 1.64 + // Engine names localized for display in Sync Settings. 1.65 + protected String[] _options; 1.66 + // Selection state of engines corresponding to _options array. 1.67 + final boolean[] _selections = new boolean[_collectionsNames.length]; 1.68 + protected Account account; 1.69 + protected SharedPreferences accountPrefs; 1.70 + 1.71 + @Override 1.72 + public void onCreate(Bundle savedInstanceState) { 1.73 + super.onCreate(savedInstanceState); 1.74 + mContext = getApplicationContext(); 1.75 + mAccountManager = AccountManager.get(mContext); 1.76 + _options = new String[] { 1.77 + getString(R.string.sync_configure_engines_title_bookmarks), 1.78 + getString(R.string.sync_configure_engines_title_passwords), 1.79 + getString(R.string.sync_configure_engines_title_history), 1.80 + getString(R.string.sync_configure_engines_title_tabs) }; 1.81 + 1.82 + // Fetch account prefs for configuring engines. 1.83 + ThreadPool.run(new Runnable() { 1.84 + @Override 1.85 + public void run() { 1.86 + Account[] accounts = SyncAccounts.syncAccounts(mContext); 1.87 + if (accounts.length == 0) { 1.88 + Logger.error(LOG_TAG, "Failed to get account!"); 1.89 + finish(); 1.90 + return; 1.91 + } else { 1.92 + // Only supports one account per type. 1.93 + account = accounts[0]; 1.94 + try { 1.95 + if (accountPrefs == null) { 1.96 + accountPrefs = SyncAccounts.blockingPrefsFromDefaultProfileV0(mContext, mAccountManager, account); 1.97 + } 1.98 + } catch (Exception e) { 1.99 + Logger.error(LOG_TAG, "Failed to get sync account info or shared preferences.", e); 1.100 + finish(); 1.101 + } 1.102 + setSelectionsInArray(getEnginesToSelect(accountPrefs), _selections); 1.103 + } 1.104 + } 1.105 + }); 1.106 + } 1.107 + 1.108 + @Override 1.109 + public void onResume() { 1.110 + super.onResume(); 1.111 + if (accountPrefs != null) { 1.112 + setSelectionsInArray(getEnginesToSelect(accountPrefs), _selections); 1.113 + } 1.114 + AlertDialog dialog = new AlertDialog.Builder(this) 1.115 + .setTitle(R.string.sync_configure_engines_sync_my_title) 1.116 + .setMultiChoiceItems(_options, _selections, this) 1.117 + .setIcon(R.drawable.icon).setPositiveButton(android.R.string.ok, this) 1.118 + .setNegativeButton(android.R.string.cancel, this).create(); 1.119 + 1.120 + dialog.setOnDismissListener(new OnDismissListener() { 1.121 + @Override 1.122 + public void onDismiss(DialogInterface dialog) { 1.123 + finish(); 1.124 + } 1.125 + }); 1.126 + 1.127 + dialog.show(); 1.128 + } 1.129 + 1.130 + private static Set<String> getEnginesFromPrefs(SharedPreferences syncPrefs) { 1.131 + Set<String> engines = SyncConfiguration.getEnabledEngineNames(syncPrefs); 1.132 + if (engines == null) { 1.133 + engines = SyncConfiguration.validEngineNames(); 1.134 + } 1.135 + return engines; 1.136 + } 1.137 + 1.138 + /** 1.139 + * Fetches the engine names that should be displayed as selected for syncing. 1.140 + * Check first for selected engines set by this activity, then the enabled 1.141 + * engines, and finally default to the set of valid engine names for Android 1.142 + * Sync if neither exists. 1.143 + * 1.144 + * @param syncPrefs 1.145 + * <code>SharedPreferences</code> of Account being modified. 1.146 + * @return Set<String> of engine names to display as selected. Should never be 1.147 + * null. 1.148 + */ 1.149 + public static Set<String> getEnginesToSelect(SharedPreferences syncPrefs) { 1.150 + Set<String> engines = getEnginesFromPrefs(syncPrefs); 1.151 + Map<String, Boolean> engineSelections = SyncConfiguration.getUserSelectedEngines(syncPrefs); 1.152 + if (engineSelections != null) { 1.153 + for (Entry<String, Boolean> pair : engineSelections.entrySet()) { 1.154 + if (pair.getValue()) { 1.155 + engines.add(pair.getKey()); 1.156 + } else { 1.157 + engines.remove(pair.getKey()); 1.158 + } 1.159 + } 1.160 + } 1.161 + return engines; 1.162 + } 1.163 + 1.164 + public void setSelectionsInArray(Set<String> selected, boolean[] array) { 1.165 + for (int i = 0; i < _collectionsNames.length; i++) { 1.166 + array[i] = selected.contains(_collectionsNames[i]); 1.167 + } 1.168 + } 1.169 + 1.170 + @Override 1.171 + public void onClick(DialogInterface dialog, int which) { 1.172 + if (which == DialogInterface.BUTTON_POSITIVE) { 1.173 + Logger.debug(LOG_TAG, "Saving selected engines."); 1.174 + saveSelections(); 1.175 + setResult(RESULT_OK); 1.176 + Toast.makeText(this, R.string.sync_notification_savedprefs, Toast.LENGTH_SHORT).show(); 1.177 + } else { 1.178 + setResult(RESULT_CANCELED); 1.179 + } 1.180 + finish(); 1.181 + } 1.182 + 1.183 + @Override 1.184 + public void onClick(DialogInterface dialog, int which, boolean isChecked) { 1.185 + // Display multi-selection clicks in UI. 1.186 + _selections[which] = isChecked; 1.187 + ListView selectionsList = ((AlertDialog) dialog).getListView(); 1.188 + selectionsList.setItemChecked(which, isChecked); 1.189 + } 1.190 + 1.191 + /** 1.192 + * Persists engine selection state to SharedPreferences if it has changed. 1.193 + * 1.194 + * @return true if changed, false otherwise. 1.195 + */ 1.196 + private void saveSelections() { 1.197 + boolean[] origSelections = new boolean[_options.length]; 1.198 + setSelectionsInArray(getEnginesFromPrefs(accountPrefs), origSelections); 1.199 + 1.200 + Map<String, Boolean> engineSelections = new HashMap<String, Boolean>(); 1.201 + for (int i = 0; i < _selections.length; i++) { 1.202 + if (_selections[i] != origSelections[i]) { 1.203 + engineSelections.put(_collectionsNames[i], _selections[i]); 1.204 + } 1.205 + } 1.206 + 1.207 + // No GlobalSession.config, so store directly to prefs. 1.208 + SyncConfiguration.storeSelectedEnginesToPrefs(accountPrefs, engineSelections); 1.209 + 1.210 + // Request immediate sync. 1.211 + SyncAdapter.requestImmediateSync(account, null); 1.212 + } 1.213 +}