blob: 41d2b748b0467d601ec9f929b8a2176a5b6db780 [file] [log] [blame]
Michael Kolb21ce4d22010-09-15 14:55:05 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
Michael Kolb21ce4d22010-09-15 14:55:05 -070018
Michael Kolb21ce4d22010-09-15 14:55:05 -070019import android.app.SearchManager;
20import android.content.Context;
21import android.database.Cursor;
22import android.net.Uri;
John Reck35defff2010-11-11 14:06:45 -080023import android.os.AsyncTask;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080024
Bijan Amirzada41242f22014-03-21 12:12:18 -070025import com.android.browser.R;
26import com.android.browser.platformsupport.BrowserContract;
27import com.android.browser.provider.BrowserProvider2.OmniboxSuggestions;
28import com.android.browser.search.SearchEngine;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080029
Narayan Kamath5119edd2011-02-23 15:49:17 +000030import android.text.Html;
Michael Kolb21ce4d22010-09-15 14:55:05 -070031import android.text.TextUtils;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.View.OnClickListener;
35import android.view.ViewGroup;
36import android.widget.BaseAdapter;
37import android.widget.Filter;
38import android.widget.Filterable;
39import android.widget.ImageView;
Michael Kolb21ce4d22010-09-15 14:55:05 -070040import android.widget.TextView;
41
Michael Kolb5ff5c8b2012-05-03 11:37:58 -070042
Michael Kolb21ce4d22010-09-15 14:55:05 -070043import java.util.ArrayList;
44import java.util.List;
Michael Kolb21ce4d22010-09-15 14:55:05 -070045
46/**
47 * adapter to wrap multiple cursors for url/search completions
48 */
Michael Kolbbd2dd642011-01-13 13:01:30 -080049public class SuggestionsAdapter extends BaseAdapter implements Filterable,
50 OnClickListener {
Michael Kolb21ce4d22010-09-15 14:55:05 -070051
Narayan Kamath5119edd2011-02-23 15:49:17 +000052 public static final int TYPE_BOOKMARK = 0;
53 public static final int TYPE_HISTORY = 1;
54 public static final int TYPE_SUGGEST_URL = 2;
55 public static final int TYPE_SEARCH = 3;
56 public static final int TYPE_SUGGEST = 4;
Michael Kolb21ce4d22010-09-15 14:55:05 -070057
John Reck5e8466f2011-07-28 17:48:58 -070058 private static final String[] COMBINED_PROJECTION = {
59 OmniboxSuggestions._ID,
60 OmniboxSuggestions.TITLE,
61 OmniboxSuggestions.URL,
62 OmniboxSuggestions.IS_BOOKMARK
63 };
Michael Kolb21ce4d22010-09-15 14:55:05 -070064
Michael Kolb21ce4d22010-09-15 14:55:05 -070065 private static final String COMBINED_SELECTION =
66 "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
67
Narayan Kamath5119edd2011-02-23 15:49:17 +000068 final Context mContext;
69 final Filter mFilter;
John Reck35defff2010-11-11 14:06:45 -080070 SuggestionResults mMixedResults;
71 List<SuggestItem> mSuggestResults, mFilterResults;
Michael Kolb21ce4d22010-09-15 14:55:05 -070072 List<CursorSource> mSources;
73 boolean mLandscapeMode;
Narayan Kamath5119edd2011-02-23 15:49:17 +000074 final CompletionListener mListener;
75 final int mLinesPortrait;
76 final int mLinesLandscape;
77 final Object mResultsLock = new Object();
John Reck117f07d2011-01-24 09:39:03 -080078 boolean mIncognitoMode;
John Reck35e9dd62011-04-25 09:01:54 -070079 BrowserSettings mSettings;
Michael Kolb21ce4d22010-09-15 14:55:05 -070080
81 interface CompletionListener {
82
83 public void onSearch(String txt);
84
Michael Kolbbd2dd642011-01-13 13:01:30 -080085 public void onSelect(String txt, int type, String extraData);
Michael Kolb21ce4d22010-09-15 14:55:05 -070086
87 }
88
89 public SuggestionsAdapter(Context ctx, CompletionListener listener) {
90 mContext = ctx;
John Reck35e9dd62011-04-25 09:01:54 -070091 mSettings = BrowserSettings.getInstance();
Michael Kolb21ce4d22010-09-15 14:55:05 -070092 mListener = listener;
93 mLinesPortrait = mContext.getResources().
94 getInteger(R.integer.max_suggest_lines_portrait);
95 mLinesLandscape = mContext.getResources().
96 getInteger(R.integer.max_suggest_lines_landscape);
Narayan Kamath5119edd2011-02-23 15:49:17 +000097
Michael Kolb21ce4d22010-09-15 14:55:05 -070098 mFilter = new SuggestFilter();
Michael Kolb21ce4d22010-09-15 14:55:05 -070099 addSource(new CombinedCursor());
100 }
101
102 public void setLandscapeMode(boolean mode) {
103 mLandscapeMode = mode;
John Reck35defff2010-11-11 14:06:45 -0800104 notifyDataSetChanged();
Michael Kolb21ce4d22010-09-15 14:55:05 -0700105 }
106
Michael Kolb21ce4d22010-09-15 14:55:05 -0700107 public void addSource(CursorSource c) {
108 if (mSources == null) {
109 mSources = new ArrayList<CursorSource>(5);
110 }
111 mSources.add(c);
112 }
113
114 @Override
115 public void onClick(View v) {
John Reckad373302010-12-17 15:28:13 -0800116 SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
Narayan Kamath5119edd2011-02-23 15:49:17 +0000117
Michael Kolb21ce4d22010-09-15 14:55:05 -0700118 if (R.id.icon2 == v.getId()) {
119 // replace input field text with suggestion text
Narayan Kamath5119edd2011-02-23 15:49:17 +0000120 mListener.onSearch(getSuggestionUrl(item));
Michael Kolb21ce4d22010-09-15 14:55:05 -0700121 } else {
Narayan Kamath5119edd2011-02-23 15:49:17 +0000122 mListener.onSelect(getSuggestionUrl(item), item.type, item.extra);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700123 }
124 }
125
126 @Override
127 public Filter getFilter() {
128 return mFilter;
129 }
130
131 @Override
132 public int getCount() {
John Reck35defff2010-11-11 14:06:45 -0800133 return (mMixedResults == null) ? 0 : mMixedResults.getLineCount();
Michael Kolb21ce4d22010-09-15 14:55:05 -0700134 }
135
136 @Override
137 public SuggestItem getItem(int position) {
John Reck35defff2010-11-11 14:06:45 -0800138 if (mMixedResults == null) {
Michael Kolb21ce4d22010-09-15 14:55:05 -0700139 return null;
140 }
John Reckad373302010-12-17 15:28:13 -0800141 return mMixedResults.items.get(position);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700142 }
143
144 @Override
145 public long getItemId(int position) {
John Reck1605bef2011-01-10 18:11:18 -0800146 return position;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700147 }
148
149 @Override
150 public View getView(int position, View convertView, ViewGroup parent) {
151 final LayoutInflater inflater = LayoutInflater.from(mContext);
John Reck35defff2010-11-11 14:06:45 -0800152 View view = convertView;
153 if (view == null) {
John Reckad373302010-12-17 15:28:13 -0800154 view = inflater.inflate(R.layout.suggestion_item, parent, false);
John Reck35defff2010-11-11 14:06:45 -0800155 }
John Reckad373302010-12-17 15:28:13 -0800156 bindView(view, getItem(position));
157 return view;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700158 }
159
160 private void bindView(View view, SuggestItem item) {
161 // store item for click handling
162 view.setTag(item);
163 TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
164 TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
165 ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700166 View ic2 = view.findViewById(R.id.icon2);
Michael Kolb7b20ddd2010-10-14 15:03:28 -0700167 View div = view.findViewById(R.id.divider);
Narayan Kamath5119edd2011-02-23 15:49:17 +0000168 tv1.setText(Html.fromHtml(item.title));
John Reckad373302010-12-17 15:28:13 -0800169 if (TextUtils.isEmpty(item.url)) {
170 tv2.setVisibility(View.GONE);
John Reck6a9afa92011-07-29 10:18:41 -0700171 tv1.setMaxLines(2);
John Reckad373302010-12-17 15:28:13 -0800172 } else {
173 tv2.setVisibility(View.VISIBLE);
174 tv2.setText(item.url);
John Reck6a9afa92011-07-29 10:18:41 -0700175 tv1.setMaxLines(1);
John Reckad373302010-12-17 15:28:13 -0800176 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700177 int id = -1;
178 switch (item.type) {
179 case TYPE_SUGGEST:
180 case TYPE_SEARCH:
181 id = R.drawable.ic_search_category_suggest;
182 break;
183 case TYPE_BOOKMARK:
184 id = R.drawable.ic_search_category_bookmark;
185 break;
186 case TYPE_HISTORY:
187 id = R.drawable.ic_search_category_history;
188 break;
189 case TYPE_SUGGEST_URL:
190 id = R.drawable.ic_search_category_browser;
191 break;
192 default:
193 id = -1;
194 }
195 if (id != -1) {
196 ic1.setImageDrawable(mContext.getResources().getDrawable(id));
197 }
Michael Kolbbd2dd642011-01-13 13:01:30 -0800198 ic2.setVisibility(((TYPE_SUGGEST == item.type)
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700199 || (TYPE_SEARCH == item.type))
Michael Kolb21ce4d22010-09-15 14:55:05 -0700200 ? View.VISIBLE : View.GONE);
Michael Kolb7b20ddd2010-10-14 15:03:28 -0700201 div.setVisibility(ic2.getVisibility());
Michael Kolb21ce4d22010-09-15 14:55:05 -0700202 ic2.setOnClickListener(this);
John Reckad373302010-12-17 15:28:13 -0800203 view.findViewById(R.id.suggestion).setOnClickListener(this);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700204 }
205
John Reck35defff2010-11-11 14:06:45 -0800206 class SlowFilterTask extends AsyncTask<CharSequence, Void, List<SuggestItem>> {
Michael Kolb21ce4d22010-09-15 14:55:05 -0700207
John Reck35defff2010-11-11 14:06:45 -0800208 @Override
209 protected List<SuggestItem> doInBackground(CharSequence... params) {
210 SuggestCursor cursor = new SuggestCursor();
211 cursor.runQuery(params[0]);
212 List<SuggestItem> results = new ArrayList<SuggestItem>();
213 int count = cursor.getCount();
214 for (int i = 0; i < count; i++) {
215 results.add(cursor.getItem());
216 cursor.moveToNext();
217 }
218 cursor.close();
219 return results;
220 }
221
222 @Override
223 protected void onPostExecute(List<SuggestItem> items) {
224 mSuggestResults = items;
225 mMixedResults = buildSuggestionResults();
226 notifyDataSetChanged();
John Reck35defff2010-11-11 14:06:45 -0800227 }
228 }
229
230 SuggestionResults buildSuggestionResults() {
231 SuggestionResults mixed = new SuggestionResults();
232 List<SuggestItem> filter, suggest;
233 synchronized (mResultsLock) {
234 filter = mFilterResults;
235 suggest = mSuggestResults;
236 }
237 if (filter != null) {
238 for (SuggestItem item : filter) {
239 mixed.addResult(item);
240 }
241 }
242 if (suggest != null) {
243 for (SuggestItem item : suggest) {
244 mixed.addResult(item);
245 }
246 }
247 return mixed;
248 }
249
250 class SuggestFilter extends Filter {
Michael Kolb21ce4d22010-09-15 14:55:05 -0700251
252 @Override
253 public CharSequence convertResultToString(Object item) {
254 if (item == null) {
255 return "";
256 }
257 SuggestItem sitem = (SuggestItem) item;
258 if (sitem.title != null) {
259 return sitem.title;
260 } else {
261 return sitem.url;
262 }
263 }
264
John Reck35defff2010-11-11 14:06:45 -0800265 void startSuggestionsAsync(final CharSequence constraint) {
John Reck117f07d2011-01-24 09:39:03 -0800266 if (!mIncognitoMode) {
267 new SlowFilterTask().execute(constraint);
268 }
John Reck35defff2010-11-11 14:06:45 -0800269 }
270
Narayan Kamath5119edd2011-02-23 15:49:17 +0000271 private boolean shouldProcessEmptyQuery() {
John Reck35e9dd62011-04-25 09:01:54 -0700272 final SearchEngine searchEngine = mSettings.getSearchEngine();
Narayan Kamath5119edd2011-02-23 15:49:17 +0000273 return searchEngine.wantsEmptyQuery();
274 }
275
Michael Kolb21ce4d22010-09-15 14:55:05 -0700276 @Override
277 protected FilterResults performFiltering(CharSequence constraint) {
278 FilterResults res = new FilterResults();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700279 if (TextUtils.isEmpty(constraint) && !shouldProcessEmptyQuery()) {
280 res.count = 0;
281 res.values = null;
282 return res;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700283 }
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700284 startSuggestionsAsync(constraint);
285 List<SuggestItem> filterResults = new ArrayList<SuggestItem>();
286 if (constraint != null) {
287 for (CursorSource sc : mSources) {
288 sc.runQuery(constraint);
289 }
290 mixResults(filterResults);
291 }
292 synchronized (mResultsLock) {
293 mFilterResults = filterResults;
294 }
295 SuggestionResults mixed = buildSuggestionResults();
296 res.count = mixed.getLineCount();
297 res.values = mixed;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700298 return res;
299 }
300
John Reck35defff2010-11-11 14:06:45 -0800301 void mixResults(List<SuggestItem> results) {
Narayan Kamath5119edd2011-02-23 15:49:17 +0000302 int maxLines = getMaxLines();
Michael Kolb21ce4d22010-09-15 14:55:05 -0700303 for (int i = 0; i < mSources.size(); i++) {
304 CursorSource s = mSources.get(i);
John Reck35defff2010-11-11 14:06:45 -0800305 int n = Math.min(s.getCount(), maxLines);
306 maxLines -= n;
Michael Kolb0506f2d2010-10-14 16:20:16 -0700307 boolean more = false;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700308 for (int j = 0; j < n; j++) {
John Reck35defff2010-11-11 14:06:45 -0800309 results.add(s.getItem());
Michael Kolb21ce4d22010-09-15 14:55:05 -0700310 more = s.moveToNext();
311 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700312 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700313 }
314
315 @Override
316 protected void publishResults(CharSequence constraint, FilterResults fresults) {
Michael Kolbcfa3af52010-12-14 10:36:11 -0800317 if (fresults.values instanceof SuggestionResults) {
318 mMixedResults = (SuggestionResults) fresults.values;
John Recka005cd72011-02-01 11:46:53 -0800319 notifyDataSetChanged();
Michael Kolbcfa3af52010-12-14 10:36:11 -0800320 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700321 }
Narayan Kamath5119edd2011-02-23 15:49:17 +0000322 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700323
Narayan Kamath5119edd2011-02-23 15:49:17 +0000324 private int getMaxLines() {
325 int maxLines = mLandscapeMode ? mLinesLandscape : mLinesPortrait;
326 maxLines = (int) Math.ceil(maxLines / 2.0);
327 return maxLines;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700328 }
329
330 /**
331 * sorted list of results of a suggestion query
332 *
333 */
334 class SuggestionResults {
335
336 ArrayList<SuggestItem> items;
337 // count per type
338 int[] counts;
339
340 SuggestionResults() {
341 items = new ArrayList<SuggestItem>(24);
342 // n of types:
343 counts = new int[5];
344 }
345
346 int getTypeCount(int type) {
347 return counts[type];
348 }
349
350 void addResult(SuggestItem item) {
351 int ix = 0;
352 while ((ix < items.size()) && (item.type >= items.get(ix).type))
353 ix++;
354 items.add(ix, item);
355 counts[item.type]++;
356 }
357
358 int getLineCount() {
Narayan Kamath5119edd2011-02-23 15:49:17 +0000359 return Math.min((mLandscapeMode ? mLinesLandscape : mLinesPortrait), items.size());
Michael Kolb21ce4d22010-09-15 14:55:05 -0700360 }
361
John Reck35defff2010-11-11 14:06:45 -0800362 @Override
Michael Kolb21ce4d22010-09-15 14:55:05 -0700363 public String toString() {
364 if (items == null) return null;
365 if (items.size() == 0) return "[]";
366 StringBuilder sb = new StringBuilder();
367 for (int i = 0; i < items.size(); i++) {
368 SuggestItem item = items.get(i);
369 sb.append(item.type + ": " + item.title);
370 if (i < items.size() - 1) {
371 sb.append(", ");
372 }
373 }
374 return sb.toString();
375 }
376 }
377
378 /**
379 * data object to hold suggestion values
380 */
Narayan Kamath80aad8d2011-02-23 12:01:13 +0000381 public class SuggestItem {
382 public String title;
383 public String url;
384 public int type;
385 public String extra;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700386
387 public SuggestItem(String text, String u, int t) {
388 title = text;
389 url = u;
390 type = t;
391 }
Michael Kolbbd2dd642011-01-13 13:01:30 -0800392
Michael Kolb21ce4d22010-09-15 14:55:05 -0700393 }
394
395 abstract class CursorSource {
396
397 Cursor mCursor;
398
399 boolean moveToNext() {
400 return mCursor.moveToNext();
401 }
402
403 public abstract void runQuery(CharSequence constraint);
404
405 public abstract SuggestItem getItem();
406
407 public int getCount() {
408 return (mCursor != null) ? mCursor.getCount() : 0;
409 }
410
411 public void close() {
412 if (mCursor != null) {
413 mCursor.close();
414 }
415 }
416 }
417
418 /**
419 * combined bookmark & history source
420 */
421 class CombinedCursor extends CursorSource {
422
423 @Override
424 public SuggestItem getItem() {
425 if ((mCursor != null) && (!mCursor.isAfterLast())) {
426 String title = mCursor.getString(1);
427 String url = mCursor.getString(2);
428 boolean isBookmark = (mCursor.getInt(3) == 1);
429 return new SuggestItem(getTitle(title, url), getUrl(title, url),
430 isBookmark ? TYPE_BOOKMARK : TYPE_HISTORY);
431 }
432 return null;
433 }
434
435 @Override
436 public void runQuery(CharSequence constraint) {
437 // constraint != null
438 if (mCursor != null) {
439 mCursor.close();
440 }
441 String like = constraint + "%";
442 String[] args = null;
443 String selection = null;
444 if (like.startsWith("http") || like.startsWith("file")) {
445 args = new String[1];
446 args[0] = like;
447 selection = "url LIKE ?";
448 } else {
449 args = new String[5];
450 args[0] = "http://" + like;
451 args[1] = "http://www." + like;
452 args[2] = "https://" + like;
453 args[3] = "https://www." + like;
454 // To match against titles.
455 args[4] = like;
456 selection = COMBINED_SELECTION;
457 }
John Reck5e8466f2011-07-28 17:48:58 -0700458 Uri.Builder ub = OmniboxSuggestions.CONTENT_URI.buildUpon();
Michael Kolb0506f2d2010-10-14 16:20:16 -0700459 ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
John Reckad373302010-12-17 15:28:13 -0800460 Integer.toString(Math.max(mLinesLandscape, mLinesPortrait)));
Michael Kolb21ce4d22010-09-15 14:55:05 -0700461 mCursor =
Michael Kolb0506f2d2010-10-14 16:20:16 -0700462 mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION,
John Reck5e8466f2011-07-28 17:48:58 -0700463 selection, (constraint != null) ? args : null, null);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700464 if (mCursor != null) {
465 mCursor.moveToFirst();
466 }
467 }
468
469 /**
470 * Provides the title (text line 1) for a browser suggestion, which should be the
471 * webpage title. If the webpage title is empty, returns the stripped url instead.
472 *
473 * @return the title string to use
474 */
475 private String getTitle(String title, String url) {
476 if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
John Reckfb3017f2010-10-26 19:01:24 -0700477 title = UrlUtils.stripUrl(url);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700478 }
479 return title;
480 }
481
482 /**
483 * Provides the subtitle (text line 2) for a browser suggestion, which should be the
484 * webpage url. If the webpage title is empty, then the url should go in the title
485 * instead, and the subtitle should be empty, so this would return null.
486 *
487 * @return the subtitle string to use, or null if none
488 */
489 private String getUrl(String title, String url) {
John Reck7d132b12010-10-26 15:10:21 -0700490 if (TextUtils.isEmpty(title)
491 || TextUtils.getTrimmedLength(title) == 0
492 || title.equals(url)) {
Michael Kolb21ce4d22010-09-15 14:55:05 -0700493 return null;
494 } else {
John Reckfb3017f2010-10-26 19:01:24 -0700495 return UrlUtils.stripUrl(url);
Michael Kolb21ce4d22010-09-15 14:55:05 -0700496 }
497 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700498 }
499
Michael Kolb21ce4d22010-09-15 14:55:05 -0700500 class SuggestCursor extends CursorSource {
501
502 @Override
503 public SuggestItem getItem() {
504 if (mCursor != null) {
505 String title = mCursor.getString(
506 mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
507 String text2 = mCursor.getString(
508 mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
509 String url = mCursor.getString(
510 mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
511 String uri = mCursor.getString(
512 mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
513 int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
John Reck40f720e2010-11-10 11:57:04 -0800514 SuggestItem item = new SuggestItem(title, url, type);
515 item.extra = mCursor.getString(
516 mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA));
517 return item;
Michael Kolb21ce4d22010-09-15 14:55:05 -0700518 }
519 return null;
520 }
521
522 @Override
523 public void runQuery(CharSequence constraint) {
524 if (mCursor != null) {
525 mCursor.close();
526 }
John Reck35e9dd62011-04-25 09:01:54 -0700527 SearchEngine searchEngine = mSettings.getSearchEngine();
Michael Kolb21ce4d22010-09-15 14:55:05 -0700528 if (!TextUtils.isEmpty(constraint)) {
Michael Kolb21ce4d22010-09-15 14:55:05 -0700529 if (searchEngine != null && searchEngine.supportsSuggestions()) {
530 mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
531 if (mCursor != null) {
532 mCursor.moveToFirst();
533 }
534 }
535 } else {
Narayan Kamath5119edd2011-02-23 15:49:17 +0000536 if (searchEngine.wantsEmptyQuery()) {
537 mCursor = searchEngine.getSuggestions(mContext, "");
538 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700539 mCursor = null;
540 }
541 }
542
543 }
544
John Reck35defff2010-11-11 14:06:45 -0800545 public void clearCache() {
546 mFilterResults = null;
547 mSuggestResults = null;
Narayan Kamath5119edd2011-02-23 15:49:17 +0000548 notifyDataSetInvalidated();
John Reck35defff2010-11-11 14:06:45 -0800549 }
550
John Reck117f07d2011-01-24 09:39:03 -0800551 public void setIncognitoMode(boolean incognito) {
552 mIncognitoMode = incognito;
553 clearCache();
554 }
Narayan Kamath5119edd2011-02-23 15:49:17 +0000555
556 static String getSuggestionTitle(SuggestItem item) {
557 // There must be a better way to strip HTML from things.
558 // This method is used in multiple places. It is also more
559 // expensive than a standard html escaper.
560 return (item.title != null) ? Html.fromHtml(item.title).toString() : null;
561 }
562
563 static String getSuggestionUrl(SuggestItem item) {
564 final String title = SuggestionsAdapter.getSuggestionTitle(item);
565
566 if (TextUtils.isEmpty(item.url)) {
567 return title;
568 }
569
570 return item.url;
571 }
Michael Kolb21ce4d22010-09-15 14:55:05 -0700572}