1fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert/*
2fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Copyright (C) 2010 The Android Open Source Project
3fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert *
4fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
5fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * you may not use this file except in compliance with the License.
6fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * You may obtain a copy of the License at
7fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert *
8fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
9fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert *
10fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * Unless required by applicable law or agreed to in writing, software
11fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
12fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * See the License for the specific language governing permissions and
14fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * limitations under the License.
15fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */
16fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
17fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertpackage com.android.quicksearchbox;
18fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
19fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
202353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringertimport com.android.quicksearchbox.util.Util;
212353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert
22fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.content.Context;
23fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.content.Intent;
24fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.graphics.drawable.Drawable;
25fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.net.Uri;
26fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.os.Bundle;
27848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasaniimport android.util.Log;
28dfabb7cfae91f6af3b5a9a9584cdec5557d1fcebDianne Hackbornimport android.util.Patterns;
29fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.webkit.URLUtil;
30fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
31883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringertimport java.util.ArrayList;
3213ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringertimport java.util.List;
3372f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringertimport java.util.concurrent.Executor;
34883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
35fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert/**
36fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert * The web search source.
37fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert */
38f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringertpublic class WebCorpus extends MultiSourceCorpus {
39848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    private static final String TAG = "QSB.WebCorpus";
40848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    private static final boolean DBG = false;
41fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
42fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    private static final String WEB_CORPUS_NAME = "web";
43fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
4496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert    private final SearchSettings mSettings;
4596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert
46848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    private Source mWebSearchSource;
47883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
4813ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert    private final Source mBrowserSource;
4913ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert
5096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert    public WebCorpus(Context context, Config config, SearchSettings settings, Executor executor,
51f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            Source webSearchSource, Source browserSource) {
5296c7058210699c82445169048b7c0fdfb16f59eeBjorn Bringert        super(context, config, executor, webSearchSource, browserSource);
53848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        if (DBG) {
54848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani            Log.d(TAG, "init webSource=" + webSearchSource + "; browser source = " + browserSource);
55848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        }
5696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert        mSettings = settings;
57fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        mWebSearchSource = webSearchSource;
5813ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert        mBrowserSource = browserSource;
59fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
60fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
6196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert    protected SearchSettings getSettings() {
6296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert        return mSettings;
6396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert    }
6496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert
65848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    public void setWebSource(Source web) {
66848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        if (DBG) Log.d(TAG, "setWebSource(" + web + ")");
67848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        mWebSearchSource = web;
68848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    }
69848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani
70fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public CharSequence getLabel() {
71fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return getContext().getText(R.string.corpus_label_web);
72fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
73fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
745691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert    public CharSequence getHint() {
755691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert        // The web corpus uses a drawable hint instead
765691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert        return null;
775691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert    }
785691f9062b2a558ba39c700d65bc522d397ebc75Bjorn Bringert
79c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert    private boolean isUrl(String query) {
80c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert       return Patterns.WEB_URL.matcher(query).matches();
81fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
82fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
83c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert    public Intent createSearchIntent(String query, Bundle appData) {
840be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert        if (isUrl(query)) {
850be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert            return createBrowseIntent(query);
860be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert        } else if (mWebSearchSource != null){
870be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert            return mWebSearchSource.createSearchIntent(query, appData);
880be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert        } else {
890be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert            return null;
90fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        }
91fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
92fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
930be2eb803011b1ef8c2c8277c330fe5ad975316bBjorn Bringert    private Intent createBrowseIntent(String query) {
94fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        Intent intent = new Intent(Intent.ACTION_VIEW);
95fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        intent.addCategory(Intent.CATEGORY_BROWSABLE);
96fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
97fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
98c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert        String url = URLUtil.guessUrl(query);
99fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        intent.setData(Uri.parse(url));
100fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return intent;
101fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
102fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
103fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public Intent createVoiceSearchIntent(Bundle appData) {
104848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        // TODO in 2-pane mode, mWebSearchSource may be NULL
105848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        // this functionality should be moved elsewhere.
10649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        if (mWebSearchSource != null){
10749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            return mWebSearchSource.createVoiceSearchIntent(appData);
10849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        } else {
10949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            return null;
11049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        }
111fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
112fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
1132353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert    private int getCorpusIconResource() {
1142353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert        return R.drawable.corpus_icon_web;
1152353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert    }
1162353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert
117fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public Drawable getCorpusIcon() {
1182353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert        return getContext().getResources().getDrawable(getCorpusIconResource());
119fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
120fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
121fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public Uri getCorpusIconUri() {
1222353e9c002c45c0adc8a979a49ff317cae5838b8Bjorn Bringert        return Util.getResourceUri(getContext(), getCorpusIconResource());
123fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
124fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
125fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public String getName() {
126fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return WEB_CORPUS_NAME;
127fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
128fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
1293cb8178193a41f6c74ee396c318385a50dd624e1Mathew Inwood    @Override
130fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public int getQueryThreshold() {
131fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return 0;
132fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
133fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
1343cb8178193a41f6c74ee396c318385a50dd624e1Mathew Inwood    @Override
135fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public boolean queryAfterZeroResults() {
136fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return true;
137fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
138fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
1393cb8178193a41f6c74ee396c318385a50dd624e1Mathew Inwood    @Override
140fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public boolean voiceSearchEnabled() {
141fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return true;
142fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
143fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
144fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public boolean isWebCorpus() {
145fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return true;
146fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
147fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
148fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public CharSequence getSettingsDescription() {
149fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return getContext().getText(R.string.corpus_description_web);
150fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
151fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
152f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert    @Override
153cd1e3ba5f7c3f5242345ff6f674281e3d6366e24Mathew Inwood    protected List<Source> getSourcesToQuery(String query, boolean onlyCorpus) {
154dbda78401b4b25ac1da77b2db75f0657f2705b1dBryan Mawhinney        ArrayList<Source> sourcesToQuery = new ArrayList<Source>(2);
15534955d44dddabfc672a26263363190f971c337a8Mathew Inwood        if (mWebSearchSource != null) sourcesToQuery.add(mWebSearchSource);
156dbda78401b4b25ac1da77b2db75f0657f2705b1dBryan Mawhinney        if (mBrowserSource != null && query.length() > 0) {
157dbda78401b4b25ac1da77b2db75f0657f2705b1dBryan Mawhinney            sourcesToQuery.add(mBrowserSource);
15813ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert        }
159848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        if (DBG) Log.d(TAG, "getSourcesToQuery sourcesToQuery=" + sourcesToQuery);
160dbda78401b4b25ac1da77b2db75f0657f2705b1dBryan Mawhinney        return sourcesToQuery;
16113ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert    }
16213ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert
16313ace1d0d0fa7e4c7aa7898a828763d8880db463Bjorn Bringert    @Override
164f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert    protected Result createResult(String query, ArrayList<SourceResult> results, int latency) {
165f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert        return new WebResult(query, results, latency);
166fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
167fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
168f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert    protected class WebResult extends Result {
169fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
170f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert        public WebResult(String query, ArrayList<SourceResult> results, int latency) {
171f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert            super(query, results, latency);
172f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert        }
173fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
174f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert        @Override
175f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert        public void fill() {
176f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            SourceResult webSearchResult = null;
177f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            SourceResult browserResult = null;
178f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            for (SourceResult result : getResults()) {
179f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                if (result.getSource().equals(mWebSearchSource)) {
180f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                    webSearchResult = result;
181f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                } else {
182f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                    browserResult = result;
183f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                }
184fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            }
185f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            if (browserResult != null && browserResult.getCount() > 0) {
186f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                add(new SuggestionPosition(browserResult, 0));
187f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            }
188f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            if (webSearchResult != null) {
189f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                int count = webSearchResult.getCount();
190fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert                for (int i = 0; i < count; i++) {
191f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                    add(new SuggestionPosition(webSearchResult, i));
192fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert                }
193fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            }
194fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        }
195fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
196fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
197fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert}
198