PreloadedTabControl.java revision a829d55e8af65d08d998b8166e42420dda8cf2ff
129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood/*
229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * Copyright (C) 2011 The Android Open Source Project
329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood *
429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * Licensed under the Apache License, Version 2.0 (the "License");
529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * you may not use this file except in compliance with the License.
629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * You may obtain a copy of the License at
729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood *
829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood *      http://www.apache.org/licenses/LICENSE-2.0
929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood *
1029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * Unless required by applicable law or agreed to in writing, software
1129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * distributed under the License is distributed on an "AS IS" BASIS,
1229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * See the License for the specific language governing permissions and
1429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * limitations under the License.
1529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood */
1629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodpackage com.android.browser;
1729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
18e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwoodimport android.net.Uri;
1929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodimport android.text.TextUtils;
2029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodimport android.util.Log;
2129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodimport android.webkit.SearchBox;
2229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
2329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodimport java.util.Map;
24a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwoodimport java.util.regex.Pattern;
2529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
2629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood/**
2729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood * Class to manage the controlling of preloaded tab.
2829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood */
2929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwoodpublic class PreloadedTabControl {
30e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood    private static final boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED;
3129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    private static final String LOGTAG = "PreloadedTabControl";
3229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
3329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    final Tab mTab;
3429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    private String mLastQuery;
3529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    private boolean mDestroyed;
3629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
3729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public PreloadedTabControl(Tab t) {
38e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (LOGD_ENABLED) Log.d(LOGTAG, "PreloadedTabControl.<init>");
3929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        mTab = t;
4029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
4129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
42e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood    private void maybeSetQuery(final String query, SearchBox sb) {
4329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (!TextUtils.equals(mLastQuery, query)) {
4429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            if (sb != null) {
4529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                if (LOGD_ENABLED) Log.d(LOGTAG, "Changing searchbox query to " + query);
4629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                sb.setVerbatim(true);
4729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                sb.setQuery(query);
48e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                sb.onchange(new SearchBox.SearchBoxListener() {
49e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                    @Override
50e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                    public void onChangeComplete(boolean called) {
51e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                        if (mDestroyed) return;
52e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                        if (LOGD_ENABLED) Log.d(LOGTAG, "Changed searchbox query: " + called);
53e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                        if (called) {
54e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                            mLastQuery = query;
55e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                        }
56e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                    }
57e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                });
5829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            } else {
5929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                if (LOGD_ENABLED) Log.d(LOGTAG, "Cannot set query: no searchbox interface");
6029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            }
6129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
6229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
6329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
6429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public void setQuery(String query) {
6529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        maybeSetQuery(query, mTab.getWebView().getSearchBox());
6629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
6729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
6829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public boolean searchBoxSubmit(final String query,
6929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            final String fallbackUrl, final Map<String, String> fallbackHeaders) {
7029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        final SearchBox sb = mTab.getWebView().getSearchBox();
7129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (sb == null) {
7229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            // no searchbox, cannot submit. Fallback to regular tab creation
7329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            if (LOGD_ENABLED) Log.d(LOGTAG, "No searchbox, cannot submit query");
7429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            return false;
7529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
76e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        maybeSetQuery(query, sb);
77e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (LOGD_ENABLED) Log.d(LOGTAG, "Submitting query " + query);
78a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood        final String currentUrl = mTab.getUrl();
79e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        sb.onsubmit(new SearchBox.SearchBoxListener() {
8029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            @Override
81e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            public void onSubmitComplete(boolean called) {
82e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                if (mDestroyed) return;
83e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                if (LOGD_ENABLED) Log.d(LOGTAG, "Query submitted: " + called);
84e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                if (!called) {
85e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                    if (LOGD_ENABLED) Log.d(LOGTAG, "Query not submitted; falling back");
8629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                    loadUrl(fallbackUrl, fallbackHeaders);
871dd8e82b74b1055fcd572e820a724997550edd33Mathew Inwood                    // make sure that the failed, preloaded URL is cleared from the back stack
88a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                    mTab.clearBackStackWhenItemAdded(Pattern.compile(
89a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                            "^" + Pattern.quote(fallbackUrl) + "$"));
90a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                } else {
91a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                    // ignore the next fragment change, to avoid leaving a blank page in the browser
92a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                    // after the query has been submitted.
93a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                    String currentWithoutFragment = Uri.parse(currentUrl)
94a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                            .buildUpon()
95a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                            .fragment(null)
96a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                            .toString();
97a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                    mTab.clearBackStackWhenItemAdded(
98a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                            Pattern.compile(
99a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                                    "^" +
100a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                                    Pattern.quote(currentWithoutFragment) +
101a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                                    "(\\#.*)?" +
102a829d55e8af65d08d998b8166e42420dda8cf2ffMathew Inwood                                    "$"));
10329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood                }
104e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            }});
10529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        return true;
10629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
10729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
108dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood    public void searchBoxCancel() {
109dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood        SearchBox sb = mTab.getWebView().getSearchBox();
110dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood        if (sb != null) {
111dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood            mLastQuery = null;
112dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood            sb.oncancel(new SearchBox.SearchBoxListener(){
113dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood                @Override
114dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood                public void onCancelComplete(boolean called) {
115dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood                    if (LOGD_ENABLED) Log.d(LOGTAG, "Query cancelled: " + called);
116dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood                }
117dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood            });
118dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood        }
119dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood    }
120dffa72f926d051c089981adf52a44d2c933a0de4Mathew Inwood
12129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public void loadUrlIfChanged(String url, Map<String, String> headers) {
122e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        String currentUrl = mTab.getUrl();
123e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (!TextUtils.isEmpty(currentUrl)) {
124e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            try {
125e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                // remove fragment:
126e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                currentUrl = Uri.parse(currentUrl).buildUpon().fragment(null).build().toString();
127e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            } catch (UnsupportedOperationException e) {
128e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood                // carry on
129e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood            }
130e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        }
131e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (LOGD_ENABLED) Log.d(LOGTAG, "loadUrlIfChanged\nnew: " + url + "\nold: " +currentUrl);
132e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (!TextUtils.equals(url, currentUrl)) {
13329721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood            loadUrl(url, headers);
13429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        }
13529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
13629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
13729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public void loadUrl(String url, Map<String, String> headers) {
13829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        if (LOGD_ENABLED) Log.d(LOGTAG, "Preloading " + url);
13929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        mTab.loadUrl(url, headers);
14029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
14129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
14229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public void destroy() {
143e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood        if (LOGD_ENABLED) Log.d(LOGTAG, "PreloadedTabControl.destroy");
14429721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        mDestroyed = true;
14529721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        mTab.destroy();
14629721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
14729721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
14829721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    public Tab getTab() {
14929721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood        return mTab;
15029721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood    }
15129721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood
15229721c2c6cc7f79a52962556c4431b71bb3ce46eMathew Inwood}
153