summaryrefslogtreecommitdiffstats
path: root/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/SuggestClient.java')
-rw-r--r--mobile/android/base/java/org/mozilla/gecko/SuggestClient.java142
1 files changed, 142 insertions, 0 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java b/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java
new file mode 100644
index 000000000..e43bbef1f
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/SuggestClient.java
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+
+import org.json.JSONArray;
+import org.mozilla.gecko.annotation.RobocopTarget;
+import org.mozilla.gecko.util.HardwareUtils;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+import org.mozilla.gecko.util.NetworkUtils;
+
+/**
+ * Use network-based search suggestions.
+ */
+public class SuggestClient {
+ private static final String LOGTAG = "GeckoSuggestClient";
+
+ // This should go through GeckoInterface to get the UA, but the search activity
+ // doesn't use a GeckoView yet. Until it does, get the UA directly.
+ private static final String USER_AGENT = HardwareUtils.isTablet() ?
+ AppConstants.USER_AGENT_FENNEC_TABLET : AppConstants.USER_AGENT_FENNEC_MOBILE;
+
+ private final Context mContext;
+ private final int mTimeout;
+
+ // should contain the string "__searchTerms__", which is replaced with the query
+ private final String mSuggestTemplate;
+
+ // the maximum number of suggestions to return
+ private final int mMaxResults;
+
+ // used by robocop for testing
+ private final boolean mCheckNetwork;
+
+ // used to make suggestions appear instantly after opt-in
+ private String mPrevQuery;
+ private ArrayList<String> mPrevResults;
+
+ @RobocopTarget
+ public SuggestClient(Context context, String suggestTemplate, int timeout, int maxResults, boolean checkNetwork) {
+ mContext = context;
+ mMaxResults = maxResults;
+ mSuggestTemplate = suggestTemplate;
+ mTimeout = timeout;
+ mCheckNetwork = checkNetwork;
+ }
+
+ public String getSuggestTemplate() {
+ return mSuggestTemplate;
+ }
+
+ /**
+ * Queries for a given search term and returns an ArrayList of suggestions.
+ */
+ public ArrayList<String> query(String query) {
+ if (query.equals(mPrevQuery))
+ return mPrevResults;
+
+ ArrayList<String> suggestions = new ArrayList<String>();
+ if (TextUtils.isEmpty(mSuggestTemplate) || TextUtils.isEmpty(query)) {
+ return suggestions;
+ }
+
+ if (!NetworkUtils.isConnected(mContext) && mCheckNetwork) {
+ Log.i(LOGTAG, "Not connected to network");
+ return suggestions;
+ }
+
+ try {
+ String encoded = URLEncoder.encode(query, "UTF-8");
+ String suggestUri = mSuggestTemplate.replace("__searchTerms__", encoded);
+
+ URL url = new URL(suggestUri);
+ String json = null;
+ HttpURLConnection urlConnection = null;
+ InputStream in = null;
+ try {
+ urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.setConnectTimeout(mTimeout);
+ urlConnection.setRequestProperty("User-Agent", USER_AGENT);
+ in = new BufferedInputStream(urlConnection.getInputStream());
+ json = convertStreamToString(in);
+ } finally {
+ if (urlConnection != null)
+ urlConnection.disconnect();
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ Log.e(LOGTAG, "error", e);
+ }
+ }
+ }
+
+ if (json != null) {
+ /*
+ * Sample result:
+ * ["foo",["food network","foothill college","foot locker",...]]
+ */
+ JSONArray results = new JSONArray(json);
+ JSONArray jsonSuggestions = results.getJSONArray(1);
+
+ int added = 0;
+ for (int i = 0; (i < jsonSuggestions.length()) && (added < mMaxResults); i++) {
+ String suggestion = jsonSuggestions.getString(i);
+ if (!suggestion.equalsIgnoreCase(query)) {
+ suggestions.add(suggestion);
+ added++;
+ }
+ }
+ } else {
+ Log.e(LOGTAG, "Suggestion query failed");
+ }
+ } catch (Exception e) {
+ Log.e(LOGTAG, "Error", e);
+ }
+
+ mPrevQuery = query;
+ mPrevResults = suggestions;
+ return suggestions;
+ }
+
+ private String convertStreamToString(java.io.InputStream is) {
+ try {
+ return new java.util.Scanner(is).useDelimiter("\\A").next();
+ } catch (java.util.NoSuchElementException e) {
+ return "";
+ }
+ }
+}