|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 package org.mozilla.gecko.sync.config.activities; |
|
6 |
|
7 import java.util.HashMap; |
|
8 import java.util.Map; |
|
9 import java.util.Map.Entry; |
|
10 import java.util.Set; |
|
11 |
|
12 import org.mozilla.gecko.R; |
|
13 import org.mozilla.gecko.background.common.log.Logger; |
|
14 import org.mozilla.gecko.sync.SyncConfiguration; |
|
15 import org.mozilla.gecko.sync.ThreadPool; |
|
16 import org.mozilla.gecko.sync.setup.SyncAccounts; |
|
17 import org.mozilla.gecko.sync.syncadapter.SyncAdapter; |
|
18 |
|
19 import android.accounts.Account; |
|
20 import android.accounts.AccountManager; |
|
21 import android.app.Activity; |
|
22 import android.app.AlertDialog; |
|
23 import android.content.Context; |
|
24 import android.content.DialogInterface; |
|
25 import android.content.DialogInterface.OnDismissListener; |
|
26 import android.content.SharedPreferences; |
|
27 import android.os.Bundle; |
|
28 import android.widget.ListView; |
|
29 import android.widget.Toast; |
|
30 |
|
31 /** |
|
32 * Provides a user-facing interface for selecting engines to sync. This activity |
|
33 * can be launched from the Sync Settings preferences screen, and will save the |
|
34 * selected engines to the |
|
35 * <code>SyncConfiguration.PREF_USER_SELECTED_ENGINES_TO_SYNC</code> pref. |
|
36 * |
|
37 * On launch, it displays the engines stored in the saved pref if it exists, or |
|
38 * <code>SyncConfiguration.enabledEngineNames()</code> if it doesn't, defaulting |
|
39 * to <code>SyncConfiguration.validEngineNames()</code> if neither exists. |
|
40 * |
|
41 * During a sync, the |
|
42 * <code>SyncConfiguration.PREF_USER_SELECTED_ENGINES_TO_SYNC</code> pref will |
|
43 * be cleared after the engine changes are applied to meta/global. |
|
44 */ |
|
45 |
|
46 public class SelectEnginesActivity extends Activity implements |
|
47 DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener { |
|
48 public final static String LOG_TAG = "SelectEnginesAct"; |
|
49 |
|
50 protected AccountManager mAccountManager; |
|
51 protected Context mContext; |
|
52 |
|
53 // Collections names corresponding to displayed (localized) engine options. |
|
54 final String[] _collectionsNames = new String[] { |
|
55 "bookmarks", |
|
56 "passwords", |
|
57 "history", |
|
58 "tabs" |
|
59 }; |
|
60 |
|
61 // Engine names localized for display in Sync Settings. |
|
62 protected String[] _options; |
|
63 // Selection state of engines corresponding to _options array. |
|
64 final boolean[] _selections = new boolean[_collectionsNames.length]; |
|
65 protected Account account; |
|
66 protected SharedPreferences accountPrefs; |
|
67 |
|
68 @Override |
|
69 public void onCreate(Bundle savedInstanceState) { |
|
70 super.onCreate(savedInstanceState); |
|
71 mContext = getApplicationContext(); |
|
72 mAccountManager = AccountManager.get(mContext); |
|
73 _options = new String[] { |
|
74 getString(R.string.sync_configure_engines_title_bookmarks), |
|
75 getString(R.string.sync_configure_engines_title_passwords), |
|
76 getString(R.string.sync_configure_engines_title_history), |
|
77 getString(R.string.sync_configure_engines_title_tabs) }; |
|
78 |
|
79 // Fetch account prefs for configuring engines. |
|
80 ThreadPool.run(new Runnable() { |
|
81 @Override |
|
82 public void run() { |
|
83 Account[] accounts = SyncAccounts.syncAccounts(mContext); |
|
84 if (accounts.length == 0) { |
|
85 Logger.error(LOG_TAG, "Failed to get account!"); |
|
86 finish(); |
|
87 return; |
|
88 } else { |
|
89 // Only supports one account per type. |
|
90 account = accounts[0]; |
|
91 try { |
|
92 if (accountPrefs == null) { |
|
93 accountPrefs = SyncAccounts.blockingPrefsFromDefaultProfileV0(mContext, mAccountManager, account); |
|
94 } |
|
95 } catch (Exception e) { |
|
96 Logger.error(LOG_TAG, "Failed to get sync account info or shared preferences.", e); |
|
97 finish(); |
|
98 } |
|
99 setSelectionsInArray(getEnginesToSelect(accountPrefs), _selections); |
|
100 } |
|
101 } |
|
102 }); |
|
103 } |
|
104 |
|
105 @Override |
|
106 public void onResume() { |
|
107 super.onResume(); |
|
108 if (accountPrefs != null) { |
|
109 setSelectionsInArray(getEnginesToSelect(accountPrefs), _selections); |
|
110 } |
|
111 AlertDialog dialog = new AlertDialog.Builder(this) |
|
112 .setTitle(R.string.sync_configure_engines_sync_my_title) |
|
113 .setMultiChoiceItems(_options, _selections, this) |
|
114 .setIcon(R.drawable.icon).setPositiveButton(android.R.string.ok, this) |
|
115 .setNegativeButton(android.R.string.cancel, this).create(); |
|
116 |
|
117 dialog.setOnDismissListener(new OnDismissListener() { |
|
118 @Override |
|
119 public void onDismiss(DialogInterface dialog) { |
|
120 finish(); |
|
121 } |
|
122 }); |
|
123 |
|
124 dialog.show(); |
|
125 } |
|
126 |
|
127 private static Set<String> getEnginesFromPrefs(SharedPreferences syncPrefs) { |
|
128 Set<String> engines = SyncConfiguration.getEnabledEngineNames(syncPrefs); |
|
129 if (engines == null) { |
|
130 engines = SyncConfiguration.validEngineNames(); |
|
131 } |
|
132 return engines; |
|
133 } |
|
134 |
|
135 /** |
|
136 * Fetches the engine names that should be displayed as selected for syncing. |
|
137 * Check first for selected engines set by this activity, then the enabled |
|
138 * engines, and finally default to the set of valid engine names for Android |
|
139 * Sync if neither exists. |
|
140 * |
|
141 * @param syncPrefs |
|
142 * <code>SharedPreferences</code> of Account being modified. |
|
143 * @return Set<String> of engine names to display as selected. Should never be |
|
144 * null. |
|
145 */ |
|
146 public static Set<String> getEnginesToSelect(SharedPreferences syncPrefs) { |
|
147 Set<String> engines = getEnginesFromPrefs(syncPrefs); |
|
148 Map<String, Boolean> engineSelections = SyncConfiguration.getUserSelectedEngines(syncPrefs); |
|
149 if (engineSelections != null) { |
|
150 for (Entry<String, Boolean> pair : engineSelections.entrySet()) { |
|
151 if (pair.getValue()) { |
|
152 engines.add(pair.getKey()); |
|
153 } else { |
|
154 engines.remove(pair.getKey()); |
|
155 } |
|
156 } |
|
157 } |
|
158 return engines; |
|
159 } |
|
160 |
|
161 public void setSelectionsInArray(Set<String> selected, boolean[] array) { |
|
162 for (int i = 0; i < _collectionsNames.length; i++) { |
|
163 array[i] = selected.contains(_collectionsNames[i]); |
|
164 } |
|
165 } |
|
166 |
|
167 @Override |
|
168 public void onClick(DialogInterface dialog, int which) { |
|
169 if (which == DialogInterface.BUTTON_POSITIVE) { |
|
170 Logger.debug(LOG_TAG, "Saving selected engines."); |
|
171 saveSelections(); |
|
172 setResult(RESULT_OK); |
|
173 Toast.makeText(this, R.string.sync_notification_savedprefs, Toast.LENGTH_SHORT).show(); |
|
174 } else { |
|
175 setResult(RESULT_CANCELED); |
|
176 } |
|
177 finish(); |
|
178 } |
|
179 |
|
180 @Override |
|
181 public void onClick(DialogInterface dialog, int which, boolean isChecked) { |
|
182 // Display multi-selection clicks in UI. |
|
183 _selections[which] = isChecked; |
|
184 ListView selectionsList = ((AlertDialog) dialog).getListView(); |
|
185 selectionsList.setItemChecked(which, isChecked); |
|
186 } |
|
187 |
|
188 /** |
|
189 * Persists engine selection state to SharedPreferences if it has changed. |
|
190 * |
|
191 * @return true if changed, false otherwise. |
|
192 */ |
|
193 private void saveSelections() { |
|
194 boolean[] origSelections = new boolean[_options.length]; |
|
195 setSelectionsInArray(getEnginesFromPrefs(accountPrefs), origSelections); |
|
196 |
|
197 Map<String, Boolean> engineSelections = new HashMap<String, Boolean>(); |
|
198 for (int i = 0; i < _selections.length; i++) { |
|
199 if (_selections[i] != origSelections[i]) { |
|
200 engineSelections.put(_collectionsNames[i], _selections[i]); |
|
201 } |
|
202 } |
|
203 |
|
204 // No GlobalSession.config, so store directly to prefs. |
|
205 SyncConfiguration.storeSelectedEnginesToPrefs(accountPrefs, engineSelections); |
|
206 |
|
207 // Request immediate sync. |
|
208 SyncAdapter.requestImmediateSync(account, null); |
|
209 } |
|
210 } |