summaryrefslogtreecommitdiffstats
path: root/src/com/android/browser/BrowserProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/browser/BrowserProvider.java')
-rw-r--r--src/com/android/browser/BrowserProvider.java383
1 files changed, 212 insertions, 171 deletions
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index 7aa5bb2..0c930c6 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -16,23 +16,26 @@
package com.android.browser;
+import android.app.ISearchManager;
import android.app.SearchManager;
+import android.content.ComponentName;
import android.content.ContentProvider;
-import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.UriMatcher;
import android.database.AbstractCursor;
-import android.database.ContentObserver;
import android.database.Cursor;
-import android.database.DataSetObserver;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Browser;
import android.util.Log;
+import android.server.search.SearchableInfo;
import android.text.util.Regex;
public class BrowserProvider extends ContentProvider {
@@ -40,22 +43,41 @@ public class BrowserProvider extends ContentProvider {
private SQLiteOpenHelper mOpenHelper;
private static final String sDatabaseName = "browser.db";
private static final String TAG = "BrowserProvider";
- private static final String ORDER_BY = "date DESC";
+ private static final String ORDER_BY = "visits DESC, date DESC";
private static final String[] TABLE_NAMES = new String[] {
"bookmarks", "searches"
};
- private static final String[] SUGGEST_PROJECTION = new String [] {
- "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
- "url AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA,
- "url AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
- "title AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
- "_id"
+ private static final String[] SUGGEST_PROJECTION = new String[] {
+ "_id", "url", "title", "bookmark"
};
private static final String SUGGEST_SELECTION =
"url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?";
private String[] SUGGEST_ARGS = new String[4];
+ // shared suggestion array index, make sure to match COLUMNS
+ private static final int SUGGEST_COLUMN_INTENT_ACTION_ID = 1;
+ private static final int SUGGEST_COLUMN_INTENT_DATA_ID = 2;
+ private static final int SUGGEST_COLUMN_TEXT_1_ID = 3;
+ private static final int SUGGEST_COLUMN_TEXT_2_ID = 4;
+ private static final int SUGGEST_COLUMN_ICON_1_ID = 5;
+ private static final int SUGGEST_COLUMN_ICON_2_ID = 6;
+ private static final int SUGGEST_COLUMN_QUERY_ID = 7;
+
+ // shared suggestion columns
+ private static final String[] COLUMNS = new String[] {
+ "_id",
+ SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+ SearchManager.SUGGEST_COLUMN_INTENT_DATA,
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_ICON_1,
+ SearchManager.SUGGEST_COLUMN_ICON_2,
+ SearchManager.SUGGEST_COLUMN_QUERY};
+
+ private static final int MAX_SUGGESTION_SHORT_ENTRIES = 3;
+ private static final int MAX_SUGGESTION_LONG_ENTRIES = 6;
+
// make sure that these match the index of TABLE_NAMES
private static final int URI_MATCH_BOOKMARKS = 0;
private static final int URI_MATCH_SEARCHES = 1;
@@ -206,221 +228,195 @@ public class BrowserProvider extends ContentProvider {
}
/*
- * Subclass AbstractCursor so we can add "Google Search"
+ * Subclass AbstractCursor so we can combine multiple Cursors and add
+ * "Google Search".
+ * Here are the rules.
+ * 1. We only have MAX_SUGGESTION_LONG_ENTRIES in the list plus
+ * "Google Search";
+ * 2. If bookmark/history entries are less than
+ * (MAX_SUGGESTION_SHORT_ENTRIES -1), we include Google suggest.
*/
private class MySuggestionCursor extends AbstractCursor {
- private Cursor mCursor;
+ private Cursor mHistoryCursor;
+ private Cursor mSuggestCursor;
+ private int mHistoryCount;
+ private int mSuggestionCount;
private boolean mBeyondCursor;
private String mString;
- private Uri mNotifyUri;
- private ContentResolver mContentResolver;
- private AbstractCursor.SelfContentObserver mObserver;
- private final Object mObserverLock = new Object();
-
- public MySuggestionCursor(Cursor c, String string) {
- mCursor = c;
- if (Regex.WEB_URL_PATTERN.matcher(string).matches()) {
- mString = "";
- } else {
- mString = string;
+
+ public MySuggestionCursor(Cursor hc, Cursor sc, String string) {
+ mHistoryCursor = hc;
+ mSuggestCursor = sc;
+ mHistoryCount = hc.getCount();
+ mSuggestionCount = sc != null ? sc.getCount() : 0;
+ if (mSuggestionCount > (MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount)) {
+ mSuggestionCount = MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount;
}
+ mString = string;
mBeyondCursor = false;
}
+ @Override
public boolean onMove(int oldPosition, int newPosition) {
- if (mCursor.getCount() == newPosition) {
- mBeyondCursor = true;
- } else {
- mCursor.moveToPosition(newPosition);
+ if (mHistoryCursor == null) {
+ return false;
+ }
+ if (mHistoryCount > newPosition) {
+ mHistoryCursor.moveToPosition(newPosition);
+ mBeyondCursor = false;
+ } else if (mHistoryCount + mSuggestionCount > newPosition) {
+ mSuggestCursor.moveToPosition(newPosition - mHistoryCount);
mBeyondCursor = false;
+ } else {
+ mBeyondCursor = true;
}
return true;
}
+ @Override
public int getCount() {
if (mString.length() > 0) {
- return mCursor.getCount() + 1;
+ return mHistoryCount + mSuggestionCount + 1;
} else {
- return mCursor.getCount();
+ return mHistoryCount + mSuggestionCount;
}
}
- public boolean deleteRow() {
- return !mBeyondCursor && mCursor.deleteRow();
- }
-
+ @Override
public String[] getColumnNames() {
- return mCursor.getColumnNames();
- }
-
- public int getColumnCount() {
- return mCursor.getColumnCount();
+ return COLUMNS;
}
+ @Override
public String getString(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getString(columnIndex);
- }
- switch (columnIndex) {
- case 2: // SearchManager.SUGGEST_COLUMN_TEXT_1
- return "Google Search for \"" + mString + "\"";
- case 1: // SearchManager.SUGGEST_COLUMN_INTENT_DATA
- return BrowserActivity.composeSearchUrl(mString);
- case 3: // SearchManager.SUGGEST_COLUMN_TEXT_2
- default:
- return "";
- }
- }
-
- public short getShort(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getShort(columnIndex);
- }
- if (0 == columnIndex) {
- return 0;
- }
- return -1;
- }
-
- public int getInt(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getInt(columnIndex);
- }
- if (0 == columnIndex) {
- return 0;
- }
- return -1;
- }
+ if ((mPos != -1 && mHistoryCursor != null)) {
+ switch(columnIndex) {
+ case SUGGEST_COLUMN_INTENT_ACTION_ID:
+ if (mHistoryCount > mPos) {
+ return Intent.ACTION_VIEW;
+ } else {
+ return Intent.ACTION_SEARCH;
+ }
- public long getLong(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getLong(columnIndex);
- }
- if (0 == columnIndex) {
- return 0;
- }
- return -1;
- }
+ case SUGGEST_COLUMN_INTENT_DATA_ID:
+ if (mHistoryCount > mPos) {
+ return mHistoryCursor.getString(1);
+ } else {
+ return null;
+ }
- public float getFloat(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getFloat(columnIndex);
- }
- if (0 == columnIndex) {
- return 0f;
- }
- return -1f;
- }
+ case SUGGEST_COLUMN_TEXT_1_ID:
+ if (mHistoryCount > mPos) {
+ return mHistoryCursor.getString(1);
+ } else if (!mBeyondCursor) {
+ return mSuggestCursor.getString(1);
+ } else {
+ return mString;
+ }
- public double getDouble(int columnIndex) {
- if (!mBeyondCursor) {
- return mCursor.getDouble(columnIndex);
- }
- if (0 == columnIndex) {
- return 0.0;
- }
- return -1.0;
- }
+ case SUGGEST_COLUMN_TEXT_2_ID:
+ if (mHistoryCount > mPos) {
+ return mHistoryCursor.getString(2);
+ } else if (!mBeyondCursor) {
+ return mSuggestCursor.getString(2);
+ } else {
+ return getContext().getString(R.string.search_google);
+ }
- public boolean isNull(int columnIndex) {
- return mCursor.isNull(columnIndex);
- }
+ case SUGGEST_COLUMN_ICON_1_ID:
+ if (mHistoryCount > mPos) {
+ if (mHistoryCursor.getInt(3) == 1) {
+ return new Integer(
+ R.drawable.ic_search_category_bookmark)
+ .toString();
+ } else {
+ return new Integer(
+ R.drawable.ic_search_category_history)
+ .toString();
+ }
+ } else {
+ return new Integer(
+ R.drawable.ic_search_category_suggest)
+ .toString();
+ }
- public boolean supportsUpdates() {
- return false;
- }
+ case SUGGEST_COLUMN_ICON_2_ID:
+ return new String("0");
- public boolean hasUpdates() {
- return false;
+ case SUGGEST_COLUMN_QUERY_ID:
+ if (mHistoryCount > mPos) {
+ return null;
+ } else if (!mBeyondCursor) {
+ return mSuggestCursor.getString(3);
+ } else {
+ return mString;
+ }
+ }
+ }
+ return null;
}
- public boolean updateString(int columnIndex, String value) {
- return false;
+ @Override
+ public double getDouble(int column) {
+ throw new UnsupportedOperationException();
}
- public boolean updateShort(int columnIndex, short value) {
- return false;
+ @Override
+ public float getFloat(int column) {
+ throw new UnsupportedOperationException();
}
- public boolean updateInt(int columnIndex, int value) {
- return false;
+ @Override
+ public int getInt(int column) {
+ throw new UnsupportedOperationException();
}
- public boolean updateLong(int columnIndex, long value) {
- return false;
+ @Override
+ public long getLong(int column) {
+ if ((mPos != -1) && column == 0) {
+ return mPos; // use row# as the _Id
+ }
+ throw new UnsupportedOperationException();
}
- public boolean updateFloat(int columnIndex, float value) {
- return false;
+ @Override
+ public short getShort(int column) {
+ throw new UnsupportedOperationException();
}
- public boolean updateDouble(int columnIndex, double value) {
- return false;
+ @Override
+ public boolean isNull(int column) {
+ throw new UnsupportedOperationException();
}
// TODO Temporary change, finalize after jq's changes go in
public void deactivate() {
- if (mCursor != null) {
- mCursor.deactivate();
+ if (mHistoryCursor != null) {
+ mHistoryCursor.deactivate();
+ }
+ if (mSuggestCursor != null) {
+ mSuggestCursor.deactivate();
}
super.deactivate();
}
public boolean requery() {
- return mCursor.requery();
+ return (mHistoryCursor != null ? mHistoryCursor.requery() : false) |
+ (mSuggestCursor != null ? mSuggestCursor.requery() : false);
}
// TODO Temporary change, finalize after jq's changes go in
public void close() {
super.close();
- if (mCursor != null) {
- mCursor.close();
- mCursor = null;
- }
- }
-
- public void registerContentObserver(ContentObserver observer) {
- super.registerContentObserver(observer);
- }
-
- public void unregisterContentObserver(ContentObserver observer) {
- super.unregisterContentObserver(observer);
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- super.registerDataSetObserver(observer);
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- super.unregisterDataSetObserver(observer);
- }
-
- protected void onChange(boolean selfChange) {
- synchronized (mObserverLock) {
- super.onChange(selfChange);
- if (mNotifyUri != null && selfChange) {
- mContentResolver.notifyChange(mNotifyUri, mObserver);
- }
+ if (mHistoryCursor != null) {
+ mHistoryCursor.close();
+ mHistoryCursor = null;
}
- }
-
- public void setNotificationUri(ContentResolver cr, Uri uri) {
- synchronized (mObserverLock) {
- if (mObserver != null) {
- cr.unregisterContentObserver(mObserver);
- }
- mObserver = new AbstractCursor.SelfContentObserver(this);
- cr.registerContentObserver(uri, true, mObserver);
- mCursor.setNotificationUri(cr, uri);
- super.setNotificationUri(cr, uri);
- mContentResolver = cr;
- mNotifyUri = uri;
+ if (mSuggestCursor != null) {
+ mSuggestCursor.close();
+ mSuggestCursor = null;
}
}
-
- public boolean getWantsAllOnMoveCalls() {
- return mCursor.getWantsAllOnMoveCalls();
- }
}
@Override
@@ -455,13 +451,58 @@ public class BrowserProvider extends ContentProvider {
suggestSelection = SUGGEST_SELECTION;
}
}
- // Suggestions are always performed with the default sort order:
- // date ASC.
+
Cursor c = db.query(TABLE_NAMES[URI_MATCH_BOOKMARKS],
SUGGEST_PROJECTION, suggestSelection, myArgs, null, null,
- ORDER_BY, null);
- c.setNotificationUri(getContext().getContentResolver(), url);
- return new MySuggestionCursor(c, selectionArgs[0]);
+ ORDER_BY,
+ (new Integer(MAX_SUGGESTION_LONG_ENTRIES)).toString());
+
+ if (Regex.WEB_URL_PATTERN.matcher(selectionArgs[0]).matches()) {
+ return new MySuggestionCursor(c, null, "");
+ } else {
+ // get Google suggest if there is still space in the list
+ if (myArgs != null && myArgs.length > 1
+ && c.getCount() < (MAX_SUGGESTION_SHORT_ENTRIES - 1)) {
+ ISearchManager sm = ISearchManager.Stub
+ .asInterface(ServiceManager
+ .getService(Context.SEARCH_SERVICE));
+ SearchableInfo si = null;
+ try {
+ // use the global search to get Google suggest provider
+ si = sm.getSearchableInfo(new ComponentName(
+ getContext(), "com.android.browser"), true);
+
+ // similar to the getSuggestions() in SearchDialog.java
+ StringBuilder uriStr = new StringBuilder("content://");
+ uriStr.append(si.getSuggestAuthority());
+ // if content path provided, insert it now
+ final String contentPath = si.getSuggestPath();
+ if (contentPath != null) {
+ uriStr.append('/');
+ uriStr.append(contentPath);
+ }
+ // append standard suggestion query path
+ uriStr.append('/' + SearchManager.SUGGEST_URI_PATH_QUERY);
+ // inject query, either as selection args or inline
+ String[] selArgs = null;
+ if (si.getSuggestSelection() != null) {
+ selArgs = new String[] {selectionArgs[0]};
+ } else {
+ uriStr.append('/');
+ uriStr.append(Uri.encode(selectionArgs[0]));
+ }
+
+ // finally, make the query
+ Cursor sc = getContext().getContentResolver().query(
+ Uri.parse(uriStr.toString()), null,
+ si.getSuggestSelection(), selArgs, null);
+
+ return new MySuggestionCursor(c, sc, selectionArgs[0]);
+ } catch (RemoteException e) {
+ }
+ }
+ return new MySuggestionCursor(c, null, selectionArgs[0]);
+ }
}
String[] projection = null;