Home | History | Annotate | Download | only in google
      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 
     17 package com.android.quicksearchbox.google;
     18 
     19 import com.android.quicksearchbox.R;
     20 import com.android.quicksearchbox.SearchSettings;
     21 import com.android.quicksearchbox.SearchSettingsImpl;
     22 import com.android.quicksearchbox.util.HttpHelper;
     23 
     24 import android.content.Context;
     25 import android.content.SharedPreferences;
     26 import android.os.AsyncTask;
     27 import android.text.TextUtils;
     28 import android.util.Log;
     29 
     30 import java.util.Locale;
     31 
     32 /**
     33  * Helper to build the base URL for all search requests.
     34  */
     35 public class SearchBaseUrlHelper implements SharedPreferences.OnSharedPreferenceChangeListener {
     36     private static final boolean DBG = false;
     37     private static final String TAG = "QSB.SearchBaseUrlHelper";
     38 
     39     private static final String DOMAIN_CHECK_URL =
     40             "https://www.google.com/searchdomaincheck?format=domain";
     41 
     42     private static final long SEARCH_BASE_URL_EXPIRY_MS = 24 * 3600 * 1000L;
     43 
     44     private final HttpHelper mHttpHelper;
     45     private final Context mContext;
     46     private final SearchSettings mSearchSettings;
     47 
     48     /**
     49      * Note that this constructor will spawn a thread to issue a HTTP
     50      * request if shouldUseGoogleCom is false.
     51      */
     52     public SearchBaseUrlHelper(Context context, HttpHelper helper,
     53             SearchSettings searchSettings, SharedPreferences prefs) {
     54         mHttpHelper = helper;
     55         mContext = context;
     56         mSearchSettings = searchSettings;
     57 
     58         // Note: This earlier used an inner class, but that causes issues
     59         // because SharedPreferencesImpl uses a WeakHashMap< > and the listener
     60         // will be GC'ed unless we keep a reference to it here.
     61         prefs.registerOnSharedPreferenceChangeListener(this);
     62 
     63         maybeUpdateBaseUrlSetting(false);
     64     }
     65 
     66     /**
     67      * Update the base search url, either:
     68      * (a) it has never been set (first run)
     69      * (b) it has expired
     70      * (c) if the caller forces an update by setting the "force" parameter.
     71      *
     72      * @param force if true, then the URL is reset whether or not it has
     73      *     expired.
     74      */
     75     public void maybeUpdateBaseUrlSetting(boolean force) {
     76         long lastUpdateTime = mSearchSettings.getSearchBaseDomainApplyTime();
     77         long currentTime = System.currentTimeMillis();
     78 
     79         if (force || lastUpdateTime == -1 ||
     80                 currentTime - lastUpdateTime >= SEARCH_BASE_URL_EXPIRY_MS) {
     81             if (mSearchSettings.shouldUseGoogleCom()) {
     82                 setSearchBaseDomain(getDefaultBaseDomain());
     83             } else {
     84                 checkSearchDomain();
     85             }
     86         }
     87     }
     88 
     89     /**
     90      * @return the base url for searches.
     91      */
     92     public String getSearchBaseUrl() {
     93         return mContext.getResources().getString(R.string.google_search_base_pattern,
     94                 getSearchDomain(), GoogleSearch.getLanguage(Locale.getDefault()));
     95     }
     96 
     97     /**
     98      * @return the search domain. This is of the form "google.co.xx" or "google.com",
     99      *     used by UI code.
    100      */
    101     public String getSearchDomain() {
    102         String domain = mSearchSettings.getSearchBaseDomain();
    103 
    104         if (domain == null) {
    105             if (DBG) {
    106                 Log.w(TAG, "Search base domain was null, last apply time=" +
    107                         mSearchSettings.getSearchBaseDomainApplyTime());
    108             }
    109 
    110             // This is required to deal with the case wherein getSearchDomain
    111             // is called before checkSearchDomain returns a valid URL. This will
    112             // happen *only* on the first run of the app when the "use google.com"
    113             // option is unchecked. In other cases, the previously set domain (or
    114             // the default) will be returned.
    115             //
    116             // We have no choice in this case but to use the default search domain.
    117             domain = getDefaultBaseDomain();
    118         }
    119 
    120         if (domain.startsWith(".")) {
    121             if (DBG) Log.d(TAG, "Prepending www to " + domain);
    122             domain = "www" + domain;
    123         }
    124         return domain;
    125     }
    126 
    127     /**
    128      * Issue a request to google.com/searchdomaincheck to retrieve the base
    129      * URL for search requests.
    130      */
    131     private void checkSearchDomain() {
    132         final HttpHelper.GetRequest request = new HttpHelper.GetRequest(DOMAIN_CHECK_URL);
    133 
    134         new AsyncTask<Void, Void, Void>() {
    135             @Override
    136             protected Void doInBackground(Void ... params) {
    137                 if (DBG) Log.d(TAG, "Starting request to /searchdomaincheck");
    138                 String domain;
    139                 try {
    140                     domain = mHttpHelper.get(request);
    141                 } catch (Exception e) {
    142                     if (DBG) Log.d(TAG, "Request to /searchdomaincheck failed : " + e);
    143                     // Swallow any exceptions thrown by the HTTP helper, in
    144                     // this rare case, we just use the default URL.
    145                     domain = getDefaultBaseDomain();
    146 
    147                     return null;
    148                 }
    149 
    150                 if (DBG) Log.d(TAG, "Request to /searchdomaincheck succeeded");
    151                 setSearchBaseDomain(domain);
    152 
    153                 return null;
    154             }
    155         }.execute();
    156     }
    157 
    158     private String getDefaultBaseDomain() {
    159         return mContext.getResources().getString(R.string.default_search_domain);
    160     }
    161 
    162     private void setSearchBaseDomain(String domain) {
    163         if (DBG) Log.d(TAG, "Setting search domain to : " + domain);
    164 
    165         mSearchSettings.setSearchBaseDomain(domain);
    166     }
    167 
    168     @Override
    169     public void onSharedPreferenceChanged(SharedPreferences pref, String key) {
    170         // Listen for changes only to the SEARCH_BASE_URL preference.
    171         if (DBG) Log.d(TAG, "Handling changed preference : " + key);
    172         if (SearchSettingsImpl.USE_GOOGLE_COM_PREF.equals(key)) {
    173             maybeUpdateBaseUrlSetting(true);
    174         }
    175     }
    176 }