Index: chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java |
index 855a003fcd29d839e79f3df8b66b50c6f071660d..c4863018ef9f0d11593fe887da66af4601db3acc 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java |
@@ -25,7 +25,10 @@ import android.widget.TextView; |
import org.chromium.base.ApiCompatibilityUtils; |
import org.chromium.base.ContextUtils; |
+import org.chromium.base.VisibleForTesting; |
+import org.chromium.base.metrics.RecordUserAction; |
import org.chromium.chrome.R; |
+import org.chromium.chrome.browser.locale.LocaleManager; |
import org.chromium.chrome.browser.omnibox.geo.GeolocationHeader; |
import org.chromium.chrome.browser.preferences.website.ContentSetting; |
import org.chromium.chrome.browser.preferences.website.GeolocationInfo; |
@@ -38,71 +41,64 @@ import org.chromium.components.location.LocationUtils; |
import org.chromium.ui.text.SpanApplier; |
import org.chromium.ui.text.SpanApplier.SpanInfo; |
+import java.util.ArrayList; |
import java.util.List; |
/** |
* A custom adapter for listing search engines. |
*/ |
public class SearchEngineAdapter extends BaseAdapter implements LoadListener, OnClickListener { |
- /** |
- * A callback for reporting progress to the owner. |
- */ |
- public interface SelectSearchEngineCallback { |
- /** |
- * Called when the search engine data has loaded and we've determined the currently active |
- * one. |
- * @param name Provides the name of it (with a simplified URL in parenthesis). |
- */ |
- void currentSearchEngineDetermined(int selectedIndex); |
- } |
+ private static final int VIEW_TYPE_ITEM = 0; |
+ private static final int VIEW_TYPE_DIVIDER = 1; |
+ private static final int VIEW_TYPE_COUNT = 2; |
- // The current context. |
+ /** The current context. */ |
private Context mContext; |
- // The layout inflater to use for the custom views. |
+ /** The layout inflater to use for the custom views. */ |
private LayoutInflater mLayoutInflater; |
- // The callback to use for notifying caller of progress. |
- private SelectSearchEngineCallback mCallback; |
+ /** The list of prepopluated and default search engines. */ |
+ private List<TemplateUrl> mPrepopulatedSearchEngines = new ArrayList<>(); |
- // The list of available search engines. |
- private List<TemplateUrl> mSearchEngines; |
- // The position (index into mSearchEngines) of the currently selected search engine. Can be -1 |
- // if current search engine is managed and set to something other than the pre-populated values. |
+ /** The list of recently visited search engines. */ |
+ private List<TemplateUrl> mRecentSearchEngines = new ArrayList<>(); |
+ |
+ /** |
+ * The position (index into mPrepopulatedSearchEngines) of the currently selected search engine. |
+ * Can be -1 if current search engine is managed and set to something other than the |
+ * pre-populated values. |
+ */ |
private int mSelectedSearchEnginePosition = -1; |
- // The position of the default search engine before user's action. |
+ /** The position of the default search engine before user's action. */ |
private int mInitialEnginePosition = -1; |
/** |
* Construct a SearchEngineAdapter. |
* @param context The current context. |
- * @param callback The callback to use to communicate back. |
*/ |
- public SearchEngineAdapter(Context context, SelectSearchEngineCallback callback) { |
+ public SearchEngineAdapter(Context context) { |
mContext = context; |
mLayoutInflater = (LayoutInflater) mContext.getSystemService( |
Context.LAYOUT_INFLATER_SERVICE); |
- mCallback = callback; |
initEntries(); |
} |
- /** |
- * @return The index of the selected engine before user's action. |
- */ |
- public int getInitialSearchEnginePosition() { |
- return mInitialEnginePosition; |
- } |
- |
- // Used for testing. |
- |
+ @VisibleForTesting |
String getValueForTesting() { |
return Integer.toString(mSelectedSearchEnginePosition); |
} |
- void setValueForTesting(String value) { |
- searchEngineSelected(Integer.parseInt(value)); |
+ @VisibleForTesting |
+ String setValueForTesting(String value) { |
+ return searchEngineSelected(Integer.parseInt(value)); |
+ } |
+ |
+ @VisibleForTesting |
+ String getKeywordForTesting(int index) { |
+ return toKeyword(index); |
} |
/** |
@@ -116,37 +112,68 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
return; // Flow continues in onTemplateUrlServiceLoaded below. |
} |
- // Fetch all the search engine info and the currently active one. |
- mSearchEngines = templateUrlService.getLocalizedSearchEngines(); |
- int searchEngineIndex = templateUrlService.getDefaultSearchEngineIndex(); |
- // Convert the TemplateUrl index into an index into mSearchEngines. |
+ int defaultSearchEngineIndex = templateUrlService.getDefaultSearchEngineIndex(); |
+ for (TemplateUrl templateUrl : templateUrlService.getSearchEngines()) { |
+ if (templateUrl.getType() == TemplateUrlService.TYPE_PREPOPULATED |
+ || templateUrl.getType() == TemplateUrlService.TYPE_DEFAULT) { |
+ mPrepopulatedSearchEngines.add(templateUrl); |
+ } else { |
+ mRecentSearchEngines.add(templateUrl); |
+ } |
+ } |
+ |
+ // Convert the TemplateUrl index into an index of mSearchEngines. |
mSelectedSearchEnginePosition = -1; |
- for (int i = 0; i < mSearchEngines.size(); ++i) { |
- if (mSearchEngines.get(i).getIndex() == searchEngineIndex) { |
+ for (int i = 0; i < mPrepopulatedSearchEngines.size(); ++i) { |
+ if (mPrepopulatedSearchEngines.get(i).getIndex() == defaultSearchEngineIndex) { |
mSelectedSearchEnginePosition = i; |
} |
} |
+ |
+ for (int i = 0; i < mRecentSearchEngines.size(); ++i) { |
+ if (mRecentSearchEngines.get(i).getIndex() == defaultSearchEngineIndex) { |
+ // Add one to offset the title for the recent search engine list. |
+ mSelectedSearchEnginePosition = i + computeStartIndexForRecentSearchEngines(); |
+ } |
+ } |
+ |
mInitialEnginePosition = mSelectedSearchEnginePosition; |
- // Report back what is selected. |
- mCallback.currentSearchEngineDetermined(toIndex(mSelectedSearchEnginePosition)); |
+ TemplateUrlService.getInstance().setSearchEngine(toKeyword(mSelectedSearchEnginePosition)); |
} |
- private int toIndex(int position) { |
- return mSearchEngines.get(position).getIndex(); |
+ private String toKeyword(int position) { |
+ if (position < mPrepopulatedSearchEngines.size()) { |
+ return mPrepopulatedSearchEngines.get(position).getKeyword(); |
+ } else { |
+ position -= computeStartIndexForRecentSearchEngines(); |
+ return mRecentSearchEngines.get(position).getKeyword(); |
+ } |
} |
// BaseAdapter: |
@Override |
public int getCount() { |
- return mSearchEngines == null ? 0 : mSearchEngines.size(); |
+ return mPrepopulatedSearchEngines == null |
+ ? 0 |
+ : mPrepopulatedSearchEngines.size() + mRecentSearchEngines.size() + 1; |
+ } |
+ |
+ @Override |
+ public int getViewTypeCount() { |
+ return VIEW_TYPE_COUNT; |
} |
@Override |
public Object getItem(int pos) { |
- TemplateUrl templateUrl = mSearchEngines.get(pos); |
- return templateUrl.getShortName(); |
+ if (pos < mPrepopulatedSearchEngines.size()) { |
+ return mPrepopulatedSearchEngines.get(pos); |
+ } else if (pos > mPrepopulatedSearchEngines.size()) { |
+ pos -= computeStartIndexForRecentSearchEngines(); |
+ return mRecentSearchEngines.get(pos); |
+ } |
+ return null; |
} |
@Override |
@@ -155,10 +182,27 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
} |
@Override |
+ public int getItemViewType(int position) { |
+ if (position == mPrepopulatedSearchEngines.size()) { |
+ return VIEW_TYPE_DIVIDER; |
+ } else { |
+ return VIEW_TYPE_ITEM; |
+ } |
+ } |
+ |
+ @Override |
public View getView(int position, View convertView, ViewGroup parent) { |
View view = convertView; |
+ TemplateUrl templateUrl = (TemplateUrl) getItem(position); |
+ int itemViewType = getItemViewType(position); |
if (convertView == null) { |
- view = mLayoutInflater.inflate(R.layout.search_engine, null); |
+ view = mLayoutInflater.inflate(itemViewType == VIEW_TYPE_DIVIDER |
+ ? R.layout.search_engine_recent_title |
+ : R.layout.search_engine, |
+ null); |
+ } |
+ if (itemViewType == VIEW_TYPE_DIVIDER) { |
+ return view; |
} |
view.setOnClickListener(this); |
@@ -178,11 +222,18 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
} |
radioButton.setChecked(selected); |
- TextView description = (TextView) view.findViewById(R.id.description); |
- TemplateUrl templateUrl = mSearchEngines.get(position); |
+ TextView description = (TextView) view.findViewById(R.id.name); |
Resources resources = mContext.getResources(); |
description.setText(templateUrl.getShortName()); |
+ TextView url = (TextView) view.findViewById(R.id.url); |
+ url.setText(templateUrl.getUrl()); |
+ if (templateUrl.getType() == TemplateUrlService.TYPE_PREPOPULATED |
+ || templateUrl.getType() == TemplateUrlService.TYPE_DEFAULT |
+ || templateUrl.getUrl().length() == 0) { |
+ url.setVisibility(View.GONE); |
+ } |
+ |
// To improve the explore-by-touch experience, the radio button is hidden from accessibility |
// and instead, "checked" or "not checked" is read along with the search engine's name, e.g. |
// "google.com checked" or "google.com not checked". |
@@ -202,7 +253,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
} |
}); |
- TextView link = (TextView) view.findViewById(R.id.link); |
+ TextView link = (TextView) view.findViewById(R.id.location_permission); |
link.setVisibility(selected ? View.VISIBLE : View.GONE); |
if (selected) { |
if (getLocationPermissionType(position, true) == ContentSetting.ASK) { |
@@ -251,7 +302,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
} |
} |
- private void searchEngineSelected(int position) { |
+ private String searchEngineSelected(int position) { |
// First clean up any automatically added permissions (if any) for the previously selected |
// search engine. |
SharedPreferences sharedPreferences = |
@@ -259,7 +310,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
if (sharedPreferences.getBoolean(PrefServiceBridge.LOCATION_AUTO_ALLOWED, false)) { |
if (locationEnabled(mSelectedSearchEnginePosition, false)) { |
String url = TemplateUrlService.getInstance().getSearchEngineUrlFromTemplateUrl( |
- toIndex(mSelectedSearchEnginePosition)); |
+ toKeyword(mSelectedSearchEnginePosition)); |
WebsitePreferenceBridge.nativeSetGeolocationSettingForOrigin( |
url, url, ContentSetting.DEFAULT.toInt(), false); |
} |
@@ -269,10 +320,17 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
// Record the change in search engine. |
mSelectedSearchEnginePosition = position; |
- // Report the change back. |
- mCallback.currentSearchEngineDetermined(toIndex(mSelectedSearchEnginePosition)); |
+ String keyword = toKeyword(mSelectedSearchEnginePosition); |
+ TemplateUrlService.getInstance().setSearchEngine(keyword); |
+ // If the user has manually set the default search engine, disable auto switching. |
+ boolean manualSwitch = mSelectedSearchEnginePosition != mInitialEnginePosition; |
+ if (manualSwitch) { |
+ RecordUserAction.record("SearchEngine_ManualChange"); |
+ LocaleManager.getInstance().setSearchEngineAutoSwitch(false); |
+ } |
notifyDataSetChanged(); |
+ return keyword; |
} |
private void onLocationLinkClicked() { |
@@ -282,7 +340,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
Intent settingsIntent = PreferencesLauncher.createIntentForSettingsPage( |
mContext, SingleWebsitePreferences.class.getName()); |
String url = TemplateUrlService.getInstance().getSearchEngineUrlFromTemplateUrl( |
- toIndex(mSelectedSearchEnginePosition)); |
+ toKeyword(mSelectedSearchEnginePosition)); |
Bundle fragmentArgs = SingleWebsitePreferences.createFragmentArgsForSite(url); |
fragmentArgs.putBoolean(SingleWebsitePreferences.EXTRA_LOCATION, |
locationEnabled(mSelectedSearchEnginePosition, true)); |
@@ -297,7 +355,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
} |
String url = TemplateUrlService.getInstance().getSearchEngineUrlFromTemplateUrl( |
- toIndex(position)); |
+ toKeyword(position)); |
GeolocationInfo locationSettings = new GeolocationInfo(url, null, false); |
ContentSetting locationPermission = locationSettings.getContentSetting(); |
if (locationPermission == ContentSetting.ASK) { |
@@ -314,4 +372,7 @@ public class SearchEngineAdapter extends BaseAdapter implements LoadListener, On |
return getLocationPermissionType(position, checkGeoHeader) == ContentSetting.ALLOW; |
} |
+ private int computeStartIndexForRecentSearchEngines() { |
+ return mPrepopulatedSearchEngines.size() + 1; |
+ } |
} |