SuggestionsAdapter.java revision 5119edd5744cfc6d3a8ed480a8853586c737bed4
121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb/*
221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * Copyright (C) 2010 The Android Open Source Project
321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb *
421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * you may not use this file except in compliance with the License.
621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * You may obtain a copy of the License at
721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb *
821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb *
1021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * Unless required by applicable law or agreed to in writing, software
1121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
1221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * See the License for the specific language governing permissions and
1421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * limitations under the License.
1521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb */
1621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
1721ce4d295802db811873b46e7821abfa0540dab2Michael Kolbpackage com.android.browser;
1821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
1921ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport com.android.browser.search.SearchEngine;
2021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
2121ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.app.SearchManager;
2221ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.content.Context;
2321ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.database.Cursor;
2421ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.net.Uri;
2535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reckimport android.os.AsyncTask;
2621ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.provider.BrowserContract;
275119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamathimport android.text.Html;
2821ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.text.TextUtils;
2921ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.LayoutInflater;
3021ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.View;
3121ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.View.OnClickListener;
3221ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.ViewGroup;
3321ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.BaseAdapter;
3421ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.Filter;
3521ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.Filterable;
3621ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.ImageView;
3721ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.TextView;
3821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
3921ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.ArrayList;
4021ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.List;
4121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
4221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb/**
4321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * adapter to wrap multiple cursors for url/search completions
4421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb */
45bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolbpublic class SuggestionsAdapter extends BaseAdapter implements Filterable,
46bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb        OnClickListener {
4721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
485119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_BOOKMARK = 0;
495119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_HISTORY = 1;
505119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_SUGGEST_URL = 2;
515119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_SEARCH = 3;
525119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_SUGGEST = 4;
535119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    public static final int TYPE_VOICE_SEARCH = 5;
5421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
5521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final String[] COMBINED_PROJECTION =
5621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            {BrowserContract.Combined._ID, BrowserContract.Combined.TITLE,
5721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    BrowserContract.Combined.URL, BrowserContract.Combined.IS_BOOKMARK};
5821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
5921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final String COMBINED_SELECTION =
6021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
6121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
625119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final Context mContext;
635119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final Filter mFilter;
6435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    SuggestionResults mMixedResults;
6535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    List<SuggestItem> mSuggestResults, mFilterResults;
6621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    List<CursorSource> mSources;
6721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    boolean mLandscapeMode;
685119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final CompletionListener mListener;
695119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final int mLinesPortrait;
705119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final int mLinesLandscape;
715119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    final Object mResultsLock = new Object();
72cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb    List<String> mVoiceResults;
731605bef4e1f99805a801308f97ade622b907dc7aJohn Reck    boolean mReverseResults;
74117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck    boolean mIncognitoMode;
7521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
7621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    interface CompletionListener {
7721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
7821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void onSearch(String txt);
7921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
80bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb        public void onSelect(String txt, int type, String extraData);
8121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
8221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
8321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
8421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public SuggestionsAdapter(Context ctx, CompletionListener listener) {
8521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mContext = ctx;
8621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mListener = listener;
8721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mLinesPortrait = mContext.getResources().
8821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                getInteger(R.integer.max_suggest_lines_portrait);
8921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mLinesLandscape = mContext.getResources().
9021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                getInteger(R.integer.max_suggest_lines_landscape);
915119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
9221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mFilter = new SuggestFilter();
9321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        addSource(new CombinedCursor());
9421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
9521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
96cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb    void setVoiceResults(List<String> voiceResults) {
97cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        mVoiceResults = voiceResults;
98a50c446037eecaa2dcd83dab133bd9dc390ede69Michael Kolb        notifyDataSetChanged();
99cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb    }
100cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb
10121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void setLandscapeMode(boolean mode) {
10221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mLandscapeMode = mode;
10335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        notifyDataSetChanged();
10421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
10521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
10621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void addSource(CursorSource c) {
10721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (mSources == null) {
10821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mSources = new ArrayList<CursorSource>(5);
10921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
11021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mSources.add(c);
11121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
11221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
11321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
11421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void onClick(View v) {
115ad373302b1e1a322144f818340fdce60f0eee403John Reck        SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
1165119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
11721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (R.id.icon2 == v.getId()) {
11821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // replace input field text with suggestion text
1195119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            mListener.onSearch(getSuggestionUrl(item));
12021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        } else {
1215119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            mListener.onSelect(getSuggestionUrl(item), item.type, item.extra);
12221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
12321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
12421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
12521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
12621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public Filter getFilter() {
12721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return mFilter;
12821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
12921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
13021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
13121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public int getCount() {
132cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        if (mVoiceResults != null) {
133cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb            return mVoiceResults.size();
134cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        }
13535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        return (mMixedResults == null) ? 0 : mMixedResults.getLineCount();
13621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
13721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
13821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
13921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public SuggestItem getItem(int position) {
1401605bef4e1f99805a801308f97ade622b907dc7aJohn Reck        if (mReverseResults) {
1411605bef4e1f99805a801308f97ade622b907dc7aJohn Reck            position = (getCount() - 1) - position;
1421605bef4e1f99805a801308f97ade622b907dc7aJohn Reck        }
143cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        if (mVoiceResults != null) {
144bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb            SuggestItem item = new SuggestItem(mVoiceResults.get(position),
145bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb                    null, TYPE_VOICE_SEARCH);
146bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb            item.extra = Integer.toString(position);
147bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb            return item;
148cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb        }
14935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        if (mMixedResults == null) {
15021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
15121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
152ad373302b1e1a322144f818340fdce60f0eee403John Reck        return mMixedResults.items.get(position);
15321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
15421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
1551605bef4e1f99805a801308f97ade622b907dc7aJohn Reck    public void setReverseResults(boolean reverse) {
1561605bef4e1f99805a801308f97ade622b907dc7aJohn Reck        mReverseResults = reverse;
1571605bef4e1f99805a801308f97ade622b907dc7aJohn Reck    }
1581605bef4e1f99805a801308f97ade622b907dc7aJohn Reck
15921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
16021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public long getItemId(int position) {
1611605bef4e1f99805a801308f97ade622b907dc7aJohn Reck        return position;
16221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
16321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
16421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
16521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public View getView(int position, View convertView, ViewGroup parent) {
16621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        final LayoutInflater inflater = LayoutInflater.from(mContext);
16735defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        View view = convertView;
16835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        if (view == null) {
169ad373302b1e1a322144f818340fdce60f0eee403John Reck            view = inflater.inflate(R.layout.suggestion_item, parent, false);
17021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
171ad373302b1e1a322144f818340fdce60f0eee403John Reck        bindView(view, getItem(position));
172ad373302b1e1a322144f818340fdce60f0eee403John Reck        return view;
17321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
17421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
17521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private void bindView(View view, SuggestItem item) {
17621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        // store item for click handling
17721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        view.setTag(item);
17821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
17921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
18021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
18121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        View ic2 = view.findViewById(R.id.icon2);
1827b20ddd4f03d59cca8fdd4aee790784421570aabMichael Kolb        View div = view.findViewById(R.id.divider);
1835119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        tv1.setText(Html.fromHtml(item.title));
184ad373302b1e1a322144f818340fdce60f0eee403John Reck        if (TextUtils.isEmpty(item.url)) {
185ad373302b1e1a322144f818340fdce60f0eee403John Reck            tv2.setVisibility(View.GONE);
186ad373302b1e1a322144f818340fdce60f0eee403John Reck        } else {
187ad373302b1e1a322144f818340fdce60f0eee403John Reck            tv2.setVisibility(View.VISIBLE);
188ad373302b1e1a322144f818340fdce60f0eee403John Reck            tv2.setText(item.url);
189ad373302b1e1a322144f818340fdce60f0eee403John Reck        }
19021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int id = -1;
19121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        switch (item.type) {
19221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SUGGEST:
19321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SEARCH:
194bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb            case TYPE_VOICE_SEARCH:
19521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_suggest;
19621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
19721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_BOOKMARK:
19821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_bookmark;
19921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
20021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_HISTORY:
20121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_history;
20221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
20321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SUGGEST_URL:
20421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_browser;
20521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
20621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            default:
20721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = -1;
20821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
20921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (id != -1) {
21021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            ic1.setImageDrawable(mContext.getResources().getDrawable(id));
21121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
212bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb        ic2.setVisibility(((TYPE_SUGGEST == item.type)
213bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb                || (TYPE_SEARCH == item.type)
214bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb                || (TYPE_VOICE_SEARCH == item.type))
21521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                ? View.VISIBLE : View.GONE);
2167b20ddd4f03d59cca8fdd4aee790784421570aabMichael Kolb        div.setVisibility(ic2.getVisibility());
21721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ic2.setOnClickListener(this);
218ad373302b1e1a322144f818340fdce60f0eee403John Reck        view.findViewById(R.id.suggestion).setOnClickListener(this);
21921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
22021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
22135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    class SlowFilterTask extends AsyncTask<CharSequence, Void, List<SuggestItem>> {
22235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck
22335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        @Override
22435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        protected List<SuggestItem> doInBackground(CharSequence... params) {
22535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            SuggestCursor cursor = new SuggestCursor();
22635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            cursor.runQuery(params[0]);
22735defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            List<SuggestItem> results = new ArrayList<SuggestItem>();
22835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            int count = cursor.getCount();
22935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            for (int i = 0; i < count; i++) {
23035defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                results.add(cursor.getItem());
23135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                cursor.moveToNext();
23235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            }
23335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            cursor.close();
23435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            return results;
23535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
23635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck
23735defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        @Override
23835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        protected void onPostExecute(List<SuggestItem> items) {
23935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            mSuggestResults = items;
24035defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            mMixedResults = buildSuggestionResults();
24135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            notifyDataSetChanged();
24235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
24335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    }
24435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck
24535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    SuggestionResults buildSuggestionResults() {
24635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        SuggestionResults mixed = new SuggestionResults();
24735defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        List<SuggestItem> filter, suggest;
24835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        synchronized (mResultsLock) {
24935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            filter = mFilterResults;
25035defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            suggest = mSuggestResults;
25135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
25235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        if (filter != null) {
25335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            for (SuggestItem item : filter) {
25435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                mixed.addResult(item);
25535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            }
25635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
25735defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        if (suggest != null) {
25835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            for (SuggestItem item : suggest) {
25935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                mixed.addResult(item);
26035defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck            }
26135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
26235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        return mixed;
26335defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    }
26421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
26535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    class SuggestFilter extends Filter {
26621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
26721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
26821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public CharSequence convertResultToString(Object item) {
26921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (item == null) {
27021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return "";
27121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
27221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            SuggestItem sitem = (SuggestItem) item;
27321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (sitem.title != null) {
27421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return sitem.title;
27521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
27621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return sitem.url;
27721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
27821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
27921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
28035defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        void startSuggestionsAsync(final CharSequence constraint) {
281117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck            if (!mIncognitoMode) {
282117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck                new SlowFilterTask().execute(constraint);
283117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck            }
28435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        }
28535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck
2865119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        private boolean shouldProcessEmptyQuery() {
2875119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            final SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
2885119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            return searchEngine.wantsEmptyQuery();
2895119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        }
2905119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
29121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
29221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        protected FilterResults performFiltering(CharSequence constraint) {
29321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            FilterResults res = new FilterResults();
294cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb            if (mVoiceResults == null) {
2955119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath                if (TextUtils.isEmpty(constraint) && !shouldProcessEmptyQuery()) {
296cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    res.count = 0;
297cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    res.values = null;
298cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    return res;
29921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
300cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                startSuggestionsAsync(constraint);
301cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                List<SuggestItem> filterResults = new ArrayList<SuggestItem>();
302cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                if (constraint != null) {
303cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    for (CursorSource sc : mSources) {
304cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                        sc.runQuery(constraint);
305cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    }
306cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    mixResults(filterResults);
307cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                }
308cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                synchronized (mResultsLock) {
309cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                    mFilterResults = filterResults;
310cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                }
311cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                SuggestionResults mixed = buildSuggestionResults();
312cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                res.count = mixed.getLineCount();
313cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                res.values = mixed;
314cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb            } else {
315cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                res.count = mVoiceResults.size();
316cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                res.values = mVoiceResults;
31721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
31821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return res;
31921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
32021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
32135defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        void mixResults(List<SuggestItem> results) {
3225119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            int maxLines = getMaxLines();
32321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            for (int i = 0; i < mSources.size(); i++) {
32421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                CursorSource s = mSources.get(i);
32535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                int n = Math.min(s.getCount(), maxLines);
32635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                maxLines -= n;
3270506f2dd9239e23099244e101f7d32d5fc189668Michael Kolb                boolean more = false;
32821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                for (int j = 0; j < n; j++) {
32935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck                    results.add(s.getItem());
33021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    more = s.moveToNext();
33121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
33221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
33321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
33421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
33521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
33621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        protected void publishResults(CharSequence constraint, FilterResults fresults) {
337cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb            if (fresults.values instanceof SuggestionResults) {
338cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb                mMixedResults = (SuggestionResults) fresults.values;
339a005cd7e4091513b189a6573b4fa96d762399c7eJohn Reck                notifyDataSetChanged();
340cfa3af5c59abb38c895416a80ef16da0ec1b5287Michael Kolb            }
34121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
3425119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    }
34321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
3445119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    private int getMaxLines() {
3455119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        int maxLines = mLandscapeMode ? mLinesLandscape : mLinesPortrait;
3465119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        maxLines = (int) Math.ceil(maxLines / 2.0);
3475119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        return maxLines;
34821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
34921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
35021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
35121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * sorted list of results of a suggestion query
35221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     *
35321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
35421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestionResults {
35521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
35621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ArrayList<SuggestItem> items;
35721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        // count per type
35821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int[] counts;
35921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
36021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        SuggestionResults() {
36121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            items = new ArrayList<SuggestItem>(24);
36221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // n of types:
36321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            counts = new int[5];
36421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
36521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
36621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getTypeCount(int type) {
36721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return counts[type];
36821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
36921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
37021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        void addResult(SuggestItem item) {
37121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            int ix = 0;
37221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            while ((ix < items.size()) && (item.type >= items.get(ix).type))
37321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                ix++;
37421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            items.add(ix, item);
37521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            counts[item.type]++;
37621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
37721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
37821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getLineCount() {
3795119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            return Math.min((mLandscapeMode ? mLinesLandscape : mLinesPortrait), items.size());
38021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
38121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
38235defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        @Override
38321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public String toString() {
38421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (items == null) return null;
38521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (items.size() == 0) return "[]";
38621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            StringBuilder sb = new StringBuilder();
38721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            for (int i = 0; i < items.size(); i++) {
38821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                SuggestItem item = items.get(i);
38921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                sb.append(item.type + ": " + item.title);
39021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (i < items.size() - 1) {
39121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    sb.append(", ");
39221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
39321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
39421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return sb.toString();
39521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
39621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
39721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
39821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
39921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * data object to hold suggestion values
40021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
40180aad8d851601d39f73214c198111ca49e25f654Narayan Kamath    public class SuggestItem {
40280aad8d851601d39f73214c198111ca49e25f654Narayan Kamath        public String title;
40380aad8d851601d39f73214c198111ca49e25f654Narayan Kamath        public String url;
40480aad8d851601d39f73214c198111ca49e25f654Narayan Kamath        public int type;
40580aad8d851601d39f73214c198111ca49e25f654Narayan Kamath        public String extra;
40621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
40721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem(String text, String u, int t) {
40821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            title = text;
40921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            url = u;
41021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            type = t;
41121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
412bd2dd64dda88ca8a7c2b148d88c5a44e73e1c331Michael Kolb
41321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
41421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
41521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    abstract class CursorSource {
41621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
41721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        Cursor mCursor;
41821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
41921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        boolean moveToNext() {
42021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return mCursor.moveToNext();
42121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
42221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
42321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public abstract void runQuery(CharSequence constraint);
42421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
42521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public abstract SuggestItem getItem();
42621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
42721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public int getCount() {
42821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return (mCursor != null) ? mCursor.getCount() : 0;
42921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
43021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
43121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void close() {
43221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
43321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
43421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
43521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
43621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
43721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
43821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
43921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * combined bookmark & history source
44021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
44121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class CombinedCursor extends CursorSource {
44221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
44321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
44421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem getItem() {
44521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if ((mCursor != null) && (!mCursor.isAfterLast())) {
44621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String title = mCursor.getString(1);
44721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String url = mCursor.getString(2);
44821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                boolean isBookmark = (mCursor.getInt(3) == 1);
44921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return new SuggestItem(getTitle(title, url), getUrl(title, url),
45021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        isBookmark ? TYPE_BOOKMARK : TYPE_HISTORY);
45121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
45221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
45321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
45421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
45521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
45621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void runQuery(CharSequence constraint) {
45721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // constraint != null
45821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
45921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
46021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
46121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String like = constraint + "%";
46221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String[] args = null;
46321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String selection = null;
46421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (like.startsWith("http") || like.startsWith("file")) {
46521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args = new String[1];
46621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[0] = like;
46721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                selection = "url LIKE ?";
46821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
46921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args = new String[5];
47021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[0] = "http://" + like;
47121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[1] = "http://www." + like;
47221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[2] = "https://" + like;
47321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[3] = "https://www." + like;
47421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                // To match against titles.
47521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[4] = like;
47621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                selection = COMBINED_SELECTION;
47721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
47821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            Uri.Builder ub = BrowserContract.Combined.CONTENT_URI.buildUpon();
4790506f2dd9239e23099244e101f7d32d5fc189668Michael Kolb            ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
480ad373302b1e1a322144f818340fdce60f0eee403John Reck                    Integer.toString(Math.max(mLinesLandscape, mLinesPortrait)));
4813dff1cedc22620ab56fbd39f3703f19bb552ca34John Reck            BookmarkUtils.addAccountInfo(mContext, ub);
48221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mCursor =
4830506f2dd9239e23099244e101f7d32d5fc189668Michael Kolb                    mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION,
48421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            selection,
48521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            (constraint != null) ? args : null,
4863dff1cedc22620ab56fbd39f3703f19bb552ca34John Reck                            BrowserContract.Combined.IS_BOOKMARK + " DESC, " +
48721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            BrowserContract.Combined.VISITS + " DESC, " +
48821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            BrowserContract.Combined.DATE_LAST_VISITED + " DESC");
48921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
49021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.moveToFirst();
49121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
49221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
49321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
49421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        /**
49521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * Provides the title (text line 1) for a browser suggestion, which should be the
49621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * webpage title. If the webpage title is empty, returns the stripped url instead.
49721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
49821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @return the title string to use
49921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         */
50021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        private String getTitle(String title, String url) {
50121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
502fb3017ffd8aa3f2342380270cf468e3a68914e69John Reck                title = UrlUtils.stripUrl(url);
50321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
50421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return title;
50521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
50621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
50721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        /**
50821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * Provides the subtitle (text line 2) for a browser suggestion, which should be the
50921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * webpage url. If the webpage title is empty, then the url should go in the title
51021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * instead, and the subtitle should be empty, so this would return null.
51121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
51221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @return the subtitle string to use, or null if none
51321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         */
51421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        private String getUrl(String title, String url) {
5157d132b17c9dd1a816c68bf8505be2028691aaee3John Reck            if (TextUtils.isEmpty(title)
5167d132b17c9dd1a816c68bf8505be2028691aaee3John Reck                    || TextUtils.getTrimmedLength(title) == 0
5177d132b17c9dd1a816c68bf8505be2028691aaee3John Reck                    || title.equals(url)) {
51821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return null;
51921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
520fb3017ffd8aa3f2342380270cf468e3a68914e69John Reck                return UrlUtils.stripUrl(url);
52121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
52221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
52321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
52421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
52521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestCursor extends CursorSource {
52621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
52721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
52821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem getItem() {
52921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
53021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String title = mCursor.getString(
53121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
53221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String text2 = mCursor.getString(
53321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
53421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String url = mCursor.getString(
53521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
53621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String uri = mCursor.getString(
53721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
53821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
53940f720ecfd4ef7ebb657f0fc1906a9982b3bafbdJohn Reck                SuggestItem item = new SuggestItem(title, url, type);
54040f720ecfd4ef7ebb657f0fc1906a9982b3bafbdJohn Reck                item.extra = mCursor.getString(
54140f720ecfd4ef7ebb657f0fc1906a9982b3bafbdJohn Reck                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA));
54240f720ecfd4ef7ebb657f0fc1906a9982b3bafbdJohn Reck                return item;
54321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
54421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
54521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
54621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
54721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
54821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void runQuery(CharSequence constraint) {
54921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
55021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
55121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
5525119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
55321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (!TextUtils.isEmpty(constraint)) {
55421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (searchEngine != null && searchEngine.supportsSuggestions()) {
55521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
55621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    if (mCursor != null) {
55721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.moveToFirst();
55821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    }
55921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
56021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
5615119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath                if (searchEngine.wantsEmptyQuery()) {
5625119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath                    mCursor = searchEngine.getSuggestions(mContext, "");
5635119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath                }
56421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor = null;
56521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
56621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
56721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
56821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
56921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
5705119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    private boolean useInstant() {
5715119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        return BrowserSettings.getInstance().useInstant();
5725119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    }
5735119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
57435defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    public void clearCache() {
57535defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        mFilterResults = null;
57635defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck        mSuggestResults = null;
5775119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        notifyDataSetInvalidated();
57835defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck    }
57935defffe93d70e9d5b37ff550968debdcd5d3d8bJohn Reck
580117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck    public void setIncognitoMode(boolean incognito) {
581117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck        mIncognitoMode = incognito;
582117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck        clearCache();
583117f07d08e3e25e3c920a1dabe31dcd7643bacb2John Reck    }
5845119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
5855119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    static String getSuggestionTitle(SuggestItem item) {
5865119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        // There must be a better way to strip HTML from things.
5875119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        // This method is used in multiple places. It is also more
5885119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        // expensive than a standard html escaper.
5895119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        return (item.title != null) ? Html.fromHtml(item.title).toString() : null;
5905119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    }
5915119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
5925119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    static String getSuggestionUrl(SuggestItem item) {
5935119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        final String title = SuggestionsAdapter.getSuggestionTitle(item);
5945119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
5955119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        if (TextUtils.isEmpty(item.url)) {
5965119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath            return title;
5975119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        }
5985119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath
5995119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath        return item.url;
6005119edd5744cfc6d3a8ed480a8853586c737bed4Narayan Kamath    }
60121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb}
602