18233facddcc51865d612a919d450db6954aa48e3Michael Kolb/*
28233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Copyright (C) 2010 The Android Open Source Project
38233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
48233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58233facddcc51865d612a919d450db6954aa48e3Michael Kolb * you may not use this file except in compliance with the License.
68233facddcc51865d612a919d450db6954aa48e3Michael Kolb * You may obtain a copy of the License at
78233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
88233facddcc51865d612a919d450db6954aa48e3Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
108233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Unless required by applicable law or agreed to in writing, software
118233facddcc51865d612a919d450db6954aa48e3Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128233facddcc51865d612a919d450db6954aa48e3Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138233facddcc51865d612a919d450db6954aa48e3Michael Kolb * See the License for the specific language governing permissions and
148233facddcc51865d612a919d450db6954aa48e3Michael Kolb * limitations under the License.
158233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
178233facddcc51865d612a919d450db6954aa48e3Michael Kolb
188233facddcc51865d612a919d450db6954aa48e3Michael Kolbpackage com.android.browser;
198233facddcc51865d612a919d450db6954aa48e3Michael Kolb
208233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
218233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.SearchManager;
228233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ContentResolver;
238233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Context;
248233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Intent;
258233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.Uri;
26fd77aaaa6b1b79ba0438a78e357aa877552830b1Jeff Hamiltonimport android.nfc.NfcAdapter;
278233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.AsyncTask;
288233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.Bundle;
298233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.Browser;
308233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.provider.MediaStore;
318233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.text.TextUtils;
328233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.util.Patterns;
338233facddcc51865d612a919d450db6954aa48e3Michael Kolb
34315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolbimport com.android.browser.UI.ComboViews;
35e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolbimport com.android.browser.search.SearchEngine;
36e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolbimport com.android.common.Search;
37e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb
388233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.util.HashMap;
398233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.util.Iterator;
408233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport java.util.Map;
418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
428233facddcc51865d612a919d450db6954aa48e3Michael Kolb/**
438233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Handle all browser related intents
448233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
458233facddcc51865d612a919d450db6954aa48e3Michael Kolbpublic class IntentHandler {
468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // "source" parameter for Google search suggested by the browser
488233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static String GOOGLE_SEARCH_SOURCE_SUGGEST = "browser-suggest";
498233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // "source" parameter for Google search from unknown source
508233facddcc51865d612a919d450db6954aa48e3Michael Kolb    final static String GOOGLE_SEARCH_SOURCE_UNKNOWN = "unknown";
518233facddcc51865d612a919d450db6954aa48e3Michael Kolb
528233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /* package */ static final UrlData EMPTY_URL_DATA = new UrlData(null);
538233facddcc51865d612a919d450db6954aa48e3Michael Kolb
548233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Activity mActivity;
558233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private Controller mController;
568233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private TabControl mTabControl;
578233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private BrowserSettings mSettings;
588233facddcc51865d612a919d450db6954aa48e3Michael Kolb
598233facddcc51865d612a919d450db6954aa48e3Michael Kolb    public IntentHandler(Activity browser, Controller controller) {
608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mActivity = browser;
618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mController = controller;
628233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mTabControl = mController.getTabControl();
638233facddcc51865d612a919d450db6954aa48e3Michael Kolb        mSettings = controller.getSettings();
648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
658233facddcc51865d612a919d450db6954aa48e3Michael Kolb
668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    void onNewIntent(Intent intent) {
678233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Tab current = mTabControl.getCurrentTab();
688233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // When a tab is closed on exit, the current tab index is set to -1.
698233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Reset before proceed as Browser requires the current tab to be set.
708233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (current == null) {
718233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Try to reset the tab in case the index was incorrect.
728233facddcc51865d612a919d450db6954aa48e3Michael Kolb            current = mTabControl.getTab(0);
738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (current == null) {
748233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // No tabs at all so just ignore this intent.
758233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return;
768233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
778233facddcc51865d612a919d450db6954aa48e3Michael Kolb            mController.setActiveTab(current);
788233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
798233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final String action = intent.getAction();
808233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final int flags = intent.getFlags();
818233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (Intent.ACTION_MAIN.equals(action) ||
828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                (flags & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // just resume the browser
848233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
858233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
86439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck        if (BrowserActivity.ACTION_SHOW_BOOKMARKS.equals(action)) {
87315d502edce27bb4e93e53134f1a43b8f5c45588Michael Kolb            mController.bookmarksOrHistoryPicker(ComboViews.Bookmarks);
88439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck            return;
89439c9a58765aa6aab95d55422ee61ea8360e912dJohn Reck        }
9007af2b8ae04c6e4385e41e0c559280a995eb8035John Reck
918233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // In case the SearchDialog is open.
928233facddcc51865d612a919d450db6954aa48e3Michael Kolb        ((SearchManager) mActivity.getSystemService(Context.SEARCH_SERVICE))
938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .stopSearch();
948233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (Intent.ACTION_VIEW.equals(action)
95fd77aaaa6b1b79ba0438a78e357aa877552830b1Jeff Hamilton                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)
968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || Intent.ACTION_SEARCH.equals(action)
978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
985ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb                || Intent.ACTION_WEB_SEARCH.equals(action)) {
998233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // If this was a search request (e.g. search query directly typed into the address bar),
1008233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // pass it on to the default web search provider.
1018233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (handleWebSearchIntent(mActivity, mController, intent)) {
1028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                return;
1038233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1048233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1058233facddcc51865d612a919d450db6954aa48e3Michael Kolb            UrlData urlData = getUrlDataFromIntent(intent);
1068233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (urlData.isEmpty()) {
1078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                urlData = new UrlData(mSettings.getHomePage());
1088233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1098233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1101461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            if (intent.getBooleanExtra(Browser.EXTRA_CREATE_NEW_TAB, false)
1111461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                  || urlData.isPreloaded()) {
1121461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                Tab t = mController.openTab(urlData);
1132ed6e31fc7224313d668f8edcb4c9473f4710801Leon Scroggins                return;
1142ed6e31fc7224313d668f8edcb4c9473f4710801Leon Scroggins            }
115db22ec4ee014900988062d910bc810172a07df56John Reck            /*
116db22ec4ee014900988062d910bc810172a07df56John Reck             * TODO: Don't allow javascript URIs
117db22ec4ee014900988062d910bc810172a07df56John Reck             * 0) If this is a javascript: URI, *always* open a new tab
1185ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb             * 1) If the URL is already opened, switch to that tab
1195ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb             * 2-phone) Reuse tab with same appId
1205ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb             * 2-tablet) Open new tab
121db22ec4ee014900988062d910bc810172a07df56John Reck             */
1228233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final String appId = intent
1238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    .getStringExtra(Browser.EXTRA_APPLICATION_ID);
12426b183292dc087b16af10f482744c3bb30e1f163John Reck            if (!TextUtils.isEmpty(urlData.mUrl) &&
12526b183292dc087b16af10f482744c3bb30e1f163John Reck                    urlData.mUrl.startsWith("javascript:")) {
12626b183292dc087b16af10f482744c3bb30e1f163John Reck                // Always open javascript: URIs in new tabs
12726b183292dc087b16af10f482744c3bb30e1f163John Reck                mController.openTab(urlData);
12826b183292dc087b16af10f482744c3bb30e1f163John Reck                return;
12926b183292dc087b16af10f482744c3bb30e1f163John Reck            }
130f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb            if (Intent.ACTION_VIEW.equals(action)
131f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                    && (appId != null)
132f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                    && appId.startsWith(mActivity.getPackageName())) {
133f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                Tab appTab = mTabControl.getTabFromAppId(appId);
134f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                if ((appTab != null) && (appTab == mController.getCurrentTab())) {
135f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                    mController.switchToTab(appTab);
136f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                    mController.loadUrlDataIn(appTab, urlData);
137f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                    return;
138f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb                }
139f1286a455eeacd02dfcca1335e6a7a9f87433c1bMichael Kolb            }
1405ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb            if (Intent.ACTION_VIEW.equals(action)
1415ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb                     && !mActivity.getPackageName().equals(appId)) {
1428d772b03fcfd83cea6ec81c9e826f700fac88b61Michael Kolb                if (!BrowserActivity.isTablet(mActivity)
1438d772b03fcfd83cea6ec81c9e826f700fac88b61Michael Kolb                        && !mSettings.allowAppTabs()) {
144c831b63308dd1f8ef71808db8344ca2566ba4ed4Michael Kolb                    Tab appTab = mTabControl.getTabFromAppId(appId);
145af0d334f54395798d44e300c5f4733af7d477bbeMichael Kolb                    if (appTab != null) {
14626b183292dc087b16af10f482744c3bb30e1f163John Reck                        mController.reuseTab(appTab, urlData);
147af0d334f54395798d44e300c5f4733af7d477bbeMichael Kolb                        return;
148af0d334f54395798d44e300c5f4733af7d477bbeMichael Kolb                    }
149db22ec4ee014900988062d910bc810172a07df56John Reck                }
150db22ec4ee014900988062d910bc810172a07df56John Reck                // No matching application tab, try to find a regular tab
151db22ec4ee014900988062d910bc810172a07df56John Reck                // with a matching url.
152db22ec4ee014900988062d910bc810172a07df56John Reck                Tab appTab = mTabControl.findTabWithUrl(urlData.mUrl);
153db22ec4ee014900988062d910bc810172a07df56John Reck                if (appTab != null) {
154db22ec4ee014900988062d910bc810172a07df56John Reck                    // Transfer ownership
155db22ec4ee014900988062d910bc810172a07df56John Reck                    appTab.setAppId(appId);
156db22ec4ee014900988062d910bc810172a07df56John Reck                    if (current != appTab) {
157db22ec4ee014900988062d910bc810172a07df56John Reck                        mController.switchToTab(appTab);
158db22ec4ee014900988062d910bc810172a07df56John Reck                    }
159db22ec4ee014900988062d910bc810172a07df56John Reck                    // Otherwise, we are already viewing the correct tab.
1608233facddcc51865d612a919d450db6954aa48e3Michael Kolb                } else {
161db22ec4ee014900988062d910bc810172a07df56John Reck                    // if FLAG_ACTIVITY_BROUGHT_TO_FRONT flag is on, the url
162db22ec4ee014900988062d910bc810172a07df56John Reck                    // will be opened in a new tab unless we have reached
163db22ec4ee014900988062d910bc810172a07df56John Reck                    // MAX_TABS. Then the url will be opened in the current
164db22ec4ee014900988062d910bc810172a07df56John Reck                    // tab. If a new tab is created, it will have "true" for
165db22ec4ee014900988062d910bc810172a07df56John Reck                    // exit on close.
166db22ec4ee014900988062d910bc810172a07df56John Reck                    Tab tab = mController.openTab(urlData);
167db22ec4ee014900988062d910bc810172a07df56John Reck                    if (tab != null) {
168db22ec4ee014900988062d910bc810172a07df56John Reck                        tab.setAppId(appId);
169e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb                        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
170e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb                            tab.setCloseOnBack(true);
171e28b347fcc1df6e6bd41cb294d521a4f1e7c5c75Michael Kolb                        }
1728233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
1738233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
1748233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
1758233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // Get rid of the subwindow if it exists
1768233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mController.dismissSubWindow(current);
1778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // If the current Tab is being used as an application tab,
1788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // remove the association, since the new Intent means that it is
1798233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // no longer associated with that application.
1808233facddcc51865d612a919d450db6954aa48e3Michael Kolb                current.setAppId(null);
1818233facddcc51865d612a919d450db6954aa48e3Michael Kolb                mController.loadUrlDataIn(current, urlData);
1828233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1838233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1848233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
1858233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1861461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb    protected static UrlData getUrlDataFromIntent(Intent intent) {
1878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String url = "";
1888233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Map<String, String> headers = null;
18929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        PreloadedTabControl preloaded = null;
19029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        String preloadedSearchBoxQuery = null;
191e1cab10c8690fbafa7765271621cce2b3961b9e8Leon Scroggins        if (intent != null
192e1cab10c8690fbafa7765271621cce2b3961b9e8Leon Scroggins                && (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
1938233facddcc51865d612a919d450db6954aa48e3Michael Kolb            final String action = intent.getAction();
194fd77aaaa6b1b79ba0438a78e357aa877552830b1Jeff Hamilton            if (Intent.ACTION_VIEW.equals(action) ||
195fd77aaaa6b1b79ba0438a78e357aa877552830b1Jeff Hamilton                    NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
1968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                url = UrlUtils.smartUrlFilter(intent.getData());
1978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (url != null && url.startsWith("http")) {
1988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    final Bundle pairs = intent
1998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            .getBundleExtra(Browser.EXTRA_HEADERS);
2008233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    if (pairs != null && !pairs.isEmpty()) {
2018233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        Iterator<String> iter = pairs.keySet().iterator();
2028233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        headers = new HashMap<String, String>();
2038233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        while (iter.hasNext()) {
2048233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            String key = iter.next();
2058233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            headers.put(key, pairs.getString(key));
2068233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
2078233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
2088233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
2091461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                if (intent.hasExtra(PreloadRequestReceiver.EXTRA_PRELOAD_ID)) {
2101461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    String id = intent.getStringExtra(PreloadRequestReceiver.EXTRA_PRELOAD_ID);
21129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                    preloadedSearchBoxQuery = intent.getStringExtra(
21229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                            PreloadRequestReceiver.EXTRA_SEARCHBOX_SETQUERY);
2131461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                    preloaded = Preloader.getInstance().getPreloadedTab(id);
2141461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb                }
2158233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else if (Intent.ACTION_SEARCH.equals(action)
2168233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
2178233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    || Intent.ACTION_WEB_SEARCH.equals(action)) {
2188233facddcc51865d612a919d450db6954aa48e3Michael Kolb                url = intent.getStringExtra(SearchManager.QUERY);
2198233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (url != null) {
2208233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // In general, we shouldn't modify URL from Intent.
2218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // But currently, we get the user-typed URL from search box as well.
2228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    url = UrlUtils.fixUrl(url);
2238233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    url = UrlUtils.smartUrlFilter(url);
2248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    String searchSource = "&source=android-" + GOOGLE_SEARCH_SOURCE_SUGGEST + "&";
2258233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    if (url.contains(searchSource)) {
2268233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        String source = null;
2278233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        final Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA);
2288233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (appData != null) {
2298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            source = appData.getString(Search.SOURCE);
2308233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
2318233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (TextUtils.isEmpty(source)) {
2328233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            source = GOOGLE_SEARCH_SOURCE_UNKNOWN;
2338233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
2348233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        url = url.replace(searchSource, "&source=android-"+source+"&");
2358233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
2368233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
2378233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
2388233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2399ad1eac377ffa6ffd34afae4c6580b7ba7508c31Mathew Inwood        return new UrlData(url, headers, intent, preloaded, preloadedSearchBoxQuery);
2408233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2438233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Launches the default web search activity with the query parameters if the given intent's data
2448233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * are identified as plain search terms and not URLs/shortcuts.
2458233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return true if the intent was handled and web search activity was launched, false if not.
2468233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static boolean handleWebSearchIntent(Activity activity,
2488233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Controller controller, Intent intent) {
2498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (intent == null) return false;
2508233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2518233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String url = null;
2528233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final String action = intent.getAction();
2538233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (Intent.ACTION_VIEW.equals(action)) {
2548233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Uri data = intent.getData();
2558233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (data != null) url = data.toString();
2568233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else if (Intent.ACTION_SEARCH.equals(action)
2578233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
2588233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || Intent.ACTION_WEB_SEARCH.equals(action)) {
2598233facddcc51865d612a919d450db6954aa48e3Michael Kolb            url = intent.getStringExtra(SearchManager.QUERY);
2608233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return handleWebSearchRequest(activity, controller, url,
2628233facddcc51865d612a919d450db6954aa48e3Michael Kolb                intent.getBundleExtra(SearchManager.APP_DATA),
2638233facddcc51865d612a919d450db6954aa48e3Michael Kolb                intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
2648233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2658233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2668233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
2678233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Launches the default web search activity with the query parameters if the given url string
2688233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * was identified as plain search terms and not URL/shortcut.
2698233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @return true if the request was handled and web search activity was launched, false if not.
2708233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
2718233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static boolean handleWebSearchRequest(Activity activity,
2728233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Controller controller, String inUrl, Bundle appData,
2738233facddcc51865d612a919d450db6954aa48e3Michael Kolb            String extraData) {
274991412749b1e0837ab602d77a2264a2186741a05John Reck        if (inUrl == null) return false;
2758233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2768233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // In general, we shouldn't modify URL from Intent.
2778233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // But currently, we get the user-typed URL from search box as well.
2788233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String url = UrlUtils.fixUrl(inUrl).trim();
279991412749b1e0837ab602d77a2264a2186741a05John Reck        if (TextUtils.isEmpty(url)) return false;
2808233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2818233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // URLs are handled by the regular flow of control, so
2828233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // return early.
2838233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (Patterns.WEB_URL.matcher(url).matches()
2848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || UrlUtils.ACCEPTED_URI_SCHEMA.matcher(url).matches()) {
2858233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return false;
2868233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
2878233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2888233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final ContentResolver cr = activity.getContentResolver();
2898233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final String newUrl = url;
2908233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (controller == null || controller.getTabControl() == null
2918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || controller.getTabControl().getCurrentWebView() == null
2928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || !controller.getTabControl().getCurrentWebView()
2938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .isPrivateBrowsingEnabled()) {
2948233facddcc51865d612a919d450db6954aa48e3Michael Kolb            new AsyncTask<Void, Void, Void>() {
2958233facddcc51865d612a919d450db6954aa48e3Michael Kolb                @Override
2968233facddcc51865d612a919d450db6954aa48e3Michael Kolb                protected Void doInBackground(Void... unused) {
2978233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        Browser.addSearchUrl(cr, newUrl);
2988233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    return null;
2998233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
3008233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }.execute();
3018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3028233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3038233facddcc51865d612a919d450db6954aa48e3Michael Kolb        SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
3048233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (searchEngine == null) return false;
3058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        searchEngine.startSearch(activity, url, appData, extraData);
3068233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3078233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return true;
3088233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
3098233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3108233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
3118233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * A UrlData class to abstract how the content will be set to WebView.
3128233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * This base class uses loadUrl to show the content.
3138233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
3148233facddcc51865d612a919d450db6954aa48e3Michael Kolb    static class UrlData {
3158233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final String mUrl;
3168233facddcc51865d612a919d450db6954aa48e3Michael Kolb        final Map<String, String> mHeaders;
31729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        final PreloadedTabControl mPreloadedTab;
31829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        final String mSearchBoxQueryToSubmit;
31938b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck        final boolean mDisableUrlOverride;
3208233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3218233facddcc51865d612a919d450db6954aa48e3Michael Kolb        UrlData(String url) {
3228233facddcc51865d612a919d450db6954aa48e3Michael Kolb            this.mUrl = url;
3238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            this.mHeaders = null;
3241461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            this.mPreloadedTab = null;
32529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            this.mSearchBoxQueryToSubmit = null;
32638b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck            this.mDisableUrlOverride = false;
3278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3288233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3298233facddcc51865d612a919d450db6954aa48e3Michael Kolb        UrlData(String url, Map<String, String> headers, Intent intent) {
3309ad1eac377ffa6ffd34afae4c6580b7ba7508c31Mathew Inwood            this(url, headers, intent, null, null);
3311461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        }
3321461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
33329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        UrlData(String url, Map<String, String> headers, Intent intent,
3349ad1eac377ffa6ffd34afae4c6580b7ba7508c31Mathew Inwood                PreloadedTabControl preloaded, String searchBoxQueryToSubmit) {
3358233facddcc51865d612a919d450db6954aa48e3Michael Kolb            this.mUrl = url;
3368233facddcc51865d612a919d450db6954aa48e3Michael Kolb            this.mHeaders = headers;
33729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            this.mPreloadedTab = preloaded;
33829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            this.mSearchBoxQueryToSubmit = searchBoxQueryToSubmit;
33938b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck            if (intent != null) {
34038b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                mDisableUrlOverride = intent.getBooleanExtra(
34138b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                        BrowserActivity.EXTRA_DISABLE_URL_OVERRIDE, false);
34238b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck            } else {
34338b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck                mDisableUrlOverride = false;
34438b3965028e4ac433de9d43c02d3167ff0ef208cJohn Reck            }
3458233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3478233facddcc51865d612a919d450db6954aa48e3Michael Kolb        boolean isEmpty() {
3485ff5c8b88968fa794eab4b7a263cae25f05bd4d3Michael Kolb            return (mUrl == null || mUrl.length() == 0);
3498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
3501461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
3511461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        boolean isPreloaded() {
3521461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            return mPreloadedTab != null;
3531461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        }
3541461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb
35529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        PreloadedTabControl getPreloadedTab() {
3561461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb            return mPreloadedTab;
3571461244018a225006a8d4c203f9dfe294ffe94faMichael Kolb        }
35829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
35929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        String getSearchBoxQueryToSubmit() {
36029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            return mSearchBoxQueryToSubmit;
36129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
3628233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
3638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
3648233facddcc51865d612a919d450db6954aa48e3Michael Kolb}
365