summaryrefslogtreecommitdiffstats
path: root/mobile/android/base/java/org/mozilla/gecko/preferences
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-04-23 15:32:23 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-04-23 15:32:23 -0400
commitabe80cc31d5a40ebed743085011fbcda0c1a9a10 (patch)
treefb3762f06b84745b182af281abb107b95a9fcf01 /mobile/android/base/java/org/mozilla/gecko/preferences
parent63295d0087eb58a6eb34cad324c4c53d1b220491 (diff)
downloadUXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.gz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.lz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.tar.xz
UXP-abe80cc31d5a40ebed743085011fbcda0c1a9a10.zip
Issue #1053 - Drop support Android and remove Fennec - Part 1a: Remove mobile/android
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/preferences')
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/AlignRightLinkPreference.java24
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImport.java230
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImportPreference.java112
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/AppCompatPreferenceActivity.java115
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/ClearOnShutdownPref.java37
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/CustomCheckBoxPreference.java44
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/CustomListCategory.java72
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/CustomListPreference.java182
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/DistroSharedPrefsImport.java61
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/FontSizePreference.java192
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java296
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java1514
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/LinkPreference.java35
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/ListCheckboxPreference.java58
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java316
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/ModifiableHintPreference.java67
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java271
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/MultiPrefMultiChoicePreference.java116
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreference.java255
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreferenceCategory.java261
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/PrivateDataPreference.java67
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java183
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/SearchPreferenceCategory.java145
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/SetHomepagePreference.java124
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/preferences/SyncPreference.java103
25 files changed, 0 insertions, 4880 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/AlignRightLinkPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/AlignRightLinkPreference.java
deleted file mode 100644
index b68a018f2..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/AlignRightLinkPreference.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-class AlignRightLinkPreference extends LinkPreference {
-
- public AlignRightLinkPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setLayoutResource(R.layout.preference_rightalign_icon);
- }
-
- public AlignRightLinkPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setLayoutResource(R.layout.preference_rightalign_icon);
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImport.java b/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImport.java
deleted file mode 100644
index bb71ce78b..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImport.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.ContentValues;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Build;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.db.BrowserContract;
-import org.mozilla.gecko.db.BrowserContract.Bookmarks;
-import org.mozilla.gecko.db.LocalBrowserDB;
-import org.mozilla.gecko.icons.IconResponse;
-import org.mozilla.gecko.icons.IconsHelper;
-import org.mozilla.gecko.icons.storage.DiskStorage;
-
-import android.content.ContentProviderOperation;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.OperationApplicationException;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.BaseColumns;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-public class AndroidImport implements Runnable {
- /**
- * The Android M SDK removed several fields and methods from android.provider.Browser. This class is used as a
- * replacement to support building with the new SDK but at the same time still use these fields on lower Android
- * versions.
- */
- private static class LegacyBrowserProvider {
- public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
-
- // Incomplete: This are just the fields we currently use in our code base
- public static class BookmarkColumns implements BaseColumns {
- public static final String URL = "url";
- public static final String VISITS = "visits";
- public static final String DATE = "date";
- public static final String BOOKMARK = "bookmark";
- public static final String TITLE = "title";
- public static final String CREATED = "created";
- public static final String FAVICON = "favicon";
- }
- }
-
- public static final Uri SAMSUNG_BOOKMARKS_URI = Uri.parse("content://com.sec.android.app.sbrowser.browser/bookmarks");
- public static final Uri SAMSUNG_HISTORY_URI = Uri.parse("content://com.sec.android.app.sbrowser.browser/history");
- public static final String SAMSUNG_MANUFACTURER = "samsung";
-
- private static final String LOGTAG = "AndroidImport";
- private final Context mContext;
- private final Runnable mOnDoneRunnable;
- private final ArrayList<ContentProviderOperation> mOperations;
- private final ContentResolver mCr;
- private final LocalBrowserDB mDB;
- private final boolean mImportBookmarks;
- private final boolean mImportHistory;
-
- public AndroidImport(Context context, Runnable onDoneRunnable,
- boolean doBookmarks, boolean doHistory) {
- mContext = context;
- mOnDoneRunnable = onDoneRunnable;
- mOperations = new ArrayList<ContentProviderOperation>();
- mCr = mContext.getContentResolver();
- mDB = new LocalBrowserDB(GeckoProfile.get(context).getName());
- mImportBookmarks = doBookmarks;
- mImportHistory = doHistory;
- }
-
- public void mergeBookmarks() {
- Cursor cursor = null;
- try {
- cursor = query(LegacyBrowserProvider.BOOKMARKS_URI,
- SAMSUNG_BOOKMARKS_URI,
- LegacyBrowserProvider.BookmarkColumns.BOOKMARK + " = 1");
-
- if (cursor != null) {
- final int faviconCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.FAVICON);
- final int titleCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.TITLE);
- final int urlCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.URL);
- // http://code.google.com/p/android/issues/detail?id=17969
- final int createCol = cursor.getColumnIndex(LegacyBrowserProvider.BookmarkColumns.CREATED);
-
- cursor.moveToFirst();
- while (!cursor.isAfterLast()) {
- String url = cursor.getString(urlCol);
- String title = cursor.getString(titleCol);
- long created;
- if (createCol >= 0) {
- created = cursor.getLong(createCol);
- } else {
- created = System.currentTimeMillis();
- }
- // Need to set it to the current time so Sync picks it up.
- long modified = System.currentTimeMillis();
- byte[] data = cursor.getBlob(faviconCol);
- mDB.updateBookmarkInBatch(mCr, mOperations,
- url, title, null, -1,
- created, modified,
- BrowserContract.Bookmarks.DEFAULT_POSITION,
- null, Bookmarks.TYPE_BOOKMARK);
- if (data != null) {
- storeBitmap(data, url);
- }
- cursor.moveToNext();
- }
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
-
- flushBatchOperations();
- }
-
- public void mergeHistory() {
- ArrayList<ContentValues> visitsToSynthesize = new ArrayList<>();
- Cursor cursor = null;
- try {
- cursor = query (LegacyBrowserProvider.BOOKMARKS_URI,
- SAMSUNG_HISTORY_URI,
- LegacyBrowserProvider.BookmarkColumns.BOOKMARK + " = 0 AND " +
- LegacyBrowserProvider.BookmarkColumns.VISITS + " > 0");
-
- if (cursor != null) {
- final int dateCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.DATE);
- final int faviconCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.FAVICON);
- final int titleCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.TITLE);
- final int urlCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.URL);
- final int visitsCol = cursor.getColumnIndexOrThrow(LegacyBrowserProvider.BookmarkColumns.VISITS);
-
- cursor.moveToFirst();
- while (!cursor.isAfterLast()) {
- String url = cursor.getString(urlCol);
- String title = cursor.getString(titleCol);
- long date = cursor.getLong(dateCol);
- int visits = cursor.getInt(visitsCol);
- byte[] data = cursor.getBlob(faviconCol);
- mDB.updateHistoryInBatch(mCr, mOperations, url, title, date, visits);
- if (data != null) {
- storeBitmap(data, url);
- }
- ContentValues visitData = new ContentValues();
- visitData.put(LocalBrowserDB.HISTORY_VISITS_DATE, date);
- visitData.put(LocalBrowserDB.HISTORY_VISITS_URL, url);
- visitData.put(LocalBrowserDB.HISTORY_VISITS_COUNT, visits);
- visitsToSynthesize.add(visitData);
- cursor.moveToNext();
- }
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
-
- flushBatchOperations();
-
- // Now that we have flushed history records, we need to synthesize individual visits. We have
- // gathered information about all of the visits we need to synthesize into visitsForSynthesis.
- mDB.insertVisitsFromImportHistoryInBatch(mCr, mOperations, visitsToSynthesize);
-
- flushBatchOperations();
- }
-
- private void storeBitmap(byte[] data, String url) {
- if (TextUtils.isEmpty(url) || data == null) {
- return;
- }
-
- final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- if (bitmap == null) {
- return;
- }
-
- final String iconUrl = IconsHelper.guessDefaultFaviconURL(url);
- if (iconUrl == null) {
- return;
- }
-
- final DiskStorage storage = DiskStorage.get(mContext);
-
- storage.putIcon(url, bitmap);
- storage.putMapping(url, iconUrl);
- }
-
- protected Cursor query(Uri mainUri, Uri fallbackUri, String condition) {
- final Cursor cursor = mCr.query(mainUri, null, condition, null, null);
- if (Build.MANUFACTURER.equals(SAMSUNG_MANUFACTURER) && (cursor == null || cursor.getCount() == 0)) {
- if (cursor != null) {
- cursor.close();
- }
- return mCr.query(fallbackUri, null, null, null, null);
- }
- return cursor;
- }
-
- protected void flushBatchOperations() {
- Log.d(LOGTAG, "Flushing " + mOperations.size() + " DB operations");
- try {
- // We don't really care for the results, this is best-effort.
- mCr.applyBatch(BrowserContract.AUTHORITY, mOperations);
- } catch (RemoteException e) {
- Log.e(LOGTAG, "Remote exception while updating db: ", e);
- } catch (OperationApplicationException e) {
- // Bug 716729 means this happens even in normal circumstances
- Log.d(LOGTAG, "Error while applying database updates: ", e);
- }
- mOperations.clear();
- }
-
- @Override
- public void run() {
- if (mImportBookmarks) {
- mergeBookmarks();
- }
- if (mImportHistory) {
- mergeHistory();
- }
-
- mOnDoneRunnable.run();
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImportPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImportPreference.java
deleted file mode 100644
index 0f1d3ec3f..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/AndroidImportPreference.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.restrictions.Restrictable;
-import org.mozilla.gecko.restrictions.Restrictions;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import java.util.Set;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.preference.Preference;
-import android.util.AttributeSet;
-import android.util.Log;
-
-class AndroidImportPreference extends MultiPrefMultiChoicePreference {
- private static final String LOGTAG = "AndroidImport";
- public static final String PREF_KEY = "android.not_a_preference.import_android";
- private static final String PREF_KEY_PREFIX = "import_android.data.";
- private final Context mContext;
-
- public static class Handler implements GeckoPreferences.PrefHandler {
- public boolean setupPref(Context context, Preference pref) {
- // Feature disabled on devices running Android M+ (Bug 1183559)
- return Versions.preMarshmallow && Restrictions.isAllowed(context, Restrictable.IMPORT_SETTINGS);
- }
-
- public void onChange(Context context, Preference pref, Object newValue) { }
- }
-
- public AndroidImportPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (!positiveResult)
- return;
-
- boolean bookmarksChecked = false;
- boolean historyChecked = false;
-
- Set<String> values = getValues();
-
- for (String value : values) {
- // Import checkbox values are stored in Android prefs to
- // remember their check states. The key names are import_android.data.X
- String key = value.substring(PREF_KEY_PREFIX.length());
- if ("bookmarks".equals(key)) {
- bookmarksChecked = true;
- } else if ("history".equals(key)) {
- historyChecked = true;
- }
- }
-
- runImport(bookmarksChecked, historyChecked);
- }
-
- protected void runImport(final boolean doBookmarks, final boolean doHistory) {
- Log.i(LOGTAG, "Importing Android history/bookmarks");
- if (!doBookmarks && !doHistory) {
- return;
- }
-
- final String dialogTitle;
- if (doBookmarks && doHistory) {
- dialogTitle = mContext.getString(R.string.bookmarkhistory_import_both);
- } else if (doBookmarks) {
- dialogTitle = mContext.getString(R.string.bookmarkhistory_import_bookmarks);
- } else {
- dialogTitle = mContext.getString(R.string.bookmarkhistory_import_history);
- }
-
- final ProgressDialog dialog =
- ProgressDialog.show(mContext,
- dialogTitle,
- mContext.getString(R.string.bookmarkhistory_import_wait),
- true);
-
- final Runnable stopCallback = new Runnable() {
- @Override
- public void run() {
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- dialog.dismiss();
- }
- });
- }
- };
-
- ThreadUtils.postToBackgroundThread(
- // Constructing AndroidImport may need finding the profile,
- // which hits disk, so it needs to go into a Runnable too.
- new Runnable() {
- @Override
- public void run() {
- new AndroidImport(mContext, stopCallback, doBookmarks, doHistory).run();
- }
- }
- );
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/AppCompatPreferenceActivity.java b/mobile/android/base/java/org/mozilla/gecko/preferences/AppCompatPreferenceActivity.java
deleted file mode 100644
index fb4a8f751..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/AppCompatPreferenceActivity.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.mozilla.gecko.preferences;
-
-
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.Nullable;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatDelegate;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
- * to be used with AppCompat.
- *
- * This technique can be used with an {@link android.app.Activity} class, not just
- * {@link android.preference.PreferenceActivity}.
- *
- * This class was directly imported (without any modifications) from Android SDK examples, at:
- * https://android.googlesource.com/platform/development/+/master/samples/Support7Demos/src/com/example/android/supportv7/app/AppCompatPreferenceActivity.java
- */
-public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
- private AppCompatDelegate mDelegate;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- getDelegate().installViewFactory();
- getDelegate().onCreate(savedInstanceState);
- super.onCreate(savedInstanceState);
- }
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- getDelegate().onPostCreate(savedInstanceState);
- }
- public ActionBar getSupportActionBar() {
- return getDelegate().getSupportActionBar();
- }
- public void setSupportActionBar(@Nullable Toolbar toolbar) {
- getDelegate().setSupportActionBar(toolbar);
- }
- @Override
- public MenuInflater getMenuInflater() {
- return getDelegate().getMenuInflater();
- }
- @Override
- public void setContentView(@LayoutRes int layoutResID) {
- getDelegate().setContentView(layoutResID);
- }
- @Override
- public void setContentView(View view) {
- getDelegate().setContentView(view);
- }
- @Override
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().setContentView(view, params);
- }
- @Override
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().addContentView(view, params);
- }
- @Override
- protected void onPostResume() {
- super.onPostResume();
- getDelegate().onPostResume();
- }
- @Override
- protected void onTitleChanged(CharSequence title, int color) {
- super.onTitleChanged(title, color);
- getDelegate().setTitle(title);
- }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- getDelegate().onConfigurationChanged(newConfig);
- }
- @Override
- protected void onStop() {
- super.onStop();
- getDelegate().onStop();
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- getDelegate().onDestroy();
- }
- public void invalidateOptionsMenu() {
- getDelegate().invalidateOptionsMenu();
- }
- private AppCompatDelegate getDelegate() {
- if (mDelegate == null) {
- mDelegate = AppCompatDelegate.create(this, null);
- }
- return mDelegate;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/ClearOnShutdownPref.java b/mobile/android/base/java/org/mozilla/gecko/preferences/ClearOnShutdownPref.java
deleted file mode 100644
index 5218cd06d..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/ClearOnShutdownPref.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.util.PrefUtils;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.Preference;
-
-public class ClearOnShutdownPref implements GeckoPreferences.PrefHandler {
- public static final String PREF = GeckoPreferences.NON_PREF_PREFIX + "history.clear_on_exit";
-
- @Override
- public boolean setupPref(Context context, Preference pref) {
- // The pref is initialized asynchronously. Read the pref explicitly
- // here to make sure we have the data.
- final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
- final Set<String> clearItems = PrefUtils.getStringSet(prefs, PREF, new HashSet<String>());
- ((ListCheckboxPreference) pref).setChecked(clearItems.size() > 0);
- return true;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void onChange(Context context, Preference pref, Object newValue) {
- final Set<String> vals = (Set<String>) newValue;
- ((ListCheckboxPreference) pref).setChecked(vals.size() > 0);
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomCheckBoxPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/CustomCheckBoxPreference.java
deleted file mode 100644
index 2934ca88e..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomCheckBoxPreference.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.Context;
-import android.preference.CheckBoxPreference;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.TextView;
-
-/**
- * Represents a Checkbox element in a preference menu.
- * The title of the Checkbox can be larger than the view.
- * In this case, it will be displayed in 2 or more lines.
- * The default behavior of the class CheckBoxPreference
- * doesn't wrap the title.
- */
-
-public class CustomCheckBoxPreference extends CheckBoxPreference {
-
- public CustomCheckBoxPreference(Context context) {
- super(context);
- }
-
- public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public CustomCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
- final TextView title = (TextView) view.findViewById(android.R.id.title);
- if (title != null) {
- title.setSingleLine(false);
- title.setEllipsize(null);
- }
- }
-
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListCategory.java b/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListCategory.java
deleted file mode 100644
index ee5a46bef..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListCategory.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.Context;
-import android.preference.PreferenceCategory;
-import android.util.AttributeSet;
-
-public abstract class CustomListCategory extends PreferenceCategory {
- protected CustomListPreference mDefaultReference;
-
- public CustomListCategory(Context context) {
- super(context);
- }
-
- public CustomListCategory(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public CustomListCategory(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onAttachedToActivity() {
- super.onAttachedToActivity();
-
- setOrderingAsAdded(true);
- }
-
- /**
- * Set the default to some available list item. Used if the current default is removed or
- * disabled.
- */
- protected void setFallbackDefault() {
- if (getPreferenceCount() > 0) {
- CustomListPreference aItem = (CustomListPreference) getPreference(0);
- setDefault(aItem);
- }
- }
-
- /**
- * Removes the given item from the set of available list items.
- * This only updates the UI, so callers are responsible for persisting any state.
- *
- * @param item The given item to remove.
- */
- public void uninstall(CustomListPreference item) {
- removePreference(item);
- if (item == mDefaultReference) {
- // If the default is being deleted, set a new default.
- setFallbackDefault();
- }
- }
-
- /**
- * Sets the given item as the current default.
- * This only updates the UI, so callers are responsible for persisting any state.
- *
- * @param item The intended new default.
- */
- public void setDefault(CustomListPreference item) {
- if (mDefaultReference != null) {
- mDefaultReference.setIsDefault(false);
- }
-
- item.setIsDefault(true);
- mDefaultReference = item;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListPreference.java
deleted file mode 100644
index 8b7e0e7b3..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/CustomListPreference.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.preference.Preference;
-import android.view.View;
-import android.widget.TextView;
-
-/**
- * Represents an element in a <code>CustomListCategory</code> preference menu.
- * This preference con display a dialog when clicked, and also supports
- * being set as a default item within the preference list category.
- */
-
-public abstract class CustomListPreference extends Preference implements View.OnLongClickListener {
- protected String LOGTAG = "CustomListPreference";
-
- // Indices of the buttons of the Dialog.
- public static final int INDEX_SET_DEFAULT_BUTTON = 0;
-
- // Dialog item labels.
- private String[] mDialogItems;
-
- // Dialog displayed when this element is tapped.
- protected AlertDialog mDialog;
-
- // Cache label to avoid repeated use of the resource system.
- protected final String LABEL_IS_DEFAULT;
- protected final String LABEL_SET_AS_DEFAULT;
- protected final String LABEL_REMOVE;
-
- protected boolean mIsDefault;
-
- // Enclosing parent category that contains this preference.
- protected final CustomListCategory mParentCategory;
-
- /**
- * Create a preference object to represent a list preference that is attached to
- * a category.
- *
- * @param context The activity context we operate under.
- * @param parentCategory The PreferenceCategory this object exists within.
- */
- public CustomListPreference(Context context, CustomListCategory parentCategory) {
- super(context);
-
- mParentCategory = parentCategory;
- setLayoutResource(getPreferenceLayoutResource());
-
- setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- CustomListPreference sPref = (CustomListPreference) preference;
- sPref.showDialog();
- return true;
- }
- });
-
- Resources res = getContext().getResources();
-
- // Fetch these strings now, instead of every time we ever want to relabel a button.
- LABEL_IS_DEFAULT = res.getString(R.string.pref_default);
- LABEL_SET_AS_DEFAULT = res.getString(R.string.pref_dialog_set_default);
- LABEL_REMOVE = res.getString(R.string.pref_dialog_remove);
- }
-
- /**
- * Returns the Android resource id for the layout.
- */
- protected abstract int getPreferenceLayoutResource();
-
- /**
- * Set whether this object's UI should display this as the default item.
- * Note: This must be called from the UI thread because it touches the view hierarchy.
- *
- * To ensure proper ordering, this method should only be called after this Preference
- * is added to the PreferenceCategory.
- *
- * @param isDefault Flag indicating if this represents the default list item.
- */
- public void setIsDefault(boolean isDefault) {
- mIsDefault = isDefault;
- if (isDefault) {
- setOrder(0);
- setSummary(LABEL_IS_DEFAULT);
- } else {
- setOrder(1);
- setSummary("");
- }
- }
-
- private String[] getCachedDialogItems() {
- if (mDialogItems == null) {
- mDialogItems = createDialogItems();
- }
- return mDialogItems;
- }
-
- /**
- * Returns the strings to be displayed in the dialog.
- */
- abstract protected String[] createDialogItems();
-
- /**
- * Display a dialog for this preference, when the preference is clicked.
- */
- public void showDialog() {
- final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setTitle(getTitle().toString());
- builder.setItems(getCachedDialogItems(), new DialogInterface.OnClickListener() {
- // Forward relevant events to the container class for handling.
- @Override
- public void onClick(DialogInterface dialog, int indexClicked) {
- hideDialog();
- onDialogIndexClicked(indexClicked);
- }
- });
-
- configureDialogBuilder(builder);
-
- // We have to construct the dialog itself on the UI thread.
- mDialog = builder.create();
- mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
- // Called when the dialog is shown (so we're finally able to manipulate button enabledness).
- @Override
- public void onShow(DialogInterface dialog) {
- configureShownDialog();
- }
- });
- mDialog.show();
- }
-
- /**
- * (Optional) Configure the AlertDialog builder.
- */
- protected void configureDialogBuilder(AlertDialog.Builder builder) {
- return;
- }
-
- abstract protected void onDialogIndexClicked(int index);
-
- /**
- * Disables buttons in the shown AlertDialog as required. The button elements are not created
- * until after show is called, so this method has to be called from the onShowListener above.
- * @see this.showDialog
- */
- protected void configureShownDialog() {
- // If this is already the default list item, disable the button for setting this as the default.
- final TextView defaultButton = (TextView) mDialog.getListView().getChildAt(INDEX_SET_DEFAULT_BUTTON);
- if (mIsDefault) {
- defaultButton.setEnabled(false);
-
- // Failure to unregister this listener leads to tapping the button dismissing the dialog
- // without doing anything.
- defaultButton.setOnClickListener(null);
- }
- }
-
- /**
- * Hide the dialog we previously created, if any.
- */
- public void hideDialog() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- }
-
- @Override
- public boolean onLongClick(View view) {
- // Show the preference dialog on long-press.
- showDialog();
- return true;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/DistroSharedPrefsImport.java b/mobile/android/base/java/org/mozilla/gecko/preferences/DistroSharedPrefsImport.java
deleted file mode 100644
index 1e235640e..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/DistroSharedPrefsImport.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.distribution.Distribution;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.Iterator;
-
-public class DistroSharedPrefsImport {
-
- public static final String LOGTAG = DistroSharedPrefsImport.class.getSimpleName();
-
- public static void importPreferences(final Context context, final Distribution distribution) {
- if (distribution == null) {
- return;
- }
-
- final JSONObject preferences = distribution.getAndroidPreferences();
- if (preferences.length() == 0) {
- return;
- }
-
- final Iterator<?> keys = preferences.keys();
- final SharedPreferences.Editor sharedPreferences = GeckoSharedPrefs.forProfile(context).edit();
-
- while (keys.hasNext()) {
- final String key = (String) keys.next();
- final Object value;
- try {
- value = preferences.get(key);
- } catch (JSONException e) {
- Log.e(LOGTAG, "Unable to completely process Android Preferences JSON.", e);
- continue;
- }
-
- // We currently don't support Float preferences.
- if (value instanceof String) {
- sharedPreferences.putString(GeckoPreferences.NON_PREF_PREFIX + key, (String) value);
- } else if (value instanceof Boolean) {
- sharedPreferences.putBoolean(GeckoPreferences.NON_PREF_PREFIX + key, (boolean) value);
- } else if (value instanceof Integer) {
- sharedPreferences.putInt(GeckoPreferences.NON_PREF_PREFIX + key, (int) value);
- } else if (value instanceof Long) {
- sharedPreferences.putLong(GeckoPreferences.NON_PREF_PREFIX + key, (long) value);
- } else {
- Log.d(LOGTAG, "Unknown preference value type whilst importing android preferences from distro file.");
- }
- }
- sharedPreferences.apply();
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/FontSizePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/FontSizePreference.java
deleted file mode 100644
index c77c2cc23..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/FontSizePreference.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import java.util.HashMap;
-
-class FontSizePreference extends DialogPreference {
- private static final String LOGTAG = "FontSizePreference";
- private static final int TWIP_TO_PT_RATIO = 20; // 20 twip = 1 point.
- private static final int PREVIEW_FONT_SIZE_UNIT = TypedValue.COMPLEX_UNIT_PT;
- private static final int DEFAULT_FONT_INDEX = 2;
-
- private final Context mContext;
- /** Container for mPreviewFontView to allow for scrollable padding at the top of the view. */
- private ScrollView mScrollingContainer;
- private TextView mPreviewFontView;
- private Button mIncreaseFontButton;
- private Button mDecreaseFontButton;
-
- private final String[] mFontTwipValues;
- private final String[] mFontSizeNames; // Ex: "Small".
- /** Index into the above arrays for the saved preference value (from Gecko). */
- private int mSavedFontIndex = DEFAULT_FONT_INDEX;
- /** Index into the above arrays for the currently displayed font size (the preview). */
- private int mPreviewFontIndex = mSavedFontIndex;
- private final HashMap<String, Integer> mFontTwipToIndexMap;
-
- public FontSizePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
-
- final Resources res = mContext.getResources();
- mFontTwipValues = res.getStringArray(R.array.pref_font_size_values);
- mFontSizeNames = res.getStringArray(R.array.pref_font_size_entries);
- mFontTwipToIndexMap = new HashMap<String, Integer>();
- for (int i = 0; i < mFontTwipValues.length; ++i) {
- mFontTwipToIndexMap.put(mFontTwipValues[i], i);
- }
- }
-
- @Override
- protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
- final LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View dialogView = inflater.inflate(R.layout.font_size_preference, null);
- initInternalViews(dialogView);
- updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);
-
- builder.setTitle(null);
- builder.setView(dialogView);
- }
-
- /** Saves relevant views to instance variables and initializes their settings. */
- private void initInternalViews(View dialogView) {
- mScrollingContainer = (ScrollView) dialogView.findViewById(R.id.scrolling_container);
- // Background cannot be set in XML (see bug 783597 - TODO: Change this to XML when bug is fixed).
- mScrollingContainer.setBackgroundColor(Color.WHITE);
- mPreviewFontView = (TextView) dialogView.findViewById(R.id.preview);
-
- mDecreaseFontButton = (Button) dialogView.findViewById(R.id.decrease_preview_font_button);
- mIncreaseFontButton = (Button) dialogView.findViewById(R.id.increase_preview_font_button);
- setButtonState(mPreviewFontIndex);
- mDecreaseFontButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPreviewFontIndex = Math.max(mPreviewFontIndex - 1, 0);
- updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);
- mIncreaseFontButton.setEnabled(true);
- // If we reached the minimum index, disable the button.
- if (mPreviewFontIndex == 0) {
- mDecreaseFontButton.setEnabled(false);
- }
- }
- });
- mIncreaseFontButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPreviewFontIndex = Math.min(mPreviewFontIndex + 1, mFontTwipValues.length - 1);
- updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);
-
- mDecreaseFontButton.setEnabled(true);
- // If we reached the maximum index, disable the button.
- if (mPreviewFontIndex == mFontTwipValues.length - 1) {
- mIncreaseFontButton.setEnabled(false);
- }
- }
- });
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
- if (!positiveResult) {
- mPreviewFontIndex = mSavedFontIndex;
- return;
- }
- mSavedFontIndex = mPreviewFontIndex;
- final String twipVal = mFontTwipValues[mSavedFontIndex];
- final OnPreferenceChangeListener prefChangeListener = getOnPreferenceChangeListener();
- if (prefChangeListener == null) {
- Log.e(LOGTAG, "PreferenceChangeListener is null. FontSizePreference will not be saved to Gecko.");
- return;
- }
- prefChangeListener.onPreferenceChange(this, twipVal);
- }
-
- /**
- * Finds the index of the given twip value and sets it as the saved preference value. Also the
- * current preview text size to the given value. Does not update the mPreviewFontView text size.
- */
- protected void setSavedFontSize(String twip) {
- final Integer index = mFontTwipToIndexMap.get(twip);
- if (index != null) {
- mSavedFontIndex = index;
- mPreviewFontIndex = mSavedFontIndex;
- return;
- }
- resetSavedFontSizeToDefault();
- Log.e(LOGTAG, "setSavedFontSize: Given font size does not exist in twip values map. Reverted to default font size.");
- }
-
- /**
- * Updates the mPreviewFontView to the given text size, resets the container's scroll to the top
- * left, and invalidates the view. Does not update the font indices.
- */
- private void updatePreviewFontSize(String twip) {
- float pt = convertTwipStrToPT(twip);
- // Android will not render a font size of 0 pt but for Gecko, 0 twip turns off font
- // inflation. Thus we special case 0 twip to display a renderable font size.
- if (pt == 0) {
- // Android adds an inexplicable extra margin on the smallest font size so to get around
- // this, we reinflate the view.
- ViewGroup parentView = (ViewGroup) mScrollingContainer.getParent();
- parentView.removeAllViews();
- final LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View dialogView = inflater.inflate(R.layout.font_size_preference, parentView);
- initInternalViews(dialogView);
- mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, 1);
- } else {
- mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, pt);
- }
- mScrollingContainer.scrollTo(0, 0);
- }
-
- /**
- * Resets the font indices to the default value. Does not update the mPreviewFontView text size.
- */
- private void resetSavedFontSizeToDefault() {
- mSavedFontIndex = DEFAULT_FONT_INDEX;
- mPreviewFontIndex = mSavedFontIndex;
- }
-
- private void setButtonState(int index) {
- if (index == 0) {
- mDecreaseFontButton.setEnabled(false);
- } else if (index == mFontTwipValues.length - 1) {
- mIncreaseFontButton.setEnabled(false);
- }
- }
-
- /**
- * Returns the name of the font size (ex: "Small") at the currently saved preference value.
- */
- protected String getSavedFontSizeName() {
- return mFontSizeNames[mSavedFontIndex];
- }
-
- private float convertTwipStrToPT(String twip) {
- return Float.parseFloat(twip) / TWIP_TO_PT_RATIO;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java
deleted file mode 100644
index 6be9e6ea5..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferenceFragment.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import java.util.Locale;
-
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.BrowserLocaleManager;
-import org.mozilla.gecko.GeckoApplication;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.LocaleManager;
-import org.mozilla.gecko.PrefsHelper;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.fxa.AccountLoader;
-import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
-
-import android.accounts.Account;
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.Context;
-import android.content.Loader;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceScreen;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-
-import com.squareup.leakcanary.RefWatcher;
-
-/* A simple implementation of PreferenceFragment for large screen devices
- * This will strip category headers (so that they aren't shown to the user twice)
- * as well as initializing Gecko prefs when a fragment is shown.
-*/
-public class GeckoPreferenceFragment extends PreferenceFragment {
-
- public static final int ACCOUNT_LOADER_ID = 1;
- private AccountLoaderCallbacks accountLoaderCallbacks;
- private SyncPreference syncPreference;
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- Log.d(LOGTAG, "onConfigurationChanged: " + newConfig.locale);
-
- final Activity context = getActivity();
-
- final LocaleManager localeManager = BrowserLocaleManager.getInstance();
- final Locale changed = localeManager.onSystemConfigurationChanged(context, getResources(), newConfig, lastLocale);
- if (changed != null) {
- applyLocale(changed);
- }
- }
-
- private static final String LOGTAG = "GeckoPreferenceFragment";
- private PrefsHelper.PrefHandler mPrefsRequest;
- private Locale lastLocale = Locale.getDefault();
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Write prefs to our custom GeckoSharedPrefs file.
- getPreferenceManager().setSharedPreferencesName(GeckoSharedPrefs.APP_PREFS_NAME);
-
- int res = getResource();
- if (res == R.xml.preferences) {
- Telemetry.startUISession(TelemetryContract.Session.SETTINGS);
- } else {
- final String resourceName = getArguments().getString("resource");
- Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, Method.SETTINGS, resourceName);
- }
-
- // Display a menu for Search preferences.
- if (res == R.xml.preferences_search) {
- setHasOptionsMenu(true);
- }
-
- addPreferencesFromResource(res);
-
- PreferenceScreen screen = getPreferenceScreen();
- setPreferenceScreen(screen);
- mPrefsRequest = ((GeckoPreferences)getActivity()).setupPreferences(screen);
- syncPreference = (SyncPreference) findPreference(GeckoPreferences.PREFS_SYNC);
- }
-
- /**
- * Return the title to use for this preference fragment.
- *
- * We only return titles for the preference screens that are
- * launched directly, and thus might need to be redisplayed.
- *
- * This method sets the title that you see on non-multi-pane devices.
- */
- private String getTitle() {
- final int res = getResource();
- if (res == R.xml.preferences) {
- return getString(R.string.settings_title);
- }
-
- // We can launch this category from the Data Reporting notification.
- if (res == R.xml.preferences_privacy) {
- return getString(R.string.pref_category_privacy_short);
- }
-
- // We can launch this category from the the magnifying glass in the quick search bar.
- if (res == R.xml.preferences_search) {
- return getString(R.string.pref_category_search);
- }
-
- // Launched as action from content notifications.
- if (res == R.xml.preferences_notifications) {
- return getString(R.string.pref_category_notifications);
- }
-
- return null;
- }
-
- /**
- * Return the header id for this preference fragment. This allows
- * us to select the correct header when launching a preference
- * screen directly.
- *
- * We only return titles for the preference screens that are
- * launched directly.
- */
- private int getHeader() {
- final int res = getResource();
- if (res == R.xml.preferences) {
- return R.id.pref_header_general;
- }
-
- // We can launch this category from the Data Reporting notification.
- if (res == R.xml.preferences_privacy) {
- return R.id.pref_header_privacy;
- }
-
- // We can launch this category from the the magnifying glass in the quick search bar.
- if (res == R.xml.preferences_search) {
- return R.id.pref_header_search;
- }
-
- // Launched as action from content notifications.
- if (res == R.xml.preferences_notifications) {
- return R.id.pref_header_notifications;
- }
-
- return -1;
- }
-
- private void updateTitle() {
- final String newTitle = getTitle();
- if (newTitle == null) {
- Log.d(LOGTAG, "No new title to show.");
- return;
- }
-
- final GeckoPreferences activity = (GeckoPreferences) getActivity();
- if (activity.isMultiPane()) {
- // In a multi-pane activity, the title is "Settings", and the action
- // bar is along the top of the screen. We don't want to change those.
- activity.showBreadCrumbs(newTitle, newTitle);
- activity.switchToHeader(getHeader());
- return;
- }
-
- Log.v(LOGTAG, "Setting activity title to " + newTitle);
- activity.setTitle(newTitle);
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- accountLoaderCallbacks = new AccountLoaderCallbacks();
- getLoaderManager().initLoader(ACCOUNT_LOADER_ID, null, accountLoaderCallbacks);
- }
-
- @Override
- public void onResume() {
- // This is a little delicate. Ensure that you do nothing prior to
- // super.onResume that you wouldn't do in onCreate.
- applyLocale(Locale.getDefault());
- super.onResume();
-
- // Force reload as the account may have been deleted while the app was in background.
- getLoaderManager().restartLoader(ACCOUNT_LOADER_ID, null, accountLoaderCallbacks);
- }
-
- private void applyLocale(final Locale currentLocale) {
- final Context context = getActivity().getApplicationContext();
-
- BrowserLocaleManager.getInstance().updateConfiguration(context, currentLocale);
-
- if (!currentLocale.equals(lastLocale)) {
- // Locales differ. Let's redisplay.
- Log.d(LOGTAG, "Locale changed: " + currentLocale);
- this.lastLocale = currentLocale;
-
- // Rebuild the list to reflect the current locale.
- getPreferenceScreen().removeAll();
- addPreferencesFromResource(getResource());
- }
-
- // Fix the parent title regardless.
- updateTitle();
- }
-
- /*
- * Get the resource from Fragment arguments and return it.
- *
- * If no resource can be found, return the resource id of the default preference screen.
- */
- private int getResource() {
- int resid = 0;
-
- final String resourceName = getArguments().getString("resource");
- final Activity activity = getActivity();
-
- if (resourceName != null) {
- // Fetch resource id by resource name.
- final Resources resources = activity.getResources();
- final String packageName = activity.getPackageName();
- resid = resources.getIdentifier(resourceName, "xml", packageName);
- }
-
- if (resid == 0) {
- // The resource was invalid. Use the default resource.
- Log.e(LOGTAG, "Failed to find resource: " + resourceName + ". Displaying default settings.");
-
- boolean isMultiPane = ((GeckoPreferences) activity).isMultiPane();
- resid = isMultiPane ? R.xml.preferences_general_tablet : R.xml.preferences;
- }
-
- return resid;
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- inflater.inflate(R.menu.preferences_search_menu, menu);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mPrefsRequest != null) {
- PrefsHelper.removeObserver(mPrefsRequest);
- mPrefsRequest = null;
- }
-
- final int res = getResource();
- if (res == R.xml.preferences) {
- Telemetry.stopUISession(TelemetryContract.Session.SETTINGS);
- }
-
- GeckoApplication.watchReference(getActivity(), this);
- }
-
- private class AccountLoaderCallbacks implements LoaderManager.LoaderCallbacks<Account> {
- @Override
- public Loader<Account> onCreateLoader(int id, Bundle args) {
- return new AccountLoader(getActivity());
- }
-
- @Override
- public void onLoadFinished(Loader<Account> loader, Account account) {
- if (syncPreference == null) {
- return;
- }
-
- if (account == null) {
- syncPreference.update(null);
- return;
- }
-
- syncPreference.update(new AndroidFxAccount(getActivity(), account));
- }
-
- @Override
- public void onLoaderReset(Loader<Account> loader) {
- if (syncPreference != null) {
- syncPreference.update(null);
- }
- }
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
deleted file mode 100644
index aab5be2de..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java
+++ /dev/null
@@ -1,1514 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.json.JSONArray;
-import org.mozilla.gecko.AboutPages;
-import org.mozilla.gecko.AdjustConstants;
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.BrowserApp;
-import org.mozilla.gecko.BrowserLocaleManager;
-import org.mozilla.gecko.DataReportingNotification;
-import org.mozilla.gecko.DynamicToolbar;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoActivityStatus;
-import org.mozilla.gecko.GeckoApp;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoApplication;
-import org.mozilla.gecko.GeckoProfile;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.LocaleManager;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.PrefsHelper;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.SnackbarBuilder;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.activitystream.ActivityStream;
-import org.mozilla.gecko.background.common.GlobalConstants;
-import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
-import org.mozilla.gecko.feeds.FeedService;
-import org.mozilla.gecko.feeds.action.CheckForUpdatesAction;
-import org.mozilla.gecko.permissions.Permissions;
-import org.mozilla.gecko.restrictions.Restrictable;
-import org.mozilla.gecko.restrictions.Restrictions;
-import org.mozilla.gecko.tabqueue.TabQueueHelper;
-import org.mozilla.gecko.tabqueue.TabQueuePrompt;
-import org.mozilla.gecko.updater.UpdateService;
-import org.mozilla.gecko.updater.UpdateServiceHelper;
-import org.mozilla.gecko.util.ContextUtils;
-import org.mozilla.gecko.util.EventCallback;
-import org.mozilla.gecko.util.HardwareUtils;
-import org.mozilla.gecko.util.InputOptionsUtils;
-import org.mozilla.gecko.util.NativeEventListener;
-import org.mozilla.gecko.util.NativeJSObject;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.annotation.TargetApi;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.NotificationManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.res.Configuration;
-import android.Manifest;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.EditTextPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
-import android.preference.SwitchPreference;
-import android.preference.TwoStatePreference;
-import android.support.design.widget.Snackbar;
-import android.support.design.widget.TextInputLayout;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.app.ActionBar;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-public class GeckoPreferences
-extends AppCompatPreferenceActivity
-implements
-GeckoActivityStatus,
-NativeEventListener,
-OnPreferenceChangeListener,
-OnSharedPreferenceChangeListener
-{
- private static final String LOGTAG = "GeckoPreferences";
-
- // We have a white background, which makes transitions on
- // some devices look bad. Don't use transitions on those
- // devices.
- private static final boolean NO_TRANSITIONS = HardwareUtils.IS_KINDLE_DEVICE;
- private static final int NO_SUCH_ID = 0;
-
- public static final String NON_PREF_PREFIX = "android.not_a_preference.";
- public static final String INTENT_EXTRA_RESOURCES = "resource";
- public static final String PREFS_TRACKING_PROTECTION_PROMPT_SHOWN = NON_PREF_PREFIX + "trackingProtectionPromptShown";
- public static String PREFS_HEALTHREPORT_UPLOAD_ENABLED = NON_PREF_PREFIX + "healthreport.uploadEnabled";
- public static final String PREFS_SYNC = NON_PREF_PREFIX + "sync";
-
- private static boolean sIsCharEncodingEnabled;
- private boolean mInitialized;
- private PrefsHelper.PrefHandler mPrefsRequest;
- private List<Header> mHeaders;
-
- // These match keys in resources/xml*/preferences*.xml
- private static final String PREFS_SEARCH_RESTORE_DEFAULTS = NON_PREF_PREFIX + "search.restore_defaults";
- private static final String PREFS_DATA_REPORTING_PREFERENCES = NON_PREF_PREFIX + "datareporting.preferences";
- private static final String PREFS_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
- private static final String PREFS_CRASHREPORTER_ENABLED = "datareporting.crashreporter.submitEnabled";
- private static final String PREFS_MENU_CHAR_ENCODING = "browser.menu.showCharacterEncoding";
- private static final String PREFS_MP_ENABLED = "privacy.masterpassword.enabled";
- private static final String PREFS_UPDATER_AUTODOWNLOAD = "app.update.autodownload";
- private static final String PREFS_UPDATER_URL = "app.update.url.android";
- private static final String PREFS_GEO_REPORTING = NON_PREF_PREFIX + "app.geo.reportdata";
- private static final String PREFS_GEO_LEARN_MORE = NON_PREF_PREFIX + "geo.learn_more";
- private static final String PREFS_HEALTHREPORT_LINK = NON_PREF_PREFIX + "healthreport.link";
- private static final String PREFS_DEVTOOLS_REMOTE_USB_ENABLED = "devtools.remote.usb.enabled";
- private static final String PREFS_DEVTOOLS_REMOTE_WIFI_ENABLED = "devtools.remote.wifi.enabled";
- private static final String PREFS_DEVTOOLS_REMOTE_LINK = NON_PREF_PREFIX + "remote_debugging.link";
- private static final String PREFS_TRACKING_PROTECTION = "privacy.trackingprotection.state";
- private static final String PREFS_TRACKING_PROTECTION_PB = "privacy.trackingprotection.pbmode.enabled";
- private static final String PREFS_ZOOMED_VIEW_ENABLED = "ui.zoomedview.enabled";
- public static final String PREFS_VOICE_INPUT_ENABLED = NON_PREF_PREFIX + "voice_input_enabled";
- public static final String PREFS_QRCODE_ENABLED = NON_PREF_PREFIX + "qrcode_enabled";
- private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled";
- private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
- private static final String PREFS_CLEAR_PRIVATE_DATA = NON_PREF_PREFIX + "privacy.clear";
- private static final String PREFS_CLEAR_PRIVATE_DATA_EXIT = NON_PREF_PREFIX + "history.clear_on_exit";
- private static final String PREFS_SCREEN_ADVANCED = NON_PREF_PREFIX + "advanced_screen";
- public static final String PREFS_HOMEPAGE = NON_PREF_PREFIX + "homepage";
- public static final String PREFS_HOMEPAGE_PARTNER_COPY = GeckoPreferences.PREFS_HOMEPAGE + ".partner";
- public static final String PREFS_HISTORY_SAVED_SEARCH = NON_PREF_PREFIX + "search.search_history.enabled";
- private static final String PREFS_FAQ_LINK = NON_PREF_PREFIX + "faq.link";
- private static final String PREFS_FEEDBACK_LINK = NON_PREF_PREFIX + "feedback.link";
- public static final String PREFS_NOTIFICATIONS_CONTENT = NON_PREF_PREFIX + "notifications.content";
- public static final String PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE = NON_PREF_PREFIX + "notifications.content.learn_more";
- public static final String PREFS_NOTIFICATIONS_WHATS_NEW = NON_PREF_PREFIX + "notifications.whats_new";
- public static final String PREFS_APP_UPDATE_LAST_BUILD_ID = "app.update.last_build_id";
- public static final String PREFS_READ_PARTNER_CUSTOMIZATIONS_PROVIDER = NON_PREF_PREFIX + "distribution.read_partner_customizations_provider";
- public static final String PREFS_READ_PARTNER_BOOKMARKS_PROVIDER = NON_PREF_PREFIX + "distribution.read_partner_bookmarks_provider";
- public static final String PREFS_CUSTOM_TABS = NON_PREF_PREFIX + "customtabs";
- public static final String PREFS_ACTIVITY_STREAM = NON_PREF_PREFIX + "activitystream";
- public static final String PREFS_CATEGORY_EXPERIMENTAL_FEATURES = NON_PREF_PREFIX + "category_experimental";
-
- private static final String ACTION_STUMBLER_UPLOAD_PREF = "STUMBLER_PREF";
-
-
- // This isn't a Gecko pref, even if it looks like one.
- private static final String PREFS_BROWSER_LOCALE = "locale";
-
- public static final String PREFS_RESTORE_SESSION = NON_PREF_PREFIX + "restoreSession3";
- public static final String PREFS_RESTORE_SESSION_FROM_CRASH = "browser.sessionstore.resume_from_crash";
- public static final String PREFS_RESTORE_SESSION_MAX_CRASH_RESUMES = "browser.sessionstore.max_resumed_crashes";
- public static final String PREFS_TAB_QUEUE = NON_PREF_PREFIX + "tab_queue";
- public static final String PREFS_TAB_QUEUE_LAST_SITE = NON_PREF_PREFIX + "last_site";
- public static final String PREFS_TAB_QUEUE_LAST_TIME = NON_PREF_PREFIX + "last_time";
-
- private static final String PREFS_DYNAMIC_TOOLBAR = "browser.chrome.dynamictoolbar";
-
- // These values are chosen to be distinct from other Activity constants.
- private static final int REQUEST_CODE_PREF_SCREEN = 5;
- private static final int RESULT_CODE_EXIT_SETTINGS = 6;
-
- // Result code used when a locale preference changes.
- // Callers can recognize this code to refresh themselves to
- // accommodate a locale change.
- public static final int RESULT_CODE_LOCALE_DID_CHANGE = 7;
-
- private static final int REQUEST_CODE_TAB_QUEUE = 8;
-
- private final Map<String, PrefHandler> HANDLERS;
- {
- final HashMap<String, PrefHandler> tempHandlers = new HashMap<>(2);
- tempHandlers.put(ClearOnShutdownPref.PREF, new ClearOnShutdownPref());
- tempHandlers.put(AndroidImportPreference.PREF_KEY, new AndroidImportPreference.Handler());
- HANDLERS = Collections.unmodifiableMap(tempHandlers);
- }
-
- private SwitchPreference tabQueuePreference;
-
- /**
- * Track the last locale so we know whether to redisplay.
- */
- private Locale lastLocale = Locale.getDefault();
- private boolean localeSwitchingIsEnabled;
-
- private void startActivityForResultChoosingTransition(final Intent intent, final int requestCode) {
- startActivityForResult(intent, requestCode);
- if (NO_TRANSITIONS) {
- overridePendingTransition(0, 0);
- }
- }
-
- private void finishChoosingTransition() {
- finish();
- if (NO_TRANSITIONS) {
- overridePendingTransition(0, 0);
- }
- }
- private void updateActionBarTitle(int title) {
- final String newTitle = getString(title);
- if (newTitle != null) {
- Log.v(LOGTAG, "Setting action bar title to " + newTitle);
-
- setTitle(newTitle);
- }
- }
-
- /**
- * We only call this method for pre-HC versions of Android.
- */
- private void updateTitleForPrefsResource(int res) {
- // At present we only need to do this for non-leaf prefs views
- // and the locale switcher itself.
- int title = -1;
- if (res == R.xml.preferences) {
- title = R.string.settings_title;
- } else if (res == R.xml.preferences_locale) {
- title = R.string.pref_category_language;
- } else if (res == R.xml.preferences_vendor) {
- title = R.string.pref_category_vendor;
- } else if (res == R.xml.preferences_general) {
- title = R.string.pref_category_general;
- } else if (res == R.xml.preferences_search) {
- title = R.string.pref_category_search;
- }
- if (title != -1) {
- setTitle(title);
- }
- }
-
- private void onLocaleChanged(Locale newLocale) {
- Log.d(LOGTAG, "onLocaleChanged: " + newLocale);
-
- BrowserLocaleManager.getInstance().updateConfiguration(getApplicationContext(), newLocale);
- this.lastLocale = newLocale;
-
- if (isMultiPane()) {
- // This takes care of the left pane.
- invalidateHeaders();
-
- // Detach and reattach the current prefs pane so that it
- // reflects the new locale.
- final FragmentManager fragmentManager = getFragmentManager();
- int id = getResources().getIdentifier("android:id/prefs", null, null);
- final Fragment current = fragmentManager.findFragmentById(id);
- if (current != null) {
- fragmentManager.beginTransaction()
- .disallowAddToBackStack()
- .detach(current)
- .attach(current)
- .commitAllowingStateLoss();
- } else {
- Log.e(LOGTAG, "No prefs fragment to reattach!");
- }
-
- // Because Android just rebuilt the activity itself with the
- // old language, we need to update the top title and other
- // wording again.
- if (onIsMultiPane()) {
- updateActionBarTitle(R.string.settings_title);
- }
-
- // Update the title to for the preference pane that we're currently showing.
- final int titleId = getIntent().getExtras().getInt(PreferenceActivity.EXTRA_SHOW_FRAGMENT_TITLE);
- if (titleId != NO_SUCH_ID) {
- setTitle(titleId);
- } else {
- throw new IllegalStateException("Title id not found in intent bundle extras");
- }
-
- // Don't finish the activity -- we just reloaded all of the
- // individual parts! -- but when it returns, make sure that the
- // caller knows the locale changed.
- setResult(RESULT_CODE_LOCALE_DID_CHANGE);
- return;
- }
-
- refreshSuggestedSites();
-
- // Cause the current fragment to redisplay, the hard way.
- // This avoids nonsense with trying to reach inside fragments and force them
- // to redisplay themselves.
- // We also don't need to update the title.
- final Intent intent = (Intent) getIntent().clone();
- intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- startActivityForResultChoosingTransition(intent, REQUEST_CODE_PREF_SCREEN);
-
- setResult(RESULT_CODE_LOCALE_DID_CHANGE);
- finishChoosingTransition();
- }
-
- private void checkLocale() {
- final Locale currentLocale = Locale.getDefault();
- Log.v(LOGTAG, "Checking locale: " + currentLocale + " vs " + lastLocale);
- if (currentLocale.equals(lastLocale)) {
- return;
- }
-
- onLocaleChanged(currentLocale);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // Apply the current user-selected locale, if necessary.
- checkLocale();
-
- // Track this so we can decide whether to show locale options.
- // See also the workaround below for Bug 1015209.
- localeSwitchingIsEnabled = BrowserLocaleManager.getInstance().isEnabled();
-
- // For Android v11+ where we use Fragments (v11+ only due to bug 866352),
- // check that PreferenceActivity.EXTRA_SHOW_FRAGMENT has been set
- // (or set it) before super.onCreate() is called so Android can display
- // the correct Fragment resource.
- // Note: this seems to only be required for non-multipane devices, multipane
- // manages to automatically select the correct fragments.
- if (!getIntent().hasExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT)) {
- // Set up the default fragment if there is no explicit fragment to show.
- setupTopLevelFragmentIntent();
- }
-
- // We must call this before setTitle to avoid crashes. Most devices don't seem to care
- // (we used to call onCreate later), however the ASUS TF300T (running 4.2) crashes
- // with an NPE in android.support.v7.app.AppCompatDelegateImplV7.ensureSubDecor(), and it's
- // likely other strange devices (other Asus devices, some Samsungs) could do the same.
- super.onCreate(savedInstanceState);
-
- if (onIsMultiPane()) {
- // So that Android doesn't put the fragment title (or nothing at
- // all) in the action bar.
- updateActionBarTitle(R.string.settings_title);
-
- if (Build.VERSION.SDK_INT < 13) {
- // Affected by Bug 1015209 -- no detach/attach.
- // If we try rejigging fragments, we'll crash, so don't
- // enable locale switching at all.
- localeSwitchingIsEnabled = false;
- throw new IllegalStateException("foobar");
- }
- }
-
- // Use setResourceToOpen to specify these extras.
- Bundle intentExtras = getIntent().getExtras();
-
- EventDispatcher.getInstance().registerGeckoThreadListener(this,
- "Sanitize:Finished",
- "Snackbar:Show");
-
- // Add handling for long-press click.
- // This is only for Android 3.0 and below (which use the long-press-context-menu paradigm).
- final ListView mListView = getListView();
- mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
- @Override
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- // Call long-click handler if it the item implements it.
- final ListAdapter listAdapter = ((ListView) parent).getAdapter();
- final Object listItem = listAdapter.getItem(position);
-
- // Only CustomListPreference handles long clicks.
- if (listItem instanceof CustomListPreference && listItem instanceof View.OnLongClickListener) {
- final View.OnLongClickListener longClickListener = (View.OnLongClickListener) listItem;
- return longClickListener.onLongClick(view);
- }
- return false;
- }
- });
-
- // N.B., if we ever need to redisplay the locale selection UI without
- // just finishing and recreating the activity, right here we'll need to
- // capture EXTRA_SHOW_FRAGMENT_TITLE from the intent and store the title ID.
-
- // If launched from notification, explicitly cancel the notification.
- if (intentExtras != null && intentExtras.containsKey(DataReportingNotification.ALERT_NAME_DATAREPORTING_NOTIFICATION)) {
- Telemetry.sendUIEvent(TelemetryContract.Event.LAUNCH, Method.NOTIFICATION, "settings-data-choices");
- NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.cancel(DataReportingNotification.ALERT_NAME_DATAREPORTING_NOTIFICATION.hashCode());
- }
-
- // Launched from "Notifications settings" action button in a notification.
- if (intentExtras != null && intentExtras.containsKey(CheckForUpdatesAction.EXTRA_CONTENT_NOTIFICATION)) {
- Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(this));
- Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, Method.BUTTON, "notification-settings");
- Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, FeedService.getEnabledExperiment(this));
- }
- }
-
- /**
- * Set intent to display top-level settings fragment,
- * and show the correct title.
- */
- private void setupTopLevelFragmentIntent() {
- Intent intent = getIntent();
- // Check intent to determine settings screen to display.
- Bundle intentExtras = intent.getExtras();
- Bundle fragmentArgs = new Bundle();
- // Add resource argument to fragment if it exists.
- if (intentExtras != null && intentExtras.containsKey(INTENT_EXTRA_RESOURCES)) {
- String resourceName = intentExtras.getString(INTENT_EXTRA_RESOURCES);
- fragmentArgs.putString(INTENT_EXTRA_RESOURCES, resourceName);
- } else {
- // Use top-level settings screen.
- if (!onIsMultiPane()) {
- fragmentArgs.putString(INTENT_EXTRA_RESOURCES, "preferences");
- } else {
- fragmentArgs.putString(INTENT_EXTRA_RESOURCES, "preferences_general_tablet");
- }
- }
-
- // Build fragment intent.
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, GeckoPreferenceFragment.class.getName());
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
- // Used to get fragment title when locale changes (see onLocaleChanged method above)
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_TITLE, R.string.settings_title);
- }
-
- @Override
- public boolean isValidFragment(String fragmentName) {
- return GeckoPreferenceFragment.class.getName().equals(fragmentName);
- }
-
- @TargetApi(11)
- @Override
- public void onBuildHeaders(List<Header> target) {
- if (onIsMultiPane()) {
- loadHeadersFromResource(R.xml.preference_headers, target);
-
- Iterator<Header> iterator = target.iterator();
-
- while (iterator.hasNext()) {
- Header header = iterator.next();
-
- if (header.id == R.id.pref_header_advanced && !Restrictions.isAllowed(this, Restrictable.ADVANCED_SETTINGS)) {
- iterator.remove();
- } else if (header.id == R.id.pref_header_clear_private_data
- && !Restrictions.isAllowed(this, Restrictable.CLEAR_HISTORY)) {
- iterator.remove();
- }
- }
-
- mHeaders = target;
- }
- }
-
- @TargetApi(11)
- public void switchToHeader(int id) {
- if (mHeaders == null) {
- // Can't switch to a header if there are no headers!
- return;
- }
-
- for (Header header : mHeaders) {
- if (header.id == id) {
- switchToHeader(header);
- return;
- }
- }
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- if (!hasFocus || mInitialized)
- return;
-
- mInitialized = true;
- }
-
- @Override
- public void onBackPressed() {
- super.onBackPressed();
-
- if (NO_TRANSITIONS) {
- overridePendingTransition(0, 0);
- }
-
- Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL, Method.BACK, "settings");
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
- "Sanitize:Finished",
- "Snackbar:Show");
-
- if (mPrefsRequest != null) {
- PrefsHelper.removeObserver(mPrefsRequest);
- mPrefsRequest = null;
- }
- }
-
- @Override
- public void onPause() {
- // Symmetric with onResume.
- if (isMultiPane()) {
- SharedPreferences prefs = GeckoSharedPrefs.forApp(this);
- prefs.unregisterOnSharedPreferenceChangeListener(this);
- }
-
- super.onPause();
-
- if (getApplication() instanceof GeckoApplication) {
- ((GeckoApplication) getApplication()).onActivityPause(this);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- if (getApplication() instanceof GeckoApplication) {
- ((GeckoApplication) getApplication()).onActivityResume(this);
- }
-
- // Watch prefs, otherwise we don't reliably get told when they change.
- // See documentation for onSharedPreferenceChange for more.
- // Inexplicably only needed on tablet.
- if (isMultiPane()) {
- SharedPreferences prefs = GeckoSharedPrefs.forApp(this);
- prefs.registerOnSharedPreferenceChangeListener(this);
- }
- }
-
- @Override
- public void startActivity(Intent intent) {
- // For settings, we want to be able to pass results up the chain
- // of preference screens so Settings can behave as a single unit.
- // Specifically, when we open a link, we want to back out of all
- // the settings screens.
- // We need to start nested PreferenceScreens withStartActivityForResult().
- // Android doesn't let us do that (see Preference.onClick), so we're overriding here.
- startActivityForResultChoosingTransition(intent, REQUEST_CODE_PREF_SCREEN);
- }
-
- @Override
- public void startWithFragment(String fragmentName, Bundle args,
- Fragment resultTo, int resultRequestCode, int titleRes, int shortTitleRes) {
- Log.v(LOGTAG, "Starting with fragment: " + fragmentName + ", title " + titleRes);
-
- // Overriding because we want to use startActivityForResult for Fragment intents.
- Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
- if (resultTo == null) {
- startActivityForResultChoosingTransition(intent, REQUEST_CODE_PREF_SCREEN);
- } else {
- resultTo.startActivityForResult(intent, resultRequestCode);
- if (NO_TRANSITIONS) {
- overridePendingTransition(0, 0);
- }
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- // We might have just returned from a settings activity that allows us
- // to switch locales, so reflect any change that occurred.
- checkLocale();
-
- switch (requestCode) {
- case REQUEST_CODE_PREF_SCREEN:
- switch (resultCode) {
- case RESULT_CODE_EXIT_SETTINGS:
- updateActionBarTitle(R.string.settings_title);
-
- // Pass this result up to the parent activity.
- setResult(RESULT_CODE_EXIT_SETTINGS);
- finishChoosingTransition();
- break;
- }
- break;
- case REQUEST_CODE_TAB_QUEUE:
- if (TabQueueHelper.processTabQueuePromptResponse(resultCode, this)) {
- tabQueuePreference.setChecked(true);
- }
- break;
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- Permissions.onRequestPermissionsResult(this, permissions, grantResults);
- }
-
- @Override
- public void handleMessage(final String event, final NativeJSObject message, final EventCallback callback) {
- try {
- switch (event) {
- case "Sanitize:Finished":
- boolean success = message.getBoolean("success");
- final int stringRes = success ? R.string.private_data_success : R.string.private_data_fail;
-
- SnackbarBuilder.builder(GeckoPreferences.this)
- .message(stringRes)
- .duration(Snackbar.LENGTH_LONG)
- .buildAndShow();
- break;
- case "Snackbar:Show":
- SnackbarBuilder.builder(this)
- .fromEvent(message)
- .callback(callback)
- .buildAndShow();
- break;
- }
- } catch (Exception e) {
- Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
- }
- }
-
- /**
- * Initialize all of the preferences (native of Gecko ones) for this screen.
- *
- * @param prefs The android.preference.PreferenceGroup to initialize
- * @return The integer id for the PrefsHelper.PrefHandlerBase listener added
- * to monitor changes to Gecko prefs.
- */
- public PrefsHelper.PrefHandler setupPreferences(PreferenceGroup prefs) {
- ArrayList<String> list = new ArrayList<String>();
- setupPreferences(prefs, list);
- return getGeckoPreferences(prefs, list);
- }
-
- /**
- * Recursively loop through a PreferenceGroup. Initialize native Android prefs,
- * and build a list of Gecko preferences in the passed in prefs array
- *
- * @param preferences The android.preference.PreferenceGroup to initialize
- * @param prefs An ArrayList to fill with Gecko preferences that need to be
- * initialized
- * @return The integer id for the PrefsHelper.PrefHandlerBase listener added
- * to monitor changes to Gecko prefs.
- */
- private void setupPreferences(PreferenceGroup preferences, ArrayList<String> prefs) {
- for (int i = 0; i < preferences.getPreferenceCount(); i++) {
- final Preference pref = preferences.getPreference(i);
-
- // Eliminate locale switching if necessary.
- // This logic will need to be extended when
- // content language selection (Bug 881510) is implemented.
- if (!localeSwitchingIsEnabled &&
- "preferences_locale".equals(pref.getExtras().getString("resource"))) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
-
- String key = pref.getKey();
- if (pref instanceof PreferenceGroup) {
- // If datareporting is disabled, remove UI.
- if (PREFS_DATA_REPORTING_PREFERENCES.equals(key)) {
- if (!AppConstants.MOZ_DATA_REPORTING || !Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_SCREEN_ADVANCED.equals(key) &&
- !Restrictions.isAllowed(this, Restrictable.ADVANCED_SETTINGS)) {
- preferences.removePreference(pref);
- i--;
- continue;
- } else if (PREFS_CATEGORY_EXPERIMENTAL_FEATURES.equals(key)
- && !AppConstants.MOZ_ANDROID_ACTIVITY_STREAM
- && !AppConstants.MOZ_ANDROID_CUSTOM_TABS) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- setupPreferences((PreferenceGroup) pref, prefs);
- } else {
- if (HANDLERS.containsKey(key)) {
- PrefHandler handler = HANDLERS.get(key);
- if (!handler.setupPref(this, pref)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- }
-
- pref.setOnPreferenceChangeListener(this);
- if (PREFS_UPDATER_AUTODOWNLOAD.equals(key)) {
- if (!AppConstants.MOZ_UPDATER || ContextUtils.isInstalledFromGooglePlay(this)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_TRACKING_PROTECTION.equals(key)) {
- // Remove UI for global TP pref in non-Nightly builds.
- if (!AppConstants.NIGHTLY_BUILD) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_TRACKING_PROTECTION_PB.equals(key)) {
- // Remove UI for private-browsing-only TP pref in Nightly builds.
- if (AppConstants.NIGHTLY_BUILD) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_TELEMETRY_ENABLED.equals(key)) {
- if (!AppConstants.MOZ_TELEMETRY_REPORTING || !Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_HEALTHREPORT_UPLOAD_ENABLED.equals(key) ||
- PREFS_HEALTHREPORT_LINK.equals(key)) {
- if (!AppConstants.MOZ_SERVICES_HEALTHREPORT || !Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_GEO_REPORTING.equals(key) ||
- PREFS_GEO_LEARN_MORE.equals(key)) {
- if (!AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED || !Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_DEVTOOLS_REMOTE_USB_ENABLED.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.REMOTE_DEBUGGING)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_DEVTOOLS_REMOTE_WIFI_ENABLED.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.REMOTE_DEBUGGING)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- if (!InputOptionsUtils.supportsQrCodeReader(getApplicationContext())) {
- // WiFi debugging requires a QR code reader
- pref.setEnabled(false);
- pref.setSummary(getString(R.string.pref_developer_remotedebugging_wifi_disabled_summary));
- continue;
- }
- } else if (PREFS_DEVTOOLS_REMOTE_LINK.equals(key)) {
- // Remove the "Learn more" link if remote debugging is disabled
- if (!Restrictions.isAllowed(this, Restrictable.REMOTE_DEBUGGING)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_RESTORE_SESSION.equals(key) ||
- PREFS_BROWSER_LOCALE.equals(key)) {
- // Set the summary string to the current entry. The summary
- // for other list prefs will be set in the PrefsHelper
- // callback, but since this pref doesn't live in Gecko, we
- // need to handle it separately.
- ListPreference listPref = (ListPreference) pref;
- CharSequence selectedEntry = listPref.getEntry();
- listPref.setSummary(selectedEntry);
- continue;
- } else if (PREFS_SYNC.equals(key)) {
- // Don't show sync prefs while in guest mode.
- if (!Restrictions.isAllowed(this, Restrictable.MODIFY_ACCOUNTS)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_SEARCH_RESTORE_DEFAULTS.equals(key)) {
- pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- GeckoPreferences.this.restoreDefaultSearchEngines();
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_RESTORE_DEFAULTS, Method.LIST_ITEM);
- return true;
- }
- });
- } else if (PREFS_TAB_QUEUE.equals(key)) {
- tabQueuePreference = (SwitchPreference) pref;
- // Only show tab queue pref on nightly builds with the tab queue build flag.
- if (!TabQueueHelper.TAB_QUEUE_ENABLED) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_ZOOMED_VIEW_ENABLED.equals(key)) {
- if (!AppConstants.NIGHTLY_BUILD) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_VOICE_INPUT_ENABLED.equals(key)) {
- if (!InputOptionsUtils.supportsVoiceRecognizer(getApplicationContext(), getResources().getString(R.string.voicesearch_prompt))) {
- // Remove UI for voice input on non nightly builds.
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_QRCODE_ENABLED.equals(key)) {
- if (!InputOptionsUtils.supportsQrCodeReader(getApplicationContext())) {
- // Remove UI for qr code input on non nightly builds
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.PRIVATE_BROWSING)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_TRACKING_PROTECTION_LEARN_MORE.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.PRIVATE_BROWSING)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_MP_ENABLED.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.MASTER_PASSWORD)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_CLEAR_PRIVATE_DATA.equals(key) || PREFS_CLEAR_PRIVATE_DATA_EXIT.equals(key)) {
- if (!Restrictions.isAllowed(this, Restrictable.CLEAR_HISTORY)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_HOMEPAGE.equals(key)) {
- String setUrl = GeckoSharedPrefs.forProfile(getBaseContext()).getString(PREFS_HOMEPAGE, AboutPages.HOME);
- setHomePageSummary(pref, setUrl);
- pref.setOnPreferenceChangeListener(this);
- } else if (PREFS_FAQ_LINK.equals(key)) {
- // Format the FAQ link
- final String VERSION = AppConstants.MOZ_APP_VERSION;
- final String OS = AppConstants.OS_TARGET;
- final String LOCALE = Locales.getLanguageTag(Locale.getDefault());
-
- final String url = getResources().getString(R.string.faq_link, VERSION, OS, LOCALE);
- ((LinkPreference) pref).setUrl(url);
- } else if (PREFS_FEEDBACK_LINK.equals(key)) {
- // Format the feedback link. We can't easily use this "app.feedbackURL"
- // Gecko preference because the URL must be formatted.
- final String url = getResources().getString(R.string.feedback_link, AppConstants.MOZ_APP_VERSION, AppConstants.MOZ_UPDATE_CHANNEL);
- ((LinkPreference) pref).setUrl(url);
- } else if (PREFS_DYNAMIC_TOOLBAR.equals(key)) {
- if (DynamicToolbar.isForceDisabled()) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_NOTIFICATIONS_CONTENT.equals(key) ||
- PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE.equals(key)) {
- if (!FeedService.isInExperiment(this)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
- } else if (PREFS_CUSTOM_TABS.equals(key) && !AppConstants.MOZ_ANDROID_CUSTOM_TABS) {
- preferences.removePreference(pref);
- i--;
- continue;
- } else if (PREFS_ACTIVITY_STREAM.equals(key) && !ActivityStream.isUserEligible(this)) {
- preferences.removePreference(pref);
- i--;
- continue;
- }
-
- // Some Preference UI elements are not actually preferences,
- // but they require a key to work correctly. For example,
- // "Clear private data" requires a key for its state to be
- // saved when the orientation changes. It uses the
- // "android.not_a_preference.privacy.clear" key - which doesn't
- // exist in Gecko - to satisfy this requirement.
- if (isGeckoPref(key)) {
- prefs.add(key);
- }
- }
- }
- }
-
- private void setHomePageSummary(Preference pref, String value) {
- if (!TextUtils.isEmpty(value)) {
- pref.setSummary(value);
- } else {
- pref.setSummary(AboutPages.HOME);
- }
- }
-
- private boolean isGeckoPref(String key) {
- if (TextUtils.isEmpty(key)) {
- return false;
- }
-
- if (key.startsWith(NON_PREF_PREFIX)) {
- return false;
- }
-
- if (key.equals(PREFS_BROWSER_LOCALE)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Restore default search engines in Gecko and retrigger a search engine refresh.
- */
- protected void restoreDefaultSearchEngines() {
- GeckoAppShell.notifyObservers("SearchEngines:RestoreDefaults", null);
-
- // Send message to Gecko to get engines. SearchPreferenceCategory listens for the response.
- GeckoAppShell.notifyObservers("SearchEngines:GetVisible", null);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int itemId = item.getItemId();
- switch (itemId) {
- case android.R.id.home:
- finishChoosingTransition();
- return true;
- }
-
- // Generated R.id.* apparently aren't constant expressions, so they can't be switched.
- if (itemId == R.id.restore_defaults) {
- restoreDefaultSearchEngines();
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_RESTORE_DEFAULTS, Method.MENU);
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- final private int DIALOG_CREATE_MASTER_PASSWORD = 0;
- final private int DIALOG_REMOVE_MASTER_PASSWORD = 1;
-
- public static void setCharEncodingState(boolean enabled) {
- sIsCharEncodingEnabled = enabled;
- }
-
- public static boolean getCharEncodingState() {
- return sIsCharEncodingEnabled;
- }
-
- public static void broadcastAction(final Context context, final Intent intent) {
- fillIntentWithProfileInfo(context, intent);
- LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
- }
-
- private static void fillIntentWithProfileInfo(final Context context, final Intent intent) {
- // There is a race here, but GeckoProfile returns the default profile
- // when Gecko is not explicitly running for a different profile. In a
- // multi-profile world, this will need to be updated (possibly to
- // broadcast settings for all profiles). See Bug 882182.
- GeckoProfile profile = GeckoProfile.get(context);
- if (profile != null) {
- intent.putExtra("profileName", profile.getName())
- .putExtra("profilePath", profile.getDir().getAbsolutePath());
- }
- }
-
- /**
- * Broadcast the provided value as the value of the
- * <code>PREFS_GEO_REPORTING</code> pref.
- */
- public static void broadcastStumblerPref(final Context context, final boolean value) {
- Intent intent = new Intent(ACTION_STUMBLER_UPLOAD_PREF)
- .putExtra("pref", PREFS_GEO_REPORTING)
- .putExtra("branch", GeckoSharedPrefs.APP_PREFS_NAME)
- .putExtra("enabled", value)
- .putExtra("moz_mozilla_api_key", AppConstants.MOZ_MOZILLA_API_KEY);
- if (GeckoAppShell.getGeckoInterface() != null) {
- intent.putExtra("user_agent", GeckoAppShell.getGeckoInterface().getDefaultUAString());
- }
- broadcastAction(context, intent);
- }
-
- /**
- * Broadcast the current value of the
- * <code>PREFS_GEO_REPORTING</code> pref.
- */
- public static void broadcastStumblerPref(final Context context) {
- final boolean value = getBooleanPref(context, PREFS_GEO_REPORTING, false);
- broadcastStumblerPref(context, value);
- }
-
- /**
- * Return the value of the named preference in the default preferences file.
- *
- * This corresponds to the storage that backs preferences.xml.
- * @param context a <code>Context</code>; the
- * <code>PreferenceActivity</code> will suffice, but this
- * method is intended to be called from other contexts
- * within the application, not just this <code>Activity</code>.
- * @param name the name of the preference to retrieve.
- * @param def the default value to return if the preference is not present.
- * @return the value of the preference, or the default.
- */
- public static boolean getBooleanPref(final Context context, final String name, boolean def) {
- final SharedPreferences prefs = GeckoSharedPrefs.forApp(context);
- return prefs.getBoolean(name, def);
- }
-
- /**
- * Immediately handle the user's selection of a browser locale.
- *
- * Earlier locale-handling code did this with centralized logic in
- * GeckoApp, delegating to LocaleManager for persistence and refreshing
- * the activity as necessary.
- *
- * We no longer handle this by sending a message to GeckoApp, for
- * several reasons:
- *
- * * GeckoApp might not be running. Activities don't always stick around.
- * A Java bridge message might not be handled.
- * * We need to adapt the preferences UI to the locale ourselves.
- * * The user might not hit Back (or Up) -- they might hit Home and never
- * come back.
- *
- * We handle the case of the user returning to the browser via the
- * onActivityResult mechanism: see {@link BrowserApp#onActivityResult(int, int, Intent)}.
- */
- private boolean onLocaleSelected(final String currentLocale, final String newValue) {
- final Context context = getApplicationContext();
-
- // LocaleManager operations need to occur on the background thread.
- // ... but activity operations need to occur on the UI thread. So we
- // have nested runnables.
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- final LocaleManager localeManager = BrowserLocaleManager.getInstance();
-
- if (TextUtils.isEmpty(newValue)) {
- BrowserLocaleManager.getInstance().resetToSystemLocale(context);
- Telemetry.sendUIEvent(TelemetryContract.Event.LOCALE_BROWSER_RESET);
- } else {
- if (null == localeManager.setSelectedLocale(context, newValue)) {
- localeManager.updateConfiguration(context, Locale.getDefault());
- }
- Telemetry.sendUIEvent(TelemetryContract.Event.LOCALE_BROWSER_UNSELECTED, Method.NONE,
- currentLocale == null ? "unknown" : currentLocale);
- Telemetry.sendUIEvent(TelemetryContract.Event.LOCALE_BROWSER_SELECTED, Method.NONE, newValue);
- }
-
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- onLocaleChanged(Locale.getDefault());
- }
- });
- }
- });
-
- return true;
- }
-
- private void refreshSuggestedSites() {
- final ContentResolver cr = getApplicationContext().getContentResolver();
-
- // This will force all active suggested sites cursors
- // to request a refresh (e.g. cursor loaders).
- cr.notifyChange(SuggestedSites.CONTENT_URI, null);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- Log.d(LOGTAG, "onConfigurationChanged: " + newConfig.locale);
-
- if (lastLocale.equals(newConfig.locale)) {
- Log.d(LOGTAG, "Old locale same as new locale. Short-circuiting.");
- return;
- }
-
- final LocaleManager localeManager = BrowserLocaleManager.getInstance();
- final Locale changed = localeManager.onSystemConfigurationChanged(this, getResources(), newConfig, lastLocale);
- if (changed != null) {
- onLocaleChanged(changed);
- }
- }
-
- /**
- * Implementation for the {@link OnSharedPreferenceChangeListener} interface,
- * which we use to watch changes in our prefs file.
- *
- * This is reliably called whenever the pref changes, which is not the case
- * for multiple consecutive changes in the case of onPreferenceChange.
- *
- * Note that this listener is not always registered: we use it only on
- * tablets, Honeycomb and up, where we'll have a multi-pane view and prefs
- * changing multiple times.
- */
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (PREFS_BROWSER_LOCALE.equals(key)) {
- onLocaleSelected(Locales.getLanguageTag(lastLocale),
- sharedPreferences.getString(key, null));
- }
- }
-
- public interface PrefHandler {
- // Allows the pref to do any initialization it needs. Return false to have the pref removed
- // from the prefs screen entirely.
- public boolean setupPref(Context context, Preference pref);
- public void onChange(Context context, Preference pref, Object newValue);
- }
-
- private void recordSettingChangeTelemetry(String prefName, Object newValue) {
- final String value;
- if (newValue instanceof Boolean) {
- value = (Boolean) newValue ? "1" : "0";
- } else if (prefName.equals(PREFS_HOMEPAGE)) {
- // Don't record the user's homepage preference.
- value = "*";
- } else {
- value = newValue.toString();
- }
-
- final JSONArray extras = new JSONArray();
- extras.put(prefName);
- extras.put(value);
- Telemetry.sendUIEvent(TelemetryContract.Event.EDIT, Method.SETTINGS, extras.toString());
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final String prefName = preference.getKey();
- Log.i(LOGTAG, "Changed " + prefName + " = " + newValue);
- recordSettingChangeTelemetry(prefName, newValue);
-
- if (PREFS_MP_ENABLED.equals(prefName)) {
- showDialog((Boolean) newValue ? DIALOG_CREATE_MASTER_PASSWORD : DIALOG_REMOVE_MASTER_PASSWORD);
-
- // We don't want the "use master password" pref to change until the
- // user has gone through the dialog.
- return false;
- }
-
- if (PREFS_HOMEPAGE.equals(prefName)) {
- setHomePageSummary(preference, String.valueOf(newValue));
- }
-
- if (PREFS_BROWSER_LOCALE.equals(prefName)) {
- // Even though this is a list preference, we don't want to handle it
- // below, so we return here.
- return onLocaleSelected(Locales.getLanguageTag(lastLocale), (String) newValue);
- }
-
- if (PREFS_MENU_CHAR_ENCODING.equals(prefName)) {
- setCharEncodingState(((String) newValue).equals("true"));
- } else if (PREFS_UPDATER_AUTODOWNLOAD.equals(prefName)) {
- UpdateServiceHelper.setAutoDownloadPolicy(this, UpdateService.AutoDownloadPolicy.get((String) newValue));
- } else if (PREFS_UPDATER_URL.equals(prefName)) {
- UpdateServiceHelper.setUpdateUrl(this, (String) newValue);
- } else if (PREFS_HEALTHREPORT_UPLOAD_ENABLED.equals(prefName)) {
- final Boolean newBooleanValue = (Boolean) newValue;
- AdjustConstants.getAdjustHelper().setEnabled(newBooleanValue);
- } else if (PREFS_GEO_REPORTING.equals(prefName)) {
- if ((Boolean) newValue) {
- enableStumbler((CheckBoxPreference) preference);
- return false;
- } else {
- broadcastStumblerPref(GeckoPreferences.this, false);
- return true;
- }
- } else if (PREFS_TAB_QUEUE.equals(prefName)) {
- if ((Boolean) newValue && !TabQueueHelper.canDrawOverlays(this)) {
- Intent promptIntent = new Intent(this, TabQueuePrompt.class);
- startActivityForResult(promptIntent, REQUEST_CODE_TAB_QUEUE);
- return false;
- }
- } else if (PREFS_NOTIFICATIONS_CONTENT.equals(prefName)) {
- FeedService.setup(this);
- } else if (PREFS_ACTIVITY_STREAM.equals(prefName)) {
- ThreadUtils.postDelayedToUiThread(new Runnable() {
- @Override
- public void run() {
- GeckoAppShell.scheduleRestart();
- }
- }, 1000);
- } else if (HANDLERS.containsKey(prefName)) {
- PrefHandler handler = HANDLERS.get(prefName);
- handler.onChange(this, preference, newValue);
- }
-
- // Send Gecko-side pref changes to Gecko
- if (isGeckoPref(prefName)) {
- PrefsHelper.setPref(prefName, newValue, true /* flush */);
- }
-
- if (preference instanceof ListPreference) {
- // We need to find the entry for the new value
- int newIndex = ((ListPreference) preference).findIndexOfValue((String) newValue);
- CharSequence newEntry = ((ListPreference) preference).getEntries()[newIndex];
- ((ListPreference) preference).setSummary(newEntry);
- } else if (preference instanceof LinkPreference) {
- setResult(RESULT_CODE_EXIT_SETTINGS);
- finishChoosingTransition();
- } else if (preference instanceof FontSizePreference) {
- final FontSizePreference fontSizePref = (FontSizePreference) preference;
- fontSizePref.setSummary(fontSizePref.getSavedFontSizeName());
- }
-
- return true;
- }
-
- private void enableStumbler(final CheckBoxPreference preference) {
- Permissions
- .from(this)
- .withPermissions(Manifest.permission.ACCESS_FINE_LOCATION)
- .onUIThread()
- .andFallback(new Runnable() {
- @Override
- public void run() {
- preference.setChecked(false);
- }
- })
- .run(new Runnable() {
- @Override
- public void run() {
- preference.setChecked(true);
- broadcastStumblerPref(GeckoPreferences.this, true);
- }
- });
- }
-
- private TextInputLayout getTextBox(int aHintText) {
- final EditText input = new EditText(this);
- int inputtype = InputType.TYPE_CLASS_TEXT;
- inputtype |= InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
- input.setInputType(inputtype);
-
- input.setHint(aHintText);
-
- final TextInputLayout layout = new TextInputLayout(this);
- layout.addView(input);
-
- return layout;
- }
-
- private class PasswordTextWatcher implements TextWatcher {
- EditText input1;
- EditText input2;
- AlertDialog dialog;
-
- PasswordTextWatcher(EditText aInput1, EditText aInput2, AlertDialog aDialog) {
- input1 = aInput1;
- input2 = aInput2;
- dialog = aDialog;
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (dialog == null)
- return;
-
- String text1 = input1.getText().toString();
- String text2 = input2.getText().toString();
- boolean disabled = TextUtils.isEmpty(text1) || TextUtils.isEmpty(text2) || !text1.equals(text2);
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!disabled);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) { }
- }
-
- private class EmptyTextWatcher implements TextWatcher {
- EditText input;
- AlertDialog dialog;
-
- EmptyTextWatcher(EditText aInput, AlertDialog aDialog) {
- input = aInput;
- dialog = aDialog;
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (dialog == null)
- return;
-
- String text = input.getText().toString();
- boolean disabled = TextUtils.isEmpty(text);
- dialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!disabled);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) { }
- }
-
- @Override
- protected Dialog onCreateDialog(int id) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- LinearLayout linearLayout = new LinearLayout(this);
- linearLayout.setOrientation(LinearLayout.VERTICAL);
- AlertDialog dialog;
- switch (id) {
- case DIALOG_CREATE_MASTER_PASSWORD:
- final TextInputLayout inputLayout1 = getTextBox(R.string.masterpassword_password);
- final TextInputLayout inputLayout2 = getTextBox(R.string.masterpassword_confirm);
- linearLayout.addView(inputLayout1);
- linearLayout.addView(inputLayout2);
-
- final EditText input1 = inputLayout1.getEditText();
- final EditText input2 = inputLayout2.getEditText();
-
- builder.setTitle(R.string.masterpassword_create_title)
- .setView((View) linearLayout)
- .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- PrefsHelper.setPref(PREFS_MP_ENABLED,
- input1.getText().toString(),
- /* flush */ true);
- }
- })
- .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- return;
- }
- });
- dialog = builder.create();
- dialog.setOnShowListener(new DialogInterface.OnShowListener() {
- @Override
- public void onShow(DialogInterface dialog) {
- input1.setText("");
- input2.setText("");
- input1.requestFocus();
- }
- });
-
- PasswordTextWatcher watcher = new PasswordTextWatcher(input1, input2, dialog);
- input1.addTextChangedListener((TextWatcher) watcher);
- input2.addTextChangedListener((TextWatcher) watcher);
-
- break;
- case DIALOG_REMOVE_MASTER_PASSWORD:
- final TextInputLayout inputLayout = getTextBox(R.string.masterpassword_password);
- linearLayout.addView(inputLayout);
- final EditText input = inputLayout.getEditText();
-
- builder.setTitle(R.string.masterpassword_remove_title)
- .setView((View) linearLayout)
- .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- PrefsHelper.setPref(PREFS_MP_ENABLED, input.getText().toString());
- }
- })
- .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- return;
- }
- });
- dialog = builder.create();
- dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- input.setText("");
- }
- });
- dialog.setOnShowListener(new DialogInterface.OnShowListener() {
- @Override
- public void onShow(DialogInterface dialog) {
- input.setText("");
- }
- });
- input.addTextChangedListener(new EmptyTextWatcher(input, dialog));
- break;
- default:
- return null;
- }
-
- return dialog;
- }
-
- // Initialize preferences by requesting the preference values from Gecko
- private static class PrefCallbacks extends PrefsHelper.PrefHandlerBase {
- private final PreferenceGroup screen;
-
- public PrefCallbacks(final PreferenceGroup screen) {
- this.screen = screen;
- }
-
- private Preference getField(String prefName) {
- return screen.findPreference(prefName);
- }
-
- @Override
- public void prefValue(String prefName, final boolean value) {
- final TwoStatePreference pref = (TwoStatePreference) getField(prefName);
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- if (pref.isChecked() != value) {
- pref.setChecked(value);
- }
- }
- });
- }
-
- @Override
- public void prefValue(String prefName, final String value) {
- final Preference pref = getField(prefName);
- if (pref instanceof EditTextPreference) {
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- ((EditTextPreference) pref).setText(value);
- }
- });
- } else if (pref instanceof ListPreference) {
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- ((ListPreference) pref).setValue(value);
- // Set the summary string to the current entry
- CharSequence selectedEntry = ((ListPreference) pref).getEntry();
- ((ListPreference) pref).setSummary(selectedEntry);
- }
- });
- } else if (pref instanceof FontSizePreference) {
- final FontSizePreference fontSizePref = (FontSizePreference) pref;
- fontSizePref.setSavedFontSize(value);
- final String fontSizeName = fontSizePref.getSavedFontSizeName();
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- fontSizePref.setSummary(fontSizeName); // Ex: "Small".
- }
- });
- }
- }
-
- @Override
- public void prefValue(String prefName, final int value) {
- final Preference pref = getField(prefName);
- Log.w(LOGTAG, "Unhandled int value for pref [" + pref + "]");
- }
-
- @Override
- public void finish() {
- // enable all preferences once we have them from gecko
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- screen.setEnabled(true);
- }
- });
- }
- }
-
- private PrefsHelper.PrefHandler getGeckoPreferences(final PreferenceGroup screen,
- ArrayList<String> prefs) {
- final PrefsHelper.PrefHandler prefHandler = new PrefCallbacks(screen);
- final String[] prefNames = prefs.toArray(new String[prefs.size()]);
- PrefsHelper.addObserver(prefNames, prefHandler);
- return prefHandler;
- }
-
- @Override
- public boolean isGeckoActivityOpened() {
- return false;
- }
-
- /**
- * Given an Intent instance, add extras to specify which settings section to
- * open.
- *
- * resource should be a valid Android XML resource identifier.
- *
- * The mechanism to open a section differs based on Android version.
- */
- public static void setResourceToOpen(final Intent intent, final String resource) {
- if (intent == null) {
- throw new IllegalArgumentException("intent must not be null");
- }
- if (resource == null) {
- return;
- }
-
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, GeckoPreferenceFragment.class.getName());
-
- Bundle fragmentArgs = new Bundle();
- fragmentArgs.putString("resource", resource);
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/LinkPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/LinkPreference.java
deleted file mode 100644
index 774f78c53..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/LinkPreference.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.Tabs;
-
-import android.content.Context;
-import android.preference.Preference;
-import android.util.AttributeSet;
-
-class LinkPreference extends Preference {
- private String mUrl;
-
- public LinkPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mUrl = attrs.getAttributeValue(null, "url");
- }
- public LinkPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mUrl = attrs.getAttributeValue(null, "url");
- }
-
- public void setUrl(String url) {
- mUrl = url;
- }
-
- @Override
- protected void onClick() {
- Tabs.getInstance().loadUrlInTab(mUrl);
- callChangeListener(mUrl);
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/ListCheckboxPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/ListCheckboxPreference.java
deleted file mode 100644
index f56ea58b9..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/ListCheckboxPreference.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Checkable;
-
-import org.mozilla.gecko.R;
-
-/**
- * This preference shows a checkbox on its left hand side, but will show a menu when clicked.
- * Its used for preferences like "Clear on Exit" that have a boolean on-off state, but that represent
- * multiple boolean options inside.
- **/
-class ListCheckboxPreference extends MultiChoicePreference implements Checkable {
- private static final String LOGTAG = "GeckoListCheckboxPreference";
- private boolean checked;
-
- public ListCheckboxPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWidgetLayoutResource(R.layout.preference_checkbox);
- }
-
- @Override
- public boolean isChecked() {
- return checked;
- }
-
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
-
- View checkboxView = view.findViewById(R.id.checkbox);
- if (checkboxView instanceof Checkable) {
- ((Checkable) checkboxView).setChecked(checked);
- }
- }
-
- @Override
- public void setChecked(boolean checked) {
- boolean changed = checked != this.checked;
- this.checked = checked;
- if (changed) {
- notifyDependencyChange(shouldDisableDependents());
- notifyChanged();
- }
- }
-
- @Override
- public void toggle() {
- checked = !checked;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java
deleted file mode 100644
index c962a3d19..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/LocaleListPreference.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import java.nio.ByteBuffer;
-import java.text.Collator;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.BrowserLocaleManager;
-import org.mozilla.gecko.Locales;
-import org.mozilla.gecko.R;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.preference.ListPreference;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-
-public class LocaleListPreference extends ListPreference {
- private static final String LOG_TAG = "GeckoLocaleList";
-
- /**
- * With thanks to <http://stackoverflow.com/a/22679283/22003> for the
- * initial solution.
- *
- * This class encapsulates an approach to checking whether a script
- * is usable on a device. We attempt to draw a character from the
- * script (e.g., ব). If the fonts on the device don't have the correct
- * glyph, Android typically renders whitespace (rather than .notdef).
- *
- * Pass in part of the name of the locale in its local representation,
- * and a whitespace character; this class performs the graphical comparison.
- *
- * See Bug 1023451 Comment 24 for extensive explanation.
- */
- private static class CharacterValidator {
- private static final int BITMAP_WIDTH = 32;
- private static final int BITMAP_HEIGHT = 48;
-
- private final Paint paint = new Paint();
- private final byte[] missingCharacter;
-
- public CharacterValidator(String missing) {
- this.missingCharacter = getPixels(drawBitmap(missing));
- }
-
- private Bitmap drawBitmap(String text) {
- Bitmap b = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ALPHA_8);
- Canvas c = new Canvas(b);
- c.drawText(text, 0, BITMAP_HEIGHT / 2, this.paint);
- return b;
- }
-
- private static byte[] getPixels(final Bitmap b) {
- final int byteCount;
- if (Versions.feature19Plus) {
- byteCount = b.getAllocationByteCount();
- } else {
- // Close enough for government work.
- // Equivalent to getByteCount, but works on <12.
- byteCount = b.getRowBytes() * b.getHeight();
- }
-
- final ByteBuffer buffer = ByteBuffer.allocate(byteCount);
- try {
- b.copyPixelsToBuffer(buffer);
- } catch (RuntimeException e) {
- // Android throws this if there's not enough space in the buffer.
- // This should never occur, but if it does, we don't
- // really care -- we probably don't need the entire image.
- // This is awful. I apologize.
- if ("Buffer not large enough for pixels".equals(e.getMessage())) {
- return buffer.array();
- }
- throw e;
- }
-
- return buffer.array();
- }
-
- public boolean characterIsMissingInFont(String ch) {
- byte[] rendered = getPixels(drawBitmap(ch));
- return Arrays.equals(rendered, missingCharacter);
- }
- }
-
- private volatile Locale entriesLocale;
- private final CharacterValidator characterValidator;
-
- public LocaleListPreference(Context context) {
- this(context, null);
- }
-
- public LocaleListPreference(Context context, AttributeSet attributes) {
- super(context, attributes);
-
- // Thus far, missing glyphs are replaced by whitespace, not a box
- // or other Unicode codepoint.
- this.characterValidator = new CharacterValidator(" ");
- buildList();
- }
-
- private static final class LocaleDescriptor implements Comparable<LocaleDescriptor> {
- // We use Locale.US here to ensure a stable ordering of entries.
- private static final Collator COLLATOR = Collator.getInstance(Locale.US);
-
- public final String tag;
- private final String nativeName;
-
- public LocaleDescriptor(String tag) {
- this(Locales.parseLocaleCode(tag), tag);
- }
-
- public LocaleDescriptor(Locale locale, String tag) {
- this.tag = tag;
-
- final String displayName = locale.getDisplayName(locale);
- if (TextUtils.isEmpty(displayName)) {
- // There's nothing sane we can do.
- Log.w(LOG_TAG, "Display name is empty. Using " + locale.toString());
- this.nativeName = locale.toString();
- return;
- }
-
- // For now, uppercase the first character of LTR locale names.
- // This is pretty much what Android does. This is a reasonable hack
- // for Bug 1014602, but it won't generalize to all locales.
- final byte directionality = Character.getDirectionality(displayName.charAt(0));
- if (directionality == Character.DIRECTIONALITY_LEFT_TO_RIGHT) {
- this.nativeName = displayName.substring(0, 1).toUpperCase(locale) +
- displayName.substring(1);
- return;
- }
-
- this.nativeName = displayName;
- }
-
- public String getTag() {
- return this.tag;
- }
-
- public String getDisplayName() {
- return this.nativeName;
- }
-
- @Override
- public String toString() {
- return this.nativeName;
- }
-
-
- @Override
- public int compareTo(LocaleDescriptor another) {
- // We sort by name, so we use Collator.
- return COLLATOR.compare(this.nativeName, another.nativeName);
- }
-
- /**
- * See Bug 1023451 Comment 10 for the research that led to
- * this method.
- *
- * @return true if this locale can be used for displaying UI
- * on this device without known issues.
- */
- public boolean isUsable(CharacterValidator validator) {
- if (Versions.preLollipop && this.tag.matches("[a-zA-Z]{3}.*")) {
- // Earlier versions of Android can't load three-char locale code
- // resources.
- return false;
- }
-
- // Oh, for Java 7 switch statements.
- if (this.tag.equals("bn-IN")) {
- // Bengali sometimes has an English label if the Bengali script
- // is missing. This prevents us from simply checking character
- // rendering for bn-IN; we'll get a false positive for "B", not "ব".
- //
- // This doesn't seem to affect other Bengali-script locales
- // (below), which always have a label in native script.
- if (!this.nativeName.startsWith("বাংলা")) {
- // We're on an Android version that doesn't even have
- // characters to say বাংলা. Definite failure.
- return false;
- }
- }
-
- // These locales use a script that is often unavailable
- // on common Android devices. Make sure we can show them.
- // See documentation for CharacterValidator.
- // Note that bn-IN is checked here even if it passed above.
- if (this.tag.equals("or") ||
- this.tag.equals("my") ||
- this.tag.equals("pa-IN") ||
- this.tag.equals("gu-IN") ||
- this.tag.equals("bn-IN")) {
- if (validator.characterIsMissingInFont(this.nativeName.substring(0, 1))) {
- return false;
- }
- }
-
- return true;
- }
- }
-
- /**
- * Not every locale we ship can be used on every device, due to
- * font or rendering constraints.
- *
- * This method filters down the list before generating the descriptor array.
- */
- private LocaleDescriptor[] getUsableLocales() {
- Collection<String> shippingLocales = BrowserLocaleManager.getPackagedLocaleTags(getContext());
-
- // Future: single-locale builds should be specified, too.
- if (shippingLocales == null) {
- final String fallbackTag = BrowserLocaleManager.getInstance().getFallbackLocaleTag();
- return new LocaleDescriptor[] { new LocaleDescriptor(fallbackTag) };
- }
-
- final int initialCount = shippingLocales.size();
- final Set<LocaleDescriptor> locales = new HashSet<LocaleDescriptor>(initialCount);
- for (String tag : shippingLocales) {
- final LocaleDescriptor descriptor = new LocaleDescriptor(tag);
-
- if (!descriptor.isUsable(this.characterValidator)) {
- Log.w(LOG_TAG, "Skipping locale " + tag + " on this device.");
- continue;
- }
-
- locales.add(descriptor);
- }
-
- final int usableCount = locales.size();
- final LocaleDescriptor[] descriptors = locales.toArray(new LocaleDescriptor[usableCount]);
- Arrays.sort(descriptors, 0, usableCount);
- return descriptors;
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- // The superclass will take care of persistence.
- super.onDialogClosed(positiveResult);
-
- // Use this hook to try to fix up the environment ASAP.
- // Do this so that the redisplayed fragment is inflated
- // with the right locale.
- final Locale selectedLocale = getSelectedLocale();
- final Context context = getContext();
- BrowserLocaleManager.getInstance().updateConfiguration(context, selectedLocale);
- }
-
- private Locale getSelectedLocale() {
- final String tag = getValue();
- if (tag == null || tag.equals("")) {
- return Locale.getDefault();
- }
- return Locales.parseLocaleCode(tag);
- }
-
- @Override
- public CharSequence getSummary() {
- final String value = getValue();
-
- if (TextUtils.isEmpty(value)) {
- return getContext().getString(R.string.locale_system_default);
- }
-
- // We can't trust super.getSummary() across locale changes,
- // apparently, so let's do the same work.
- return new LocaleDescriptor(value).getDisplayName();
- }
-
- private void buildList() {
- final Locale currentLocale = Locale.getDefault();
- Log.d(LOG_TAG, "Building locales list. Current locale: " + currentLocale);
-
- if (currentLocale.equals(this.entriesLocale) &&
- getEntries() != null) {
- Log.v(LOG_TAG, "No need to build list.");
- return;
- }
-
- final LocaleDescriptor[] descriptors = getUsableLocales();
- final int count = descriptors.length;
-
- this.entriesLocale = currentLocale;
-
- // We leave room for "System default".
- final String[] entries = new String[count + 1];
- final String[] values = new String[count + 1];
-
- entries[0] = getContext().getString(R.string.locale_system_default);
- values[0] = "";
-
- for (int i = 0; i < count; ++i) {
- final String displayName = descriptors[i].getDisplayName();
- final String tag = descriptors[i].getTag();
- Log.v(LOG_TAG, displayName + " => " + tag);
- entries[i + 1] = displayName;
- values[i + 1] = tag;
- }
-
- setEntries(entries);
- setEntryValues(values);
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/ModifiableHintPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/ModifiableHintPreference.java
deleted file mode 100644
index c545472e2..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/ModifiableHintPreference.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.preference.Preference;
-import android.text.Spanned;
-import android.text.SpannableStringBuilder;
-import android.text.style.ImageSpan;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-class ModifiableHintPreference extends Preference {
- private static final String LOGTAG = "ModifiableHintPref";
- private final Context mContext;
-
- private final String MATCH_STRING = "%I";
- private final int RESID_TEXT_VIEW = R.id.label_search_hint;
- private final int RESID_DRAWABLE = R.drawable.ab_add_search_engine;
- private final double SCALE_FACTOR = 0.5;
-
- public ModifiableHintPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- }
-
- public ModifiableHintPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mContext = context;
- }
-
- @Override
- protected View onCreateView(ViewGroup parent) {
- View thisView = super.onCreateView(parent);
- configurePreferenceView(thisView);
- return thisView;
- }
-
- private void configurePreferenceView(View view) {
- TextView textView = (TextView) view.findViewById(RESID_TEXT_VIEW);
- String searchHint = textView.getText().toString();
-
- // Use an ImageSpan to include the "add search" icon in the Tip.
- int imageSpanIndex = searchHint.indexOf(MATCH_STRING);
- if (imageSpanIndex != -1) {
- // Scale the resource.
- Drawable drawable = mContext.getResources().getDrawable(RESID_DRAWABLE);
- drawable.setBounds(0, 0, (int) (drawable.getIntrinsicWidth() * SCALE_FACTOR),
- (int) (drawable.getIntrinsicHeight() * SCALE_FACTOR));
-
- ImageSpan searchIcon = new ImageSpan(drawable);
- final SpannableStringBuilder hintBuilder = new SpannableStringBuilder(searchHint);
-
- // Insert the image.
- hintBuilder.setSpan(searchIcon, imageSpanIndex, imageSpanIndex + MATCH_STRING.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- textView.setText(hintBuilder, TextView.BufferType.SPANNABLE);
- }
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java
deleted file mode 100644
index 5749bf29d..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/MultiChoicePreference.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.util.PrefUtils;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.app.AlertDialog.Builder;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.content.SharedPreferences;
-import android.preference.DialogPreference;
-import android.util.AttributeSet;
-
-import java.util.HashSet;
-import java.util.Set;
-
-class MultiChoicePreference extends DialogPreference implements DialogInterface.OnMultiChoiceClickListener {
- private static final String LOGTAG = "GeckoMultiChoicePreference";
-
- private boolean mValues[];
- private boolean mPrevValues[];
- private CharSequence mEntryValues[];
- private CharSequence mEntries[];
- private CharSequence mInitialValues[];
-
- public MultiChoicePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiChoicePreference);
- mEntries = a.getTextArray(R.styleable.MultiChoicePreference_entries);
- mEntryValues = a.getTextArray(R.styleable.MultiChoicePreference_entryValues);
- mInitialValues = a.getTextArray(R.styleable.MultiChoicePreference_initialValues);
- a.recycle();
-
- loadPersistedValues();
- }
-
- public MultiChoicePreference(Context context) {
- this(context, null);
- }
-
- /**
- * Sets the human-readable entries to be shown in the list. This will be
- * shown in subsequent dialogs.
- * <p>
- * Each entry must have a corresponding index in
- * {@link #setEntryValues(CharSequence[])} and
- * {@link #setInitialValues(CharSequence[])}.
- *
- * @param entries The entries.
- */
- public void setEntries(CharSequence[] entries) {
- mEntries = entries.clone();
- }
-
- /**
- * @param entriesResId The entries array as a resource.
- */
- public void setEntries(int entriesResId) {
- setEntries(getContext().getResources().getTextArray(entriesResId));
- }
-
- /**
- * Sets the preference values for preferences shown in the list.
- *
- * @param entryValues The entry values.
- */
- public void setEntryValues(CharSequence[] entryValues) {
- mEntryValues = entryValues.clone();
- loadPersistedValues();
- }
-
- /**
- * Entry values define a separate pref for each row in the dialog.
- *
- * @param entryValuesResId The entryValues array as a resource.
- */
- public void setEntryValues(int entryValuesResId) {
- setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
- }
-
- /**
- * The array of initial entry values in this list. Each entryValue
- * corresponds to an entryKey. These values are used if a) the preference
- * isn't persisted, or b) the preference is persisted but hasn't yet been
- * set.
- *
- * @param initialValues The entry values
- */
- public void setInitialValues(CharSequence[] initialValues) {
- mInitialValues = initialValues.clone();
- loadPersistedValues();
- }
-
- /**
- * @param initialValuesResId The initialValues array as a resource.
- */
- public void setInitialValues(int initialValuesResId) {
- setInitialValues(getContext().getResources().getTextArray(initialValuesResId));
- }
-
- /**
- * The list of translated strings corresponding to each preference.
- *
- * @return The array of entries.
- */
- public CharSequence[] getEntries() {
- return mEntries.clone();
- }
-
- /**
- * The list of values corresponding to each preference.
- *
- * @return The array of values.
- */
- public CharSequence[] getEntryValues() {
- return mEntryValues.clone();
- }
-
- /**
- * The list of initial values for each preference. Each string in this list
- * should be either "true" or "false".
- *
- * @return The array of initial values.
- */
- public CharSequence[] getInitialValues() {
- return mInitialValues.clone();
- }
-
- public void setValue(final int i, final boolean value) {
- mValues[i] = value;
- mPrevValues = mValues.clone();
- }
-
- /**
- * The list of values for each preference. These values are updated after
- * the dialog has been displayed.
- *
- * @return The array of values.
- */
- public Set<String> getValues() {
- final Set<String> values = new HashSet<String>();
-
- if (mValues == null) {
- return values;
- }
-
- for (int i = 0; i < mValues.length; i++) {
- if (mValues[i]) {
- values.add(mEntryValues[i].toString());
- }
- }
-
- return values;
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which, boolean val) {
- }
-
- @Override
- protected void onPrepareDialogBuilder(Builder builder) {
- if (mEntries == null || mInitialValues == null || mEntryValues == null) {
- throw new IllegalStateException(
- "MultiChoicePreference requires entries, entryValues, and initialValues arrays.");
- }
-
- if (mEntries.length != mEntryValues.length || mEntries.length != mInitialValues.length) {
- throw new IllegalStateException(
- "MultiChoicePreference entries, entryValues, and initialValues arrays must be the same length");
- }
-
- builder.setMultiChoiceItems(mEntries, mValues, this);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- if (mPrevValues == null || mInitialValues == null) {
- // Initialization is done asynchronously, so these values may not
- // have been set before the dialog was closed.
- return;
- }
-
- if (!positiveResult) {
- // user cancelled; reset checkbox values to their previous state
- mValues = mPrevValues.clone();
- return;
- }
-
- mPrevValues = mValues.clone();
-
- if (!callChangeListener(getValues())) {
- return;
- }
-
- persist();
- }
-
- /* Persists the current data stored by this pref to SharedPreferences. */
- public boolean persist() {
- if (isPersistent()) {
- final SharedPreferences.Editor edit = GeckoSharedPrefs.forProfile(getContext()).edit();
- final boolean res = persist(edit);
- edit.apply();
- return res;
- }
-
- return false;
- }
-
- /* Internal persist method. Take an edit so that multiple prefs can be persisted in a single commit. */
- protected boolean persist(SharedPreferences.Editor edit) {
- if (isPersistent()) {
- Set<String> vals = getValues();
- PrefUtils.putStringSet(edit, getKey(), vals).apply();;
- return true;
- }
-
- return false;
- }
-
- /* Returns a list of EntryValues that are currently enabled. */
- public Set<String> getPersistedStrings(Set<String> defaultVal) {
- if (!isPersistent()) {
- return defaultVal;
- }
-
- final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
- return PrefUtils.getStringSet(prefs, getKey(), defaultVal);
- }
-
- /**
- * Loads persistent prefs from shared preferences. If the preferences
- * aren't persistent or haven't yet been stored, they will be set to their
- * initial values.
- */
- protected void loadPersistedValues() {
- final int entryCount = mInitialValues.length;
- mValues = new boolean[entryCount];
-
- if (entryCount != mEntries.length || entryCount != mEntryValues.length) {
- throw new IllegalStateException(
- "MultiChoicePreference entryValues and initialValues arrays must be the same length");
- }
-
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- final Set<String> stringVals = getPersistedStrings(null);
-
- for (int i = 0; i < entryCount; i++) {
- if (stringVals != null) {
- mValues[i] = stringVals.contains(mEntryValues[i]);
- } else {
- final boolean defaultVal = mInitialValues[i].equals("true");
- mValues[i] = defaultVal;
- }
- }
-
- mPrevValues = mValues.clone();
- }
- });
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/MultiPrefMultiChoicePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/MultiPrefMultiChoicePreference.java
deleted file mode 100644
index 580d613ca..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/MultiPrefMultiChoicePreference.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.util.ThreadUtils;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.content.SharedPreferences;
-import android.widget.Button;
-import android.util.AttributeSet;
-import android.util.Log;
-
-import java.util.Set;
-
-/* Provides backwards compatibility for some old multi-choice pref types used by Gecko.
- * This will import the old data from the old prefs the first time it is run.
- */
-class MultiPrefMultiChoicePreference extends MultiChoicePreference {
- private static final String LOGTAG = "GeckoMultiPrefPreference";
- private static final String IMPORT_SUFFIX = "_imported_";
- private final CharSequence[] keys;
-
- public MultiPrefMultiChoicePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiPrefMultiChoicePreference);
- keys = a.getTextArray(R.styleable.MultiPrefMultiChoicePreference_entryKeys);
- a.recycle();
-
- loadPersistedValues();
- }
-
- // Helper method for reading a boolean pref.
- private boolean getPersistedBoolean(SharedPreferences prefs, String key, boolean defaultReturnValue) {
- if (!isPersistent()) {
- return defaultReturnValue;
- }
-
- return prefs.getBoolean(key, defaultReturnValue);
- }
-
- // Overridden to do a one time import for the old preference type to the new one.
- @Override
- protected synchronized void loadPersistedValues() {
- // This will load the new pref if it exists.
- super.loadPersistedValues();
-
- // First check if we've already done the import the old data. If so, nothing to load.
- final SharedPreferences prefs = GeckoSharedPrefs.forApp(getContext());
- final boolean imported = getPersistedBoolean(prefs, getKey() + IMPORT_SUFFIX, false);
- if (imported) {
- return;
- }
-
- // Load the data we'll need to find the old style prefs
- final CharSequence[] init = getInitialValues();
- final CharSequence[] entries = getEntries();
- if (keys == null || init == null) {
- return;
- }
-
- final int entryCount = keys.length;
- if (entryCount != entries.length || entryCount != init.length) {
- throw new IllegalStateException("MultiChoicePreference entryKeys and initialValues arrays must be the same length");
- }
-
- // Now iterate through the entries on a background thread.
- final SharedPreferences.Editor edit = prefs.edit();
- ThreadUtils.postToBackgroundThread(new Runnable() {
- @Override
- public void run() {
- try {
- // Use one editor to batch as many changes as we can.
- for (int i = 0; i < entryCount; i++) {
- String key = keys[i].toString();
- boolean initialValue = "true".equals(init[i]);
- boolean val = getPersistedBoolean(prefs, key, initialValue);
-
- // Save the pref and remove the old preference.
- setValue(i, val);
- edit.remove(key);
- }
-
- persist(edit);
- edit.putBoolean(getKey() + IMPORT_SUFFIX, true);
- edit.apply();
- } catch (Exception ex) {
- Log.i(LOGTAG, "Err", ex);
- }
- }
- });
- }
-
-
- @Override
- public void onClick(DialogInterface dialog, int which, boolean val) {
- // enable positive button only if at least one item is checked
- boolean enabled = false;
- final Set<String> values = getValues();
-
- enabled = (values.size() > 0);
- final Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
- if (button.isEnabled() != enabled) {
- button.setEnabled(enabled);
- }
- }
-
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreference.java
deleted file mode 100644
index 337d9dd2f..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreference.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.animation.PropertyAnimator;
-import org.mozilla.gecko.animation.PropertyAnimator.Property;
-import org.mozilla.gecko.animation.ViewHelper;
-import org.mozilla.gecko.R;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.DialogInterface.OnShowListener;
-import android.content.res.Resources;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class PanelsPreference extends CustomListPreference {
- protected String LOGTAG = "PanelsPreference";
-
- // Position state of this Preference in enclosing category.
- private static final int STATE_IS_FIRST = 0;
- private static final int STATE_IS_LAST = 1;
-
- /**
- * Index of the context menu button for controlling display options.
- * For (removable) Dynamic panels, this button removes the panel.
- * For built-in panels, this button toggles showing or hiding the panel.
- */
- private static final int INDEX_DISPLAY_BUTTON = 1;
- private static final int INDEX_REORDER_BUTTON = 2;
-
- // Indices of buttons in context menu for reordering.
- private static final int INDEX_MOVE_UP_BUTTON = 0;
- private static final int INDEX_MOVE_DOWN_BUTTON = 1;
-
- private String LABEL_HIDE;
- private String LABEL_SHOW;
-
- private View preferenceView;
- protected boolean mIsHidden;
- private final boolean mIsRemovable;
-
- private boolean mAnimate;
- private static final int ANIMATION_DURATION_MS = 400;
-
- // State for reordering.
- private int mPositionState = -1;
- private final int mIndex;
-
- public PanelsPreference(Context context, CustomListCategory parentCategory, boolean isRemovable, int index, boolean animate) {
- super(context, parentCategory);
- mIsRemovable = isRemovable;
- mIndex = index;
- mAnimate = animate;
- }
-
- @Override
- protected int getPreferenceLayoutResource() {
- return R.layout.preference_panels;
- }
-
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
-
- // Override view handling so we can grey out "hidden" PanelPreferences.
- view.setEnabled(!mIsHidden);
-
- if (view instanceof ViewGroup) {
- final ViewGroup group = (ViewGroup) view;
- for (int i = 0; i < group.getChildCount(); i++) {
- group.getChildAt(i).setEnabled(!mIsHidden);
- }
- preferenceView = group;
- }
-
- if (mAnimate) {
- ViewHelper.setAlpha(preferenceView, 0);
-
- final PropertyAnimator animator = new PropertyAnimator(ANIMATION_DURATION_MS);
- animator.attach(preferenceView, Property.ALPHA, 1);
- animator.start();
-
- // Clear animate flag.
- mAnimate = false;
- }
- }
-
- @Override
- protected String[] createDialogItems() {
- final Resources res = getContext().getResources();
- final String labelReorder = res.getString(R.string.pref_panels_reorder);
-
- if (mIsRemovable) {
- return new String[] { LABEL_SET_AS_DEFAULT, LABEL_REMOVE, labelReorder };
- }
-
- // Built-in panels can't be removed, so use show/hide options.
- LABEL_HIDE = res.getString(R.string.pref_panels_hide);
- LABEL_SHOW = res.getString(R.string.pref_panels_show);
-
- return new String[] { LABEL_SET_AS_DEFAULT, LABEL_HIDE, labelReorder };
- }
-
- @Override
- public void setIsDefault(boolean isDefault) {
- mIsDefault = isDefault;
- if (isDefault) {
- setSummary(LABEL_IS_DEFAULT);
- if (mIsHidden) {
- // Unhide the panel if it's being set as the default.
- setHidden(false);
- }
- } else {
- setSummary("");
- }
- }
-
- @Override
- protected void onDialogIndexClicked(int index) {
- switch (index) {
- case INDEX_SET_DEFAULT_BUTTON:
- mParentCategory.setDefault(this);
- break;
-
- case INDEX_DISPLAY_BUTTON:
- // Handle display options for the panel.
- if (mIsRemovable) {
- // For removable panels, the button displays text for removing the panel.
- mParentCategory.uninstall(this);
- } else {
- // Otherwise, the button toggles between text for showing or hiding the panel.
- ((PanelsPreferenceCategory) mParentCategory).setHidden(this, !mIsHidden);
- }
- break;
-
- case INDEX_REORDER_BUTTON:
- // Display dialog for changing preference order.
- final Dialog orderDialog = makeReorderDialog();
- orderDialog.show();
- break;
-
- default:
- Log.w(LOGTAG, "Selected index out of range: " + index);
- }
- }
-
- @Override
- protected void configureShownDialog() {
- super.configureShownDialog();
-
- // Handle Show/Hide buttons.
- if (!mIsRemovable) {
- final TextView hideButton = (TextView) mDialog.getListView().getChildAt(INDEX_DISPLAY_BUTTON);
- hideButton.setText(mIsHidden ? LABEL_SHOW : LABEL_HIDE);
- }
- }
-
-
- private Dialog makeReorderDialog() {
- final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
-
- final Resources res = getContext().getResources();
- final String labelUp = res.getString(R.string.pref_panels_move_up);
- final String labelDown = res.getString(R.string.pref_panels_move_down);
-
- builder.setTitle(getTitle());
- builder.setItems(new String[] { labelUp, labelDown }, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int index) {
- dialog.dismiss();
- switch (index) {
- case INDEX_MOVE_UP_BUTTON:
- ((PanelsPreferenceCategory) mParentCategory).moveUp(PanelsPreference.this);
- break;
-
- case INDEX_MOVE_DOWN_BUTTON:
- ((PanelsPreferenceCategory) mParentCategory).moveDown(PanelsPreference.this);
- break;
- }
- }
- });
-
- final Dialog dialog = builder.create();
- dialog.setOnShowListener(new OnShowListener() {
- @Override
- public void onShow(DialogInterface dialog) {
- setReorderItemsEnabled(dialog);
- }
- });
-
- return dialog;
- }
-
- public void setIsFirst() {
- mPositionState = STATE_IS_FIRST;
- }
-
- public void setIsLast() {
- mPositionState = STATE_IS_LAST;
- }
-
- /**
- * Configure enabled state of the reorder dialog, which must be done after the dialog is shown.
- * @param dialog Dialog to configure
- */
- private void setReorderItemsEnabled(DialogInterface dialog) {
- // Update button enabled-ness for reordering.
- switch (mPositionState) {
- case STATE_IS_FIRST:
- final TextView itemUp = (TextView) ((AlertDialog) dialog).getListView().getChildAt(INDEX_MOVE_UP_BUTTON);
- itemUp.setEnabled(false);
- // Disable clicks to this view.
- itemUp.setOnClickListener(null);
- break;
-
- case STATE_IS_LAST:
- final TextView itemDown = (TextView) ((AlertDialog) dialog).getListView().getChildAt(INDEX_MOVE_DOWN_BUTTON);
- itemDown.setEnabled(false);
- // Disable clicks to this view.
- itemDown.setOnClickListener(null);
- break;
-
- default:
- // Do nothing.
- break;
- }
- }
-
- public void setHidden(boolean toHide) {
- if (toHide) {
- setIsDefault(false);
- }
-
- if (mIsHidden != toHide) {
- mIsHidden = toHide;
- notifyChanged();
- }
- }
-
- public boolean isHidden() {
- return mIsHidden;
- }
-
- public int getIndex() {
- return mIndex;
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreferenceCategory.java b/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreferenceCategory.java
deleted file mode 100644
index d44b6eaa9..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/PanelsPreferenceCategory.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.home.HomeConfig;
-import org.mozilla.gecko.home.HomeConfig.PanelConfig;
-import org.mozilla.gecko.home.HomeConfig.State;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.util.UIAsyncTask;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-
-public class PanelsPreferenceCategory extends CustomListCategory {
- public static final String LOGTAG = "PanelsPrefCategory";
-
- protected HomeConfig mHomeConfig;
- protected HomeConfig.Editor mConfigEditor;
-
- protected UIAsyncTask.WithoutParams<State> mLoadTask;
-
- public PanelsPreferenceCategory(Context context) {
- super(context);
- initConfig(context);
- }
-
- public PanelsPreferenceCategory(Context context, AttributeSet attrs) {
- super(context, attrs);
- initConfig(context);
- }
-
- public PanelsPreferenceCategory(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initConfig(context);
- }
-
- protected void initConfig(Context context) {
- mHomeConfig = HomeConfig.getDefault(context);
- }
-
- @Override
- public void onAttachedToActivity() {
- super.onAttachedToActivity();
-
- loadHomeConfig(null);
- }
-
- /**
- * Load the Home Panels config and populate the preferences screen and maintain local state.
- */
- private void loadHomeConfig(final String animatePanelId) {
- mLoadTask = new UIAsyncTask.WithoutParams<State>(ThreadUtils.getBackgroundHandler()) {
- @Override
- public HomeConfig.State doInBackground() {
- return mHomeConfig.load();
- }
-
- @Override
- public void onPostExecute(HomeConfig.State configState) {
- mConfigEditor = configState.edit();
- displayHomeConfig(configState, animatePanelId);
- }
- };
- mLoadTask.execute();
- }
-
- /**
- * Simplified refresh of Home Panels when there is no state to be persisted.
- */
- public void refresh() {
- refresh(null, null);
- }
-
- /**
- * Refresh the Home Panels list and animate a panel, if specified.
- * If null, load from HomeConfig.
- *
- * @param State HomeConfig.State to rebuild Home Panels list from.
- * @param String panelId of panel to be animated.
- */
- public void refresh(State state, String animatePanelId) {
- // Clear all the existing home panels.
- removeAll();
-
- if (state == null) {
- loadHomeConfig(animatePanelId);
- } else {
- displayHomeConfig(state, animatePanelId);
- }
- }
-
- private void displayHomeConfig(HomeConfig.State configState, String animatePanelId) {
- int index = 0;
- for (PanelConfig panelConfig : configState) {
- final boolean isRemovable = panelConfig.isDynamic();
-
- // Create and add the pref.
- final String panelId = panelConfig.getId();
- final boolean animate = TextUtils.equals(animatePanelId, panelId);
-
- final PanelsPreference pref = new PanelsPreference(getContext(), PanelsPreferenceCategory.this, isRemovable, index, animate);
- pref.setTitle(panelConfig.getTitle());
- pref.setKey(panelConfig.getId());
- // XXX: Pull icon from PanelInfo.
- addPreference(pref);
-
- if (panelConfig.isDisabled()) {
- pref.setHidden(true);
- }
-
- index++;
- }
-
- setPositionState();
- setDefaultFromConfig();
- }
-
- private void setPositionState() {
- final int prefCount = getPreferenceCount();
-
- // Pass in position state to first and last preference.
- final PanelsPreference firstPref = (PanelsPreference) getPreference(0);
- firstPref.setIsFirst();
-
- final PanelsPreference lastPref = (PanelsPreference) getPreference(prefCount - 1);
- lastPref.setIsLast();
- }
-
- private void setDefaultFromConfig() {
- final String defaultPanelId = mConfigEditor.getDefaultPanelId();
- if (defaultPanelId == null) {
- mDefaultReference = null;
- return;
- }
-
- final int prefCount = getPreferenceCount();
-
- for (int i = 0; i < prefCount; i++) {
- final PanelsPreference pref = (PanelsPreference) getPreference(i);
-
- if (defaultPanelId.equals(pref.getKey())) {
- super.setDefault(pref);
- break;
- }
- }
- }
-
- @Override
- public void setDefault(CustomListPreference pref) {
- super.setDefault(pref);
-
- final String id = pref.getKey();
-
- final String defaultPanelId = mConfigEditor.getDefaultPanelId();
- if (defaultPanelId != null && defaultPanelId.equals(id)) {
- return;
- }
-
- updateVisibilityPrefsForPanel(id, true);
-
- mConfigEditor.setDefault(id);
- mConfigEditor.apply();
-
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_SET_DEFAULT, Method.DIALOG, id);
- }
-
- @Override
- protected void onPrepareForRemoval() {
- super.onPrepareForRemoval();
- if (mLoadTask != null) {
- mLoadTask.cancel();
- }
- }
-
- @Override
- public void uninstall(CustomListPreference pref) {
- final String id = pref.getKey();
- mConfigEditor.uninstall(id);
- mConfigEditor.apply();
-
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_REMOVE, Method.DIALOG, id);
-
- super.uninstall(pref);
- }
-
- public void moveUp(PanelsPreference pref) {
- final int panelIndex = pref.getIndex();
- if (panelIndex > 0) {
- final String panelKey = pref.getKey();
- mConfigEditor.moveTo(panelKey, panelIndex - 1);
- final State state = mConfigEditor.apply();
-
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_MOVE, Method.DIALOG, panelKey);
-
- refresh(state, panelKey);
- }
- }
-
- public void moveDown(PanelsPreference pref) {
- final int panelIndex = pref.getIndex();
- if (panelIndex < getPreferenceCount() - 1) {
- final String panelKey = pref.getKey();
- mConfigEditor.moveTo(panelKey, panelIndex + 1);
- final State state = mConfigEditor.apply();
-
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_MOVE, Method.DIALOG, panelKey);
-
- refresh(state, panelKey);
- }
- }
-
- /**
- * Update the hide/show state of the preference and save the HomeConfig
- * changes.
- *
- * @param pref Preference to update
- * @param toHide New hidden state of the preference
- */
- protected void setHidden(PanelsPreference pref, boolean toHide) {
- final String id = pref.getKey();
- mConfigEditor.setDisabled(id, toHide);
- mConfigEditor.apply();
-
- if (toHide) {
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_HIDE, Method.DIALOG, id);
- } else {
- Telemetry.sendUIEvent(TelemetryContract.Event.PANEL_SHOW, Method.DIALOG, id);
- }
-
- updateVisibilityPrefsForPanel(id, !toHide);
-
- pref.setHidden(toHide);
- setDefaultFromConfig();
- }
-
- /**
- * When the default panel is removed or disabled, find an enabled panel
- * if possible and set it as mDefaultReference.
- */
- @Override
- protected void setFallbackDefault() {
- setDefaultFromConfig();
- }
-
- private void updateVisibilityPrefsForPanel(String panelId, boolean toShow) {
- if (HomeConfig.getIdForBuiltinPanelType(HomeConfig.PanelType.BOOKMARKS).equals(panelId)) {
- GeckoSharedPrefs.forProfile(getContext()).edit().putBoolean(HomeConfig.PREF_KEY_BOOKMARKS_PANEL_ENABLED, toShow).apply();
- }
-
- if (HomeConfig.getIdForBuiltinPanelType(HomeConfig.PanelType.COMBINED_HISTORY).equals(panelId)) {
- GeckoSharedPrefs.forProfile(getContext()).edit().putBoolean(HomeConfig.PREF_KEY_HISTORY_PANEL_ENABLED, toShow).apply();
- }
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/PrivateDataPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/PrivateDataPreference.java
deleted file mode 100644
index 61eff98e7..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/PrivateDataPreference.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.icons.storage.DiskStorage;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-
-class PrivateDataPreference extends MultiPrefMultiChoicePreference {
- private static final String LOGTAG = "GeckoPrivateDataPreference";
- private static final String PREF_KEY_PREFIX = "private.data.";
-
- public PrivateDataPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (!positiveResult) {
- return;
- }
-
- Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.DIALOG, "settings");
-
- final Set<String> values = getValues();
- final JSONObject json = new JSONObject();
-
- for (String value : values) {
- // Privacy pref checkbox values are stored in Android prefs to
- // remember their check states. The key names are private.data.X,
- // where X is a string from Gecko sanitization. This prefix is
- // removed here so we can send the values to Gecko, which then does
- // the sanitization for each key.
- final String key = value.substring(PREF_KEY_PREFIX.length());
- try {
- json.put(key, true);
- } catch (JSONException e) {
- Log.e(LOGTAG, "JSON error", e);
- }
- }
-
- if (values.contains("private.data.offlineApps")) {
- // Remove all icons from storage if removing "Offline website data" was selected.
- DiskStorage.get(getContext()).evictAll();
- }
-
- // clear private data in gecko
- GeckoAppShell.notifyObservers("Sanitize:ClearData", json.toString());
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java
deleted file mode 100644
index 3ba80b562..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/SearchEnginePreference.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.SnackbarBuilder;
-import org.mozilla.gecko.icons.IconCallback;
-import org.mozilla.gecko.icons.IconDescriptor;
-import org.mozilla.gecko.icons.IconResponse;
-import org.mozilla.gecko.icons.Icons;
-import org.mozilla.gecko.widget.FaviconView;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.support.design.widget.Snackbar;
-import android.text.SpannableString;
-import android.util.Log;
-import android.view.View;
-
-/**
- * Represents an element in the list of search engines on the preferences menu.
- */
-public class SearchEnginePreference extends CustomListPreference {
- protected String LOGTAG = "SearchEnginePreference";
-
- protected static final int INDEX_REMOVE_BUTTON = 1;
-
- // The icon to display in the prompt when clicked.
- private BitmapDrawable mPromptIcon;
-
- // The bitmap backing the drawable above - needed separately for the FaviconView.
- private Bitmap mIconBitmap;
- private final Object bitmapLock = new Object();
-
- private FaviconView mFaviconView;
-
- // Search engine identifier specified by the gecko search service. This will be "other"
- // for engines that are not shipped with the app.
- private String mIdentifier;
-
- public SearchEnginePreference(Context context, SearchPreferenceCategory parentCategory) {
- super(context, parentCategory);
- }
-
- /**
- * Called by Android when we're bound to the custom view. Allows us to set the custom properties
- * of our custom view elements as we desire (We can now use findViewById on them).
- *
- * @param view The view instance for this Preference object.
- */
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
-
- // We synchronise to avoid a race condition between this and the favicon loading callback in
- // setSearchEngineFromJSON.
- synchronized (bitmapLock) {
- // Set the icon in the FaviconView.
- mFaviconView = ((FaviconView) view.findViewById(R.id.search_engine_icon));
-
- if (mIconBitmap != null) {
- mFaviconView.updateAndScaleImage(IconResponse.create(mIconBitmap));
- }
- }
- }
-
- @Override
- protected int getPreferenceLayoutResource() {
- return R.layout.preference_search_engine;
- }
-
- /**
- * Returns the strings to be displayed in the dialog.
- */
- @Override
- protected String[] createDialogItems() {
- return new String[] { LABEL_SET_AS_DEFAULT,
- LABEL_REMOVE };
- }
-
- @Override
- public void showDialog() {
- // If this is the last engine, then we are the default, and none of the options
- // on this menu can do anything.
- if (mParentCategory.getPreferenceCount() == 1) {
- Activity activity = (Activity) getContext();
-
- SnackbarBuilder.builder(activity)
- .message(R.string.pref_search_last_toast)
- .duration(Snackbar.LENGTH_LONG)
- .buildAndShow();
-
- return;
- }
-
- super.showDialog();
- }
-
- @Override
- protected void configureDialogBuilder(AlertDialog.Builder builder) {
- // Copy the icon from this object to the prompt we produce. We lazily create the drawable,
- // as the user may not ever actually tap this object.
- if (mPromptIcon == null && mIconBitmap != null) {
- mPromptIcon = new BitmapDrawable(getContext().getResources(), mFaviconView.getBitmap());
- }
-
- builder.setIcon(mPromptIcon);
- }
-
- @Override
- protected void onDialogIndexClicked(int index) {
- switch (index) {
- case INDEX_SET_DEFAULT_BUTTON:
- mParentCategory.setDefault(this);
- break;
-
- case INDEX_REMOVE_BUTTON:
- mParentCategory.uninstall(this);
- break;
-
- default:
- Log.w(LOGTAG, "Selected index out of range.");
- break;
- }
- }
-
- /**
- * @return Identifier of built-in search engine, or "other" if engine is not built-in.
- */
- public String getIdentifier() {
- return mIdentifier;
- }
-
- /**
- * Configure this Preference object from the Gecko search engine JSON object.
- * @param geckoEngineJSON The Gecko-formatted JSON object representing the search engine.
- * @throws JSONException If the JSONObject is invalid.
- */
- public void setSearchEngineFromJSON(JSONObject geckoEngineJSON) throws JSONException {
- mIdentifier = geckoEngineJSON.getString("identifier");
-
- // A null JS value gets converted into a string.
- if (mIdentifier.equals("null")) {
- mIdentifier = "other";
- }
-
- final String engineName = geckoEngineJSON.getString("name");
- final SpannableString titleSpannable = new SpannableString(engineName);
-
- setTitle(titleSpannable);
-
- final String iconURI = geckoEngineJSON.getString("iconURI");
- // Keep a reference to the bitmap - we'll need it later in onBindView.
- try {
- Icons.with(getContext())
- .pageUrl(mIdentifier)
- .icon(IconDescriptor.createGenericIcon(iconURI))
- .privileged(true)
- .build()
- .execute(new IconCallback() {
- @Override
- public void onIconResponse(IconResponse response) {
- mIconBitmap = response.getBitmap();
-
- if (mFaviconView != null) {
- mFaviconView.updateAndScaleImage(response);
- }
- }
- });
- } catch (IllegalArgumentException e) {
- Log.e(LOGTAG, "IllegalArgumentException creating Bitmap. Most likely a zero-length bitmap.", e);
- } catch (NullPointerException e) {
- Log.e(LOGTAG, "NullPointerException creating Bitmap. Most likely a zero-length bitmap.", e);
- }
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/SearchPreferenceCategory.java b/mobile/android/base/java/org/mozilla/gecko/preferences/SearchPreferenceCategory.java
deleted file mode 100644
index 47db8b9b0..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/SearchPreferenceCategory.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.Context;
-import android.preference.Preference;
-import android.util.AttributeSet;
-import android.util.Log;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoApp;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.util.GeckoEventListener;
-import org.mozilla.gecko.util.ThreadUtils;
-
-public class SearchPreferenceCategory extends CustomListCategory implements GeckoEventListener {
- public static final String LOGTAG = "SearchPrefCategory";
-
- public SearchPreferenceCategory(Context context) {
- super(context);
- }
-
- public SearchPreferenceCategory(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public SearchPreferenceCategory(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onAttachedToActivity() {
- super.onAttachedToActivity();
-
- // Register for SearchEngines messages and request list of search engines from Gecko.
- GeckoApp.getEventDispatcher().registerGeckoThreadListener(this, "SearchEngines:Data");
- GeckoAppShell.notifyObservers("SearchEngines:GetVisible", null);
- }
-
- @Override
- protected void onPrepareForRemoval() {
- super.onPrepareForRemoval();
-
- GeckoApp.getEventDispatcher().unregisterGeckoThreadListener(this, "SearchEngines:Data");
- }
-
- @Override
- public void setDefault(CustomListPreference item) {
- super.setDefault(item);
-
- sendGeckoEngineEvent("SearchEngines:SetDefault", item.getTitle().toString());
-
- final String identifier = ((SearchEnginePreference) item).getIdentifier();
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_SET_DEFAULT, Method.DIALOG, identifier);
- }
-
- @Override
- public void uninstall(CustomListPreference item) {
- super.uninstall(item);
-
- sendGeckoEngineEvent("SearchEngines:Remove", item.getTitle().toString());
-
- final String identifier = ((SearchEnginePreference) item).getIdentifier();
- Telemetry.sendUIEvent(TelemetryContract.Event.SEARCH_REMOVE, Method.DIALOG, identifier);
- }
-
- @Override
- public void handleMessage(String event, final JSONObject data) {
- if (event.equals("SearchEngines:Data")) {
- // Parse engines array from JSON.
- JSONArray engines;
- try {
- engines = data.getJSONArray("searchEngines");
- } catch (JSONException e) {
- Log.e(LOGTAG, "Unable to decode search engine data from Gecko.", e);
- return;
- }
-
- // Clear the preferences category from this thread.
- this.removeAll();
-
- // Create an element in this PreferenceCategory for each engine.
- for (int i = 0; i < engines.length(); i++) {
- try {
- final JSONObject engineJSON = engines.getJSONObject(i);
-
- final SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
- enginePreference.setSearchEngineFromJSON(engineJSON);
- enginePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- SearchEnginePreference sPref = (SearchEnginePreference) preference;
- // Display the configuration dialog associated with the tapped engine.
- sPref.showDialog();
- return true;
- }
- });
-
- addPreference(enginePreference);
-
- // The first element in the array is the default engine.
- if (i == 0) {
- // We set this here, not in setSearchEngineFromJSON, because it allows us to
- // keep a reference to the default engine to use when the AlertDialog
- // callbacks are used.
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- enginePreference.setIsDefault(true);
- }
- });
- mDefaultReference = enginePreference;
- }
- } catch (JSONException e) {
- Log.e(LOGTAG, "JSONException parsing engine at index " + i, e);
- }
- }
- }
- }
-
- /**
- * Helper method to send a particular event string to Gecko with an associated engine name.
- * @param event The type of event to send.
- * @param engine The engine to which the event relates.
- */
- private void sendGeckoEngineEvent(String event, String engineName) {
- JSONObject json = new JSONObject();
- try {
- json.put("engine", engineName);
- } catch (JSONException e) {
- Log.e(LOGTAG, "JSONException creating search engine configuration change message for Gecko.", e);
- return;
- }
- GeckoAppShell.notifyObservers(event, json.toString());
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/SetHomepagePreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/SetHomepagePreference.java
deleted file mode 100644
index 55be702c4..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/SetHomepagePreference.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-package org.mozilla.gecko.preferences;
-
-import org.mozilla.gecko.AboutPages;
-import org.mozilla.gecko.GeckoSharedPrefs;
-import org.mozilla.gecko.R;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.DialogPreference;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.RadioButton;
-import android.widget.RadioGroup;
-
-public class SetHomepagePreference extends DialogPreference {
- private static final String DEFAULT_HOMEPAGE = AboutPages.HOME;
-
- private final SharedPreferences prefs;
-
- private RadioGroup homepageLayout;
- private RadioButton defaultRadio;
- private RadioButton userAddressRadio;
- private EditText homepageEditText;
-
- // This is the url that 1) was loaded from prefs or, 2) stored
- // when the user pressed the "default homepage" checkbox.
- private String storedUrl;
-
- public SetHomepagePreference(final Context context, final AttributeSet attrs) {
- super(context, attrs);
- prefs = GeckoSharedPrefs.forProfile(context);
- }
-
- @Override
- protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
- // Without this GB devices have a black background to the dialog.
- builder.setInverseBackgroundForced(true);
- }
-
- @Override
- protected void onBindDialogView(final View view) {
- super.onBindDialogView(view);
-
- homepageLayout = (RadioGroup) view.findViewById(R.id.homepage_layout);
- defaultRadio = (RadioButton) view.findViewById(R.id.radio_default);
- userAddressRadio = (RadioButton) view.findViewById(R.id.radio_user_address);
- homepageEditText = (EditText) view.findViewById(R.id.edittext_user_address);
-
- storedUrl = prefs.getString(GeckoPreferences.PREFS_HOMEPAGE, DEFAULT_HOMEPAGE);
-
- homepageLayout.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(final RadioGroup radioGroup, final int checkedId) {
- if (checkedId == R.id.radio_user_address) {
- homepageEditText.setVisibility(View.VISIBLE);
- openKeyboardAndSelectAll(getContext(), homepageEditText);
- } else {
- homepageEditText.setVisibility(View.GONE);
- }
- }
- });
- setUIState(storedUrl);
- }
-
- private void setUIState(final String url) {
- if (isUrlDefaultHomepage(url)) {
- defaultRadio.setChecked(true);
- } else {
- userAddressRadio.setChecked(true);
- homepageEditText.setText(url);
- }
- }
-
- private boolean isUrlDefaultHomepage(final String url) {
- return TextUtils.isEmpty(url) || DEFAULT_HOMEPAGE.equals(url);
- }
-
- private static void openKeyboardAndSelectAll(final Context context, final View viewToFocus) {
- viewToFocus.requestFocus();
- viewToFocus.post(new Runnable() {
- @Override
- public void run() {
- InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(viewToFocus, InputMethodManager.SHOW_IMPLICIT);
- // android:selectAllOnFocus doesn't work for the initial focus:
- // I'm not sure why. We manually selectAll instead.
- if (viewToFocus instanceof EditText) {
- ((EditText) viewToFocus).selectAll();
- }
- }
- });
- }
-
- @Override
- protected void onDialogClosed(final boolean positiveResult) {
- super.onDialogClosed(positiveResult);
- if (positiveResult) {
- final SharedPreferences.Editor editor = prefs.edit();
- final String homePageEditTextValue = homepageEditText.getText().toString();
- final String newPrefValue;
- if (homepageLayout.getCheckedRadioButtonId() == R.id.radio_default ||
- isUrlDefaultHomepage(homePageEditTextValue)) {
- newPrefValue = "";
- editor.remove(GeckoPreferences.PREFS_HOMEPAGE);
- } else {
- newPrefValue = homePageEditTextValue;
- editor.putString(GeckoPreferences.PREFS_HOMEPAGE, newPrefValue);
- }
- editor.apply();
-
- if (getOnPreferenceChangeListener() != null) {
- getOnPreferenceChangeListener().onPreferenceChange(this, newPrefValue);
- }
- }
- }
-}
diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/SyncPreference.java b/mobile/android/base/java/org/mozilla/gecko/preferences/SyncPreference.java
deleted file mode 100644
index 350ac8fc0..000000000
--- a/mobile/android/base/java/org/mozilla/gecko/preferences/SyncPreference.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.preferences;
-
-import android.content.Context;
-import android.content.Intent;
-import android.preference.Preference;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-
-import com.squareup.picasso.Picasso;
-import com.squareup.picasso.Target;
-
-import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.R;
-import org.mozilla.gecko.Telemetry;
-import org.mozilla.gecko.TelemetryContract;
-import org.mozilla.gecko.TelemetryContract.Method;
-import org.mozilla.gecko.fxa.FxAccountConstants;
-import org.mozilla.gecko.fxa.activities.FxAccountWebFlowActivity;
-import org.mozilla.gecko.fxa.activities.PicassoPreferenceIconTarget;
-import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
-import org.mozilla.gecko.sync.ExtendedJSONObject;
-import org.mozilla.gecko.util.ThreadUtils;
-
-class SyncPreference extends Preference {
- private final Context mContext;
- private final Target profileAvatarTarget;
-
- public SyncPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- final float cornerRadius = mContext.getResources().getDimension(R.dimen.fxaccount_profile_image_width) / 2;
- profileAvatarTarget = new PicassoPreferenceIconTarget(mContext.getResources(), this, cornerRadius);
- }
-
- private void launchFxASetup() {
- final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
- intent.putExtra(FxAccountWebFlowActivity.EXTRA_ENDPOINT, FxAccountConstants.ENDPOINT_PREFERENCES);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- mContext.startActivity(intent);
- }
-
- public void update(final AndroidFxAccount fxAccount) {
- if (fxAccount == null) {
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- setTitle(R.string.pref_sync);
- setSummary(R.string.pref_sync_summary);
- // Cancel any pending task.
- Picasso.with(mContext).cancelRequest(profileAvatarTarget);
- // Clear previously set icon.
- // Bug 1312719 - IconDrawable is prior to IconResId, drawable must be set null before setIcon(resId)
- // http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/preference/Preference.java#562
- setIcon(null);
- setIcon(R.drawable.sync_avatar_default);
- }
- });
- return;
- }
-
- // Update title from account email.
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- setTitle(fxAccount.getEmail());
- setSummary("");
- }
- });
-
- final ExtendedJSONObject profileJSON = fxAccount.getProfileJSON();
- if (profileJSON == null) {
- return;
- }
-
- // Avatar URI empty, return early.
- final String avatarURI = profileJSON.getString(FxAccountConstants.KEY_PROFILE_JSON_AVATAR);
- if (TextUtils.isEmpty(avatarURI)) {
- return;
- }
-
- Picasso.with(mContext)
- .load(avatarURI)
- .centerInside()
- .resizeDimen(R.dimen.fxaccount_profile_image_width, R.dimen.fxaccount_profile_image_height)
- .placeholder(R.drawable.sync_avatar_default)
- .error(R.drawable.sync_avatar_default)
- .into(profileAvatarTarget);
- }
-
- @Override
- protected void onClick() {
- // Launch the FxA "Get started" activity, which will dispatch to the
- // right location.
- launchFxASetup();
- Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, Method.SETTINGS, "sync_setup");
- }
-}