SearchBaseUrlHelper.java revision 964deade9111e08f22dce9c3c97b84e9c0f5b27a
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.quicksearchbox.google; 18 19import com.android.quicksearchbox.R; 20import com.android.quicksearchbox.SearchSettings; 21import com.android.quicksearchbox.SearchSettingsImpl; 22import com.android.quicksearchbox.util.HttpHelper; 23 24import android.content.Context; 25import android.content.SharedPreferences; 26import android.os.AsyncTask; 27import android.os.Handler; 28import android.text.TextUtils; 29import android.util.Log; 30 31import java.util.Locale; 32 33/** 34 * Helper to build the base URL for all search requests. 35 */ 36public class SearchBaseUrlHelper implements SharedPreferences.OnSharedPreferenceChangeListener { 37 private static final boolean DBG = false; 38 private static final String TAG = "QSB.SearchBaseUrlHelper"; 39 40 private static final String DOMAIN_CHECK_URL = 41 "https://www.google.com/searchdomaincheck?format=domain"; 42 43 private static final long SEARCH_BASE_URL_EXPIRY_MS = 24 * 3600 * 1000L; 44 45 private final HttpHelper mHttpHelper; 46 private final Context mContext; 47 private final SearchSettings mSearchSettings; 48 49 /** 50 * Note that this constructor will spawn a thread to issue a HTTP 51 * request if shouldUseGoogleCom is false. 52 */ 53 public SearchBaseUrlHelper(Context context, HttpHelper helper, 54 SearchSettings searchSettings, SharedPreferences prefs) { 55 mHttpHelper = helper; 56 mContext = context; 57 mSearchSettings = searchSettings; 58 59 // Note: This earlier used an inner class, but that causes issues 60 // because SharedPreferencesImpl uses a WeakHashMap< > and the listener 61 // will be GC'ed unless we keep a reference to it here. 62 prefs.registerOnSharedPreferenceChangeListener(this); 63 64 maybeUpdateBaseUrlSetting(false); 65 } 66 67 /** 68 * Update the base search url, either: 69 * (a) it has never been set (first run) 70 * (b) it has expired 71 * (c) if the caller forces an update by setting the "force" parameter. 72 * 73 * @param force if true, then the URL is reset whether or not it has 74 * expired. 75 */ 76 public void maybeUpdateBaseUrlSetting(boolean force) { 77 long lastUpdateTime = mSearchSettings.getSearchBaseUrlApplyTime(); 78 long currentTime = System.currentTimeMillis(); 79 80 if (force || lastUpdateTime == -1 || 81 currentTime - lastUpdateTime >= SEARCH_BASE_URL_EXPIRY_MS) { 82 if (mSearchSettings.shouldUseGoogleCom()) { 83 setSearchBaseUrl(getDefaultBaseUrl()); 84 } else { 85 checkSearchDomain(); 86 } 87 } 88 } 89 90 /** 91 * @return the base url for searches. 92 */ 93 public String getSearchBaseUrl() { 94 String domain = mSearchSettings.getSearchBaseUrl(); 95 if (TextUtils.isEmpty(domain)) domain = getDefaultBaseUrl(); 96 return domain; 97 } 98 99 /** 100 * @return the search domain. This is of the form "google.co.xx" or "google.com", 101 * used by UI code. 102 */ 103 public String getSearchDomain() { 104 String baseUrl = getSearchBaseUrl(); 105 106 final int start = baseUrl.indexOf(".google."); 107 final int endMobile = baseUrl.indexOf("/m"); 108 final int endDesktop = baseUrl.indexOf("/search"); 109 if (start > 0) { 110 if (endMobile > 0) { 111 // This is a mobile URL. (/m) 112 return baseUrl.substring(start + 1, endMobile); 113 } 114 if (endDesktop > 0) { 115 // This is a desktop URL. (/search) 116 return baseUrl.substring(start + 1, endDesktop); 117 } 118 } 119 120 if (DBG) Log.w(TAG, "Unable to extract search domain from URL" + baseUrl); 121 122 return baseUrl; 123 } 124 125 /** 126 * Issue a request to google.com/searchdomaincheck to retrieve the base 127 * URL for search requests. 128 */ 129 private void checkSearchDomain() { 130 final HttpHelper.GetRequest request = new HttpHelper.GetRequest(DOMAIN_CHECK_URL); 131 132 new AsyncTask<Void, Void, Void>() { 133 @Override 134 protected Void doInBackground(Void ... params) { 135 if (DBG) Log.d(TAG, "Starting request to /searchdomaincheck"); 136 String domain; 137 try { 138 domain = mHttpHelper.get(request); 139 } catch (Exception e) { 140 if (DBG) Log.d(TAG, "Request to /searchdomaincheck failed : " + e); 141 // Swallow any exceptions thrown by the HTTP helper, in 142 // this rare case, we just use the default URL. 143 setSearchBaseUrl(getDefaultBaseUrl()); 144 145 return null; 146 } 147 148 String searchDomain = mContext.getResources().getString( 149 R.string.google_search_base_pattern, domain, 150 GoogleSearch.getLanguage(Locale.getDefault())); 151 152 if (DBG) Log.d(TAG, "Request to /searchdomaincheck succeeded"); 153 setSearchBaseUrl(searchDomain); 154 return null; 155 } 156 }.execute(); 157 } 158 159 private String getDefaultBaseUrl() { 160 return (mContext.getResources().getString( 161 R.string.google_search_base, 162 GoogleSearch.getLanguage(Locale.getDefault()))); 163 } 164 165 private void setSearchBaseUrl(String searchDomain) { 166 if (DBG) Log.d(TAG, "Setting search domain to : " + searchDomain); 167 168 mSearchSettings.setSearchBaseUrl(searchDomain); 169 } 170 171 @Override 172 public void onSharedPreferenceChanged(SharedPreferences pref, String key) { 173 // Listen for changes only to the SEARCH_BASE_URL preference. 174 if (DBG) Log.d(TAG, "Handling changed preference : " + key); 175 if (SearchSettingsImpl.USE_GOOGLE_COM_PREF.equals(key)) { 176 maybeUpdateBaseUrlSetting(true); 177 } 178 } 179}