SuggestionsAdapter.java revision 21ce4d295802db811873b46e7821abfa0540dab2
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;
2521ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.provider.BrowserContract;
2621ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.text.TextUtils;
2721ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.LayoutInflater;
2821ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.View;
2921ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.View.OnClickListener;
3021ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.view.ViewGroup;
3121ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.BaseAdapter;
3221ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.Filter;
3321ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.Filterable;
3421ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.ImageView;
3521ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.LinearLayout.LayoutParams;
3621ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport android.widget.TextView;
3721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
3821ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.ArrayList;
3921ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.List;
4021ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.regex.Matcher;
4121ce4d295802db811873b46e7821abfa0540dab2Michael Kolbimport java.util.regex.Pattern;
4221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
4321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb/**
4421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb * adapter to wrap multiple cursors for url/search completions
4521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb */
4621ce4d295802db811873b46e7821abfa0540dab2Michael Kolbpublic class SuggestionsAdapter extends BaseAdapter implements Filterable, OnClickListener {
4721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
4821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    static final int TYPE_SEARCH = 0;
4921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    static final int TYPE_SUGGEST = 1;
5021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    static final int TYPE_BOOKMARK = 2;
5121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    static final int TYPE_SUGGEST_URL = 3;
5221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    static final int TYPE_HISTORY = 4;
5321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
5421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final String[] COMBINED_PROJECTION =
5521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            {BrowserContract.Combined._ID, BrowserContract.Combined.TITLE,
5621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    BrowserContract.Combined.URL, BrowserContract.Combined.IS_BOOKMARK};
5721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
5821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final String[] SEARCHES_PROJECTION = {BrowserContract.Searches.SEARCH};
5921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
6021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final String COMBINED_SELECTION =
6121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
6221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
6321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    // Regular expression which matches http://, followed by some stuff, followed by
6421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    // optionally a trailing slash, all matched as separate groups.
6521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private static final Pattern STRIP_URL_PATTERN = Pattern.compile("^(http://)(.*?)(/$)?");
6621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
6721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    Context mContext;
6821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    Filter mFilter;
6921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    SuggestionResults mResults;
7021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    List<CursorSource> mSources;
7121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    boolean mLandscapeMode;
7221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    CompletionListener mListener;
7321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    int mLinesPortrait;
7421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    int mLinesLandscape;
7521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
7621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    interface CompletionListener {
7721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
7821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void onSearch(String txt);
7921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
8021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void onSelect(String txt);
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);
9121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mFilter = new SuggestFilter();
9221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        addSource(new SuggestCursor());
9321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        addSource(new SearchesCursor());
9421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        addSource(new CombinedCursor());
9521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
9621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
9721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void setLandscapeMode(boolean mode) {
9821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mLandscapeMode = mode;
9921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
10021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
10121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public int getLeftCount() {
10221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return mResults.getLeftCount();
10321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
10421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
10521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public int getRightCount() {
10621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return mResults.getRightCount();
10721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
10821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
10921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void addSource(CursorSource c) {
11021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (mSources == null) {
11121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mSources = new ArrayList<CursorSource>(5);
11221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
11321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        mSources.add(c);
11421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
11521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
11621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
11721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public void onClick(View v) {
11821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (R.id.icon2 == v.getId()) {
11921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // replace input field text with suggestion text
12021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
12121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mListener.onSearch(item.title);
12221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        } else {
12321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            SuggestItem item = (SuggestItem) v.getTag();
12421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mListener.onSelect((TextUtils.isEmpty(item.url)? item.title : item.url));
12521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
12621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
12721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
12821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
12921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public Filter getFilter() {
13021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return mFilter;
13121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
13221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
13321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
13421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public int getCount() {
13521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return (mResults == null) ? 0 : mResults.getLineCount();
13621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
13721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
13821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
13921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public SuggestItem getItem(int position) {
14021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (mResults == null) {
14121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
14221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
14321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (mLandscapeMode) {
14421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (position >= mResults.getLineCount()) {
14521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                // right column
14621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                position = position - mResults.getLineCount();
14721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                // index in column
14821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (position >= mResults.getRightCount()) {
14921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    return null;
15021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
15121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return mResults.items.get(position + mResults.getLeftCount());
15221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
15321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                // left column
15421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (position >= mResults.getLeftCount()) {
15521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    return null;
15621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
15721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return mResults.items.get(position);
15821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
15921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        } else {
16021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return mResults.items.get(position);
16121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
16221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
16321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
16421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
16521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public long getItemId(int position) {
16621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        return 0;
16721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
16821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
16921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    @Override
17021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    public View getView(int position, View convertView, ViewGroup parent) {
17121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        final LayoutInflater inflater = LayoutInflater.from(mContext);
17221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (mLandscapeMode) {
17321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            View view = inflater.inflate(R.layout.suggestion_two_column, parent, false);
17421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            SuggestItem item = getItem(position);
17521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            View iv = view.findViewById(R.id.suggest1);
17621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            LayoutParams lp = new LayoutParams(iv.getLayoutParams());
17721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            lp.weight = 0.5f;
17821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            iv.setLayoutParams(lp);
17921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (item != null) {
18021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                bindView(iv, item);
18121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
18221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                iv.setVisibility((mResults.getLeftCount() == 0) ? View.GONE :
18321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        View.INVISIBLE);
18421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
18521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            item = getItem(position + mResults.getLineCount());
18621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            iv = view.findViewById(R.id.suggest2);
18721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            lp = new LayoutParams(iv.getLayoutParams());
18821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            lp.weight = 0.5f;
18921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            iv.setLayoutParams(lp);
19021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (item != null) {
19121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                bindView(iv, item);
19221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
19321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                iv.setVisibility((mResults.getRightCount() == 0) ? View.GONE :
19421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        View.INVISIBLE);
19521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
19621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return view;
19721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        } else {
19821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            View view = inflater.inflate(R.layout.suggestion_item, parent, false);
19921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            bindView(view, getItem(position));
20021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return view;
20121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
20221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
20321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
20421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    private void bindView(View view, SuggestItem item) {
20521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        // store item for click handling
20621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        view.setTag(item);
20721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
20821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
20921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
21021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        View spacer = view.findViewById(R.id.spacer);
21121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        View ic2 = view.findViewById(R.id.icon2);
21221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        tv1.setText(item.title);
21321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        tv2.setText(item.url);
21421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int id = -1;
21521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        switch (item.type) {
21621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SUGGEST:
21721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SEARCH:
21821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_suggest;
21921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
22021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_BOOKMARK:
22121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_bookmark;
22221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
22321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_HISTORY:
22421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_history;
22521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
22621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            case TYPE_SUGGEST_URL:
22721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = R.drawable.ic_search_category_browser;
22821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                break;
22921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            default:
23021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                id = -1;
23121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
23221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        if (id != -1) {
23321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            ic1.setImageDrawable(mContext.getResources().getDrawable(id));
23421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
23521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ic2.setVisibility(((TYPE_SUGGEST == item.type) || (TYPE_SEARCH == item.type))
23621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                ? View.VISIBLE : View.GONE);
23721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        spacer.setVisibility(((TYPE_SUGGEST == item.type) || (TYPE_SEARCH == item.type))
23821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                ? View.GONE : View.INVISIBLE);
23921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        view.setOnClickListener(this);
24021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ic2.setOnClickListener(this);
24121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
24221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
24321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestFilter extends Filter {
24421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
24521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int count;
24621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        SuggestionResults results;
24721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
24821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
24921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public CharSequence convertResultToString(Object item) {
25021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (item == null) {
25121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return "";
25221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
25321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            SuggestItem sitem = (SuggestItem) item;
25421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (sitem.title != null) {
25521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return sitem.title;
25621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
25721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return sitem.url;
25821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
25921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
26021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
26121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
26221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        protected FilterResults performFiltering(CharSequence constraint) {
26321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            FilterResults res = new FilterResults();
26421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (TextUtils.isEmpty(constraint)) {
26521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                res.count = 0;
26621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                res.values = null;
26721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return res;
26821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
26921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            results = new SuggestionResults();
27021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            count = 0;
27121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (constraint != null) {
27221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                for (CursorSource sc : mSources) {
27321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    sc.runQuery(constraint);
27421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
27521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mixResults();
27621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
27721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            res.count = count;
27821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            res.values = results;
27921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return res;
28021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
28121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
28221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        void mixResults() {
28321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            for (int i = 0; i < mSources.size(); i++) {
28421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                CursorSource s = mSources.get(i);
28521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                int n = Math.min(s.getCount(), (mLandscapeMode ? mLinesLandscape
28621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        : mLinesPortrait));
28721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                boolean more = true;
28821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                for (int j = 0; j < n; j++) {
28921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    results.addResult(s.getItem());
29021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    more = s.moveToNext();
29121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
29221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (s instanceof SuggestCursor) {
29321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    int k = n;
29421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    while (more && (k < mLinesPortrait)) {
29521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        SuggestItem item  = s.getItem();
29621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        if (item.type == TYPE_SUGGEST_URL) {
29721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            results.addResult(item);
29821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            break;
29921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        }
30021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        more = s.moveToNext();
30121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        k++;
30221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
30321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    }
30421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
30521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
30621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
30721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
30821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
30921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
31021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        protected void publishResults(CharSequence constraint, FilterResults fresults) {
31121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mResults = (SuggestionResults) fresults.values;
31221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            notifyDataSetChanged();
31321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
31421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
31521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
31621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
31721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
31821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * sorted list of results of a suggestion query
31921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     *
32021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
32121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestionResults {
32221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
32321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        ArrayList<SuggestItem> items;
32421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        // count per type
32521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int[] counts;
32621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
32721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        SuggestionResults() {
32821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            items = new ArrayList<SuggestItem>(24);
32921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // n of types:
33021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            counts = new int[5];
33121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
33221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
33321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getTypeCount(int type) {
33421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return counts[type];
33521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
33621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
33721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        void addResult(SuggestItem item) {
33821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            int ix = 0;
33921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            while ((ix < items.size()) && (item.type >= items.get(ix).type))
34021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                ix++;
34121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            items.add(ix, item);
34221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            counts[item.type]++;
34321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
34421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
34521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getLineCount() {
34621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mLandscapeMode) {
34721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return Math.max(getLeftCount(), getRightCount());
34821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
34921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return getLeftCount() + getRightCount();
35021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
35121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
35221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
35321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getLeftCount() {
35421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return counts[TYPE_SEARCH] + counts[TYPE_SUGGEST];
35521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
35621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
35721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int getRightCount() {
35821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return counts[TYPE_BOOKMARK] + counts[TYPE_HISTORY] + counts[TYPE_SUGGEST_URL];
35921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
36021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
36121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public String toString() {
36221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (items == null) return null;
36321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (items.size() == 0) return "[]";
36421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            StringBuilder sb = new StringBuilder();
36521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            for (int i = 0; i < items.size(); i++) {
36621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                SuggestItem item = items.get(i);
36721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                sb.append(item.type + ": " + item.title);
36821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (i < items.size() - 1) {
36921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    sb.append(", ");
37021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
37121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
37221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return sb.toString();
37321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
37421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
37521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
37621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
37721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * data object to hold suggestion values
37821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
37921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestItem {
38021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        String title;
38121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        String url;
38221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        int type;
38321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
38421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem(String text, String u, int t) {
38521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            title = text;
38621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            url = u;
38721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            type = t;
38821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
38921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
39021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
39121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    abstract class CursorSource {
39221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
39321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        Cursor mCursor;
39421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
39521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        boolean moveToNext() {
39621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return mCursor.moveToNext();
39721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
39821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
39921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public abstract void runQuery(CharSequence constraint);
40021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
40121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public abstract SuggestItem getItem();
40221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
40321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public int getCount() {
40421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return (mCursor != null) ? mCursor.getCount() : 0;
40521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
40621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
40721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void close() {
40821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
40921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
41021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
41121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
41221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
41321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
41421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    /**
41521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     * combined bookmark & history source
41621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb     */
41721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class CombinedCursor extends CursorSource {
41821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
41921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
42021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem getItem() {
42121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if ((mCursor != null) && (!mCursor.isAfterLast())) {
42221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String title = mCursor.getString(1);
42321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String url = mCursor.getString(2);
42421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                boolean isBookmark = (mCursor.getInt(3) == 1);
42521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return new SuggestItem(getTitle(title, url), getUrl(title, url),
42621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        isBookmark ? TYPE_BOOKMARK : TYPE_HISTORY);
42721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
42821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
42921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
43021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
43121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
43221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void runQuery(CharSequence constraint) {
43321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // constraint != null
43421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
43521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
43621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
43721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String like = constraint + "%";
43821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String[] args = null;
43921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String selection = null;
44021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (like.startsWith("http") || like.startsWith("file")) {
44121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args = new String[1];
44221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[0] = like;
44321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                selection = "url LIKE ?";
44421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
44521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args = new String[5];
44621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[0] = "http://" + like;
44721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[1] = "http://www." + like;
44821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[2] = "https://" + like;
44921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[3] = "https://www." + like;
45021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                // To match against titles.
45121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                args[4] = like;
45221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                selection = COMBINED_SELECTION;
45321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
45421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            Uri.Builder ub = BrowserContract.Combined.CONTENT_URI.buildUpon();
45521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
45621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    Integer.toString(mLinesPortrait));
45721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mCursor =
45821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION,
45921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            selection,
46021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            (constraint != null) ? args : null,
46121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            BrowserContract.Combined.VISITS + " DESC, " +
46221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            BrowserContract.Combined.DATE_LAST_VISITED + " DESC");
46321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
46421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.moveToFirst();
46521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
46621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
46721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
46821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        /**
46921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * Provides the title (text line 1) for a browser suggestion, which should be the
47021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * webpage title. If the webpage title is empty, returns the stripped url instead.
47121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
47221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @return the title string to use
47321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         */
47421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        private String getTitle(String title, String url) {
47521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
47621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                title = stripUrl(url);
47721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
47821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return title;
47921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
48021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
48121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        /**
48221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * Provides the subtitle (text line 2) for a browser suggestion, which should be the
48321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * webpage url. If the webpage title is empty, then the url should go in the title
48421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * instead, and the subtitle should be empty, so this would return null.
48521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
48621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @return the subtitle string to use, or null if none
48721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         */
48821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        private String getUrl(String title, String url) {
48921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
49021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return null;
49121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
49221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return stripUrl(url);
49321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
49421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
49521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
49621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        /**
49721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * Strips the provided url of preceding "http://" and any trailing "/". Does not
49821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * strip "https://". If the provided string cannot be stripped, the original string
49921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * is returned.
50021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
50121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * TODO: Put this in TextUtils to be used by other packages doing something similar.
50221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *
50321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @param url a url to strip, like "http://www.google.com/"
50421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         * @return a stripped url like "www.google.com", or the original string if it could
50521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         *         not be stripped
50621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb         */
50721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        private String stripUrl(String url) {
50821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (url == null) return null;
50921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            Matcher m = STRIP_URL_PATTERN.matcher(url);
51021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (m.matches() && m.groupCount() == 3) {
51121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return m.group(2);
51221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
51321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return url;
51421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
51521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
51621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
51721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
51821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
51921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SearchesCursor extends CursorSource {
52021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
52121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
52221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem getItem() {
52321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if ((mCursor != null) && (!mCursor.isAfterLast())) {
52421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return new SuggestItem(mCursor.getString(0), null, TYPE_SEARCH);
52521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
52621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
52721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
52821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
52921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
53021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void runQuery(CharSequence constraint) {
53121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            // constraint != null
53221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
53321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
53421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
53521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String like = constraint + "%";
53621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String[] args = new String[] {constraint.toString()};
53721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            String selection = BrowserContract.Searches.SEARCH + " LIKE ?";
53821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            Uri.Builder ub = BrowserContract.Searches.CONTENT_URI.buildUpon();
53921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
54021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    Integer.toString(mLinesPortrait));
54121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            mCursor =
54221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    mContext.getContentResolver().query(ub.build(), SEARCHES_PROJECTION,
54321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            selection,
54421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                            args, BrowserContract.Searches.DATE + " DESC");
54521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
54621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.moveToFirst();
54721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
54821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
54921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
55021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
55121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
55221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    class SuggestCursor extends CursorSource {
55321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
55421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
55521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public SuggestItem getItem() {
55621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
55721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String title = mCursor.getString(
55821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
55921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String text2 = mCursor.getString(
56021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
56121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String url = mCursor.getString(
56221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
56321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                String uri = mCursor.getString(
56421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
56521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
56621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                return new SuggestItem(title, url, type);
56721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
56821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            return null;
56921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
57021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
57121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        @Override
57221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        public void runQuery(CharSequence constraint) {
57321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (mCursor != null) {
57421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor.close();
57521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
57621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            if (!TextUtils.isEmpty(constraint)) {
57721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
57821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                if (searchEngine != null && searchEngine.supportsSuggestions()) {
57921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
58021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    if (mCursor != null) {
58121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                        mCursor.moveToFirst();
58221ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                    }
58321ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                }
58421ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            } else {
58521ce4d295802db811873b46e7821abfa0540dab2Michael Kolb                mCursor = null;
58621ce4d295802db811873b46e7821abfa0540dab2Michael Kolb            }
58721ce4d295802db811873b46e7821abfa0540dab2Michael Kolb        }
58821ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
58921ce4d295802db811873b46e7821abfa0540dab2Michael Kolb    }
59021ce4d295802db811873b46e7821abfa0540dab2Michael Kolb
59121ce4d295802db811873b46e7821abfa0540dab2Michael Kolb}
592