1c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath/* 2c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Copyright (C) 2010 The Android Open Source Project 3c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * 4c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 5c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * you may not use this file except in compliance with the License. 6c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * You may obtain a copy of the License at 7c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * 8c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 9c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * 10c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Unless required by applicable law or agreed to in writing, software 11c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 12c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * See the License for the specific language governing permissions and 14c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * limitations under the License. 15c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 16c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 17c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathpackage com.android.quicksearchbox.google; 18c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 19c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport com.android.quicksearchbox.R; 20c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport com.android.quicksearchbox.SearchSettings; 211259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamathimport com.android.quicksearchbox.SearchSettingsImpl; 22c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport com.android.quicksearchbox.util.HttpHelper; 23c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 24c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport android.content.Context; 251259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamathimport android.content.SharedPreferences; 26c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport android.os.AsyncTask; 27964deade9111e08f22dce9c3c97b84e9c0f5b27aBjorn Bringertimport android.text.TextUtils; 28c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport android.util.Log; 29c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 30c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamathimport java.util.Locale; 31c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 32c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath/** 33c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Helper to build the base URL for all search requests. 34c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 351259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamathpublic class SearchBaseUrlHelper implements SharedPreferences.OnSharedPreferenceChangeListener { 36c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private static final boolean DBG = false; 37c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private static final String TAG = "QSB.SearchBaseUrlHelper"; 38c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 39c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private static final String DOMAIN_CHECK_URL = 40c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath "https://www.google.com/searchdomaincheck?format=domain"; 41c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 42c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private static final long SEARCH_BASE_URL_EXPIRY_MS = 24 * 3600 * 1000L; 43c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 44c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private final HttpHelper mHttpHelper; 45c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private final Context mContext; 46c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private final SearchSettings mSearchSettings; 47c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 48c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath /** 49c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Note that this constructor will spawn a thread to issue a HTTP 50c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * request if shouldUseGoogleCom is false. 51c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 52c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath public SearchBaseUrlHelper(Context context, HttpHelper helper, 531259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath SearchSettings searchSettings, SharedPreferences prefs) { 54c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath mHttpHelper = helper; 55c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath mContext = context; 56c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath mSearchSettings = searchSettings; 57c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 581259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath // Note: This earlier used an inner class, but that causes issues 591259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath // because SharedPreferencesImpl uses a WeakHashMap< > and the listener 601259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath // will be GC'ed unless we keep a reference to it here. 611259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath prefs.registerOnSharedPreferenceChangeListener(this); 621259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath 63c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath maybeUpdateBaseUrlSetting(false); 64c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 65c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 66c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath /** 67c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Update the base search url, either: 68c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * (a) it has never been set (first run) 69c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * (b) it has expired 70c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * (c) if the caller forces an update by setting the "force" parameter. 71c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * 72c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * @param force if true, then the URL is reset whether or not it has 73c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * expired. 74c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 75c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath public void maybeUpdateBaseUrlSetting(boolean force) { 768f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath long lastUpdateTime = mSearchSettings.getSearchBaseDomainApplyTime(); 77c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath long currentTime = System.currentTimeMillis(); 78c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 79c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath if (force || lastUpdateTime == -1 || 80c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath currentTime - lastUpdateTime >= SEARCH_BASE_URL_EXPIRY_MS) { 81c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath if (mSearchSettings.shouldUseGoogleCom()) { 828f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath setSearchBaseDomain(getDefaultBaseDomain()); 83c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } else { 84c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath checkSearchDomain(); 85c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 86c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 87c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 88c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 89c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath /** 90c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * @return the base url for searches. 91c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 92b1cdcbce5d9c5edb20309c59b7cb52f76bbfac72Narayan Kamath public String getSearchBaseUrl() { 938f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath return mContext.getResources().getString(R.string.google_search_base_pattern, 948f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath getSearchDomain(), GoogleSearch.getLanguage(Locale.getDefault())); 95c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 96c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 97c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath /** 981259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath * @return the search domain. This is of the form "google.co.xx" or "google.com", 991259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath * used by UI code. 1001259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath */ 1011259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath public String getSearchDomain() { 1028f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath String domain = mSearchSettings.getSearchBaseDomain(); 103f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath 104f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath if (domain == null) { 105f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath if (DBG) { 106f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath Log.w(TAG, "Search base domain was null, last apply time=" + 107f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath mSearchSettings.getSearchBaseDomainApplyTime()); 108f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath } 109f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath 110f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // This is required to deal with the case wherein getSearchDomain 111f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // is called before checkSearchDomain returns a valid URL. This will 112f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // happen *only* on the first run of the app when the "use google.com" 113f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // option is unchecked. In other cases, the previously set domain (or 114f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // the default) will be returned. 115f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // 116f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath // We have no choice in this case but to use the default search domain. 117f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath domain = getDefaultBaseDomain(); 118f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath } 119f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath 1208f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath if (domain.startsWith(".")) { 1218f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath if (DBG) Log.d(TAG, "Prepending www to " + domain); 1228f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath domain = "www" + domain; 1231259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath } 1248f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath return domain; 1251259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath } 1261259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath 1271259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath /** 128c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * Issue a request to google.com/searchdomaincheck to retrieve the base 129c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath * URL for search requests. 130c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath */ 131c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath private void checkSearchDomain() { 132c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath final HttpHelper.GetRequest request = new HttpHelper.GetRequest(DOMAIN_CHECK_URL); 133c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 134c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath new AsyncTask<Void, Void, Void>() { 135c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath @Override 136c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath protected Void doInBackground(Void ... params) { 137c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath if (DBG) Log.d(TAG, "Starting request to /searchdomaincheck"); 138c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath String domain; 139c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath try { 140c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath domain = mHttpHelper.get(request); 141c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } catch (Exception e) { 142c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath if (DBG) Log.d(TAG, "Request to /searchdomaincheck failed : " + e); 143c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath // Swallow any exceptions thrown by the HTTP helper, in 144c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath // this rare case, we just use the default URL. 1458f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath domain = getDefaultBaseDomain(); 146c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 147c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath return null; 148c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 149c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 1501259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath if (DBG) Log.d(TAG, "Request to /searchdomaincheck succeeded"); 1518f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath setSearchBaseDomain(domain); 152f4e4f922ad11b7d5bdc6347436f1e129fbae9041Narayan Kamath 153c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath return null; 154c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 155c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath }.execute(); 156c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 157c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 1588f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath private String getDefaultBaseDomain() { 1598f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath return mContext.getResources().getString(R.string.default_search_domain); 160c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 161c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 1628f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath private void setSearchBaseDomain(String domain) { 1638f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath if (DBG) Log.d(TAG, "Setting search domain to : " + domain); 164c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 1658f65daa6e6df644d6cc6a9a2e100c01feb33bbd2Narayan Kamath mSearchSettings.setSearchBaseDomain(domain); 166c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath } 1671259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath 1681259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath @Override 1691259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath public void onSharedPreferenceChanged(SharedPreferences pref, String key) { 1701259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath // Listen for changes only to the SEARCH_BASE_URL preference. 1711259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath if (DBG) Log.d(TAG, "Handling changed preference : " + key); 1721259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath if (SearchSettingsImpl.USE_GOOGLE_COM_PREF.equals(key)) { 1731259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath maybeUpdateBaseUrlSetting(true); 1741259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath } 1751259cf7175b0eacac403fb5298684bdbf3ef672cNarayan Kamath } 176b1cdcbce5d9c5edb20309c59b7cb52f76bbfac72Narayan Kamath}