diff options
author | Jeff Hamilton <jham@android.com> | 2010-08-17 11:13:53 -0500 |
---|---|---|
committer | Jeff Hamilton <jham@android.com> | 2010-08-18 14:06:12 -0500 |
commit | 8ce956c6076a89aae85856f35b94bad7fc8fa1f1 (patch) | |
tree | ca6d690359a55fc4a7489f20c67a5168389c8dc9 /src/com | |
parent | 8e4fbf1b26c2cc05a56ba2d4e7d1eda7d1574e91 (diff) | |
download | packages_apps_Browser-8ce956c6076a89aae85856f35b94bad7fc8fa1f1.zip packages_apps_Browser-8ce956c6076a89aae85856f35b94bad7fc8fa1f1.tar.gz packages_apps_Browser-8ce956c6076a89aae85856f35b94bad7fc8fa1f1.tar.bz2 |
Switch the history management over to the new provider.
Also fix up a bunch of bugs causing things like
thumbnails to not be stored properly.
Change-Id: I5758ee108734d9b50e741822dcbe86b7cc834e8e
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/browser/Bookmarks.java | 69 | ||||
-rw-r--r-- | src/com/android/browser/BrowserActivity.java | 7 | ||||
-rw-r--r-- | src/com/android/browser/BrowserBookmarksPage.java | 9 | ||||
-rw-r--r-- | src/com/android/browser/BrowserDownloadAdapter.java | 7 | ||||
-rw-r--r-- | src/com/android/browser/BrowserDownloadPage.java | 13 | ||||
-rw-r--r-- | src/com/android/browser/BrowserHistoryPage.java | 210 | ||||
-rw-r--r-- | src/com/android/browser/DateSortedExpandableListAdapter.java | 117 | ||||
-rw-r--r-- | src/com/android/browser/DownloadTouchIcon.java | 24 | ||||
-rw-r--r-- | src/com/android/browser/Tab.java | 38 | ||||
-rw-r--r-- | src/com/android/browser/provider/BrowserProvider2.java | 46 |
10 files changed, 278 insertions, 262 deletions
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java index 62ed7e3..3ead203 100644 --- a/src/com/android/browser/Bookmarks.java +++ b/src/com/android/browser/Bookmarks.java @@ -24,8 +24,6 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.AsyncTask; -import android.provider.Browser; -import android.provider.Browser.BookmarkColumns; import android.provider.BrowserContract; import android.util.Log; import android.webkit.WebIconDatabase; @@ -103,40 +101,26 @@ import java.io.ByteArrayOutputStream; ContentResolver cr, String url, String title) { Cursor cursor = null; try { - cursor = cr.query( - Browser.BOOKMARKS_URI, - Browser.HISTORY_PROJECTION, - "url = ? AND title = ?", + cursor = cr.query(BrowserContract.Bookmarks.CONTENT_URI, + new String[] { BrowserContract.Bookmarks._ID }, + BrowserContract.Bookmarks.URL + " = ? AND " + + BrowserContract.Bookmarks.TITLE + " = ?", new String[] { url, title }, null); - boolean first = cursor.moveToFirst(); + // Should be in the database no matter what - if (!first) { + if (!cursor.moveToFirst()) { throw new AssertionError("URL is not in the database! " + url + " " + title); } + // Remove from bookmarks WebIconDatabase.getInstance().releaseIconForPageUrl(url); - Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI, - cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX)); - int numVisits = cursor.getInt( - Browser.HISTORY_PROJECTION_VISITS_INDEX); - if (0 == numVisits) { - cr.delete(uri, null, null); - } else { - // It is no longer a bookmark, but it is still a visited - // site. - ContentValues values = new ContentValues(); - values.put(Browser.BookmarkColumns.BOOKMARK, 0); - try { - cr.update(uri, values, null, null); - } catch (IllegalStateException e) { - Log.e("removeFromBookmarks", "no database!"); - } - } + Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, + cursor.getLong(0)); + cr.delete(uri, null, null); if (context != null) { - Toast.makeText(context, R.string.removed_from_bookmarks, - Toast.LENGTH_LONG).show(); + Toast.makeText(context, R.string.removed_from_bookmarks, Toast.LENGTH_LONG).show(); } } catch (IllegalStateException e) { Log.e(LOGTAG, "removeFromBookmarks", e); @@ -168,8 +152,15 @@ import java.io.ByteArrayOutputStream; return false; } + static final String QUERY_BOOKMARKS_WHERE = + BrowserContract.Bookmarks.IS_FOLDER + " == 0 AND (" + + BrowserContract.Bookmarks.URL + " == ? OR " + + BrowserContract.Bookmarks.URL + " == ? OR " + + BrowserContract.Bookmarks.URL + " LIKE ? || '%' OR " + + BrowserContract.Bookmarks.URL + " LIKE ? || '%')"; + /* package */ static Cursor queryBookmarksForUrl(ContentResolver cr, - String originalUrl, String url, boolean onlyBookmarks) { + String originalUrl, String url) { if (cr == null || url == null) { return null; } @@ -192,18 +183,10 @@ import java.io.ByteArrayOutputStream; // http://www.google.com/m, search for // http://www.google.com/m?some_query) final String[] selArgs = new String[] { - originalUrlNoQuery, urlNoQuery, originalUrl, url }; - String where = BookmarkColumns.URL + " == ? OR " - + BookmarkColumns.URL + " == ? OR " - + BookmarkColumns.URL + " LIKE ? || '%' OR " - + BookmarkColumns.URL + " LIKE ? || '%'"; - if (onlyBookmarks) { - where = "(" + where + ") AND " + BookmarkColumns.BOOKMARK + " == 1"; - } - final String[] projection = - new String[] { Browser.BookmarkColumns._ID }; - return cr.query(Browser.BOOKMARKS_URI, projection, where, selArgs, - null); + originalUrlNoQuery, urlNoQuery, originalUrl, url }; + final String[] projection = new String[] { BrowserContract.Bookmarks._ID }; + return cr.query(BrowserContract.Bookmarks.CONTENT_URI, projection, QUERY_BOOKMARKS_WHERE, + selArgs, null); } // Strip the query from the given url. @@ -233,7 +216,7 @@ import java.io.ByteArrayOutputStream; @Override protected Void doInBackground(Void... unused) { final Cursor c = - Bookmarks.queryBookmarksForUrl(cr, originalUrl, url, true); + Bookmarks.queryBookmarksForUrl(cr, originalUrl, url); if (c == null) { return null; } @@ -242,11 +225,11 @@ import java.io.ByteArrayOutputStream; final ByteArrayOutputStream os = new ByteArrayOutputStream(); favicon.compress(Bitmap.CompressFormat.PNG, 100, os); - values.put(Browser.BookmarkColumns.FAVICON, + values.put(BrowserContract.Bookmarks.FAVICON, os.toByteArray()); do { cr.update(ContentUris.withAppendedId( - Browser.BOOKMARKS_URI, c.getInt(0)), + BrowserContract.Bookmarks.CONTENT_URI, c.getLong(0)), values, null, null); } while (c.moveToNext()); } diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index 36be5e4..99bf017 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -62,6 +62,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.SystemClock; import android.provider.Browser; +import android.provider.BrowserContract; import android.provider.ContactsContract; import android.provider.ContactsContract.Intents.Insert; import android.provider.Downloads; @@ -2506,18 +2507,18 @@ public class BrowserActivity extends Activity Cursor c = null; try { c = Bookmarks.queryBookmarksForUrl( - cr, originalUrl, url, true); + cr, originalUrl, url); if (c != null) { if (c.moveToFirst()) { ContentValues values = new ContentValues(); final ByteArrayOutputStream os = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, os); - values.put(Browser.BookmarkColumns.THUMBNAIL, + values.put(BrowserContract.Bookmarks.THUMBNAIL, os.toByteArray()); do { cr.update(ContentUris.withAppendedId( - Browser.BOOKMARKS_URI, c.getInt(0)), + BrowserContract.Bookmarks.CONTENT_URI, c.getLong(0)), values, null, null); } while (c.moveToNext()); } diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java index 6a51b98..a01f6fa 100644 --- a/src/com/android/browser/BrowserBookmarksPage.java +++ b/src/com/android/browser/BrowserBookmarksPage.java @@ -386,7 +386,7 @@ public class BrowserBookmarksPage extends Activity implements View.OnCreateConte public void updateRow(Bundle map) { // Find the record - int id = map.getInt("id"); + long id = map.getLong("id"); int position = -1; Cursor cursor = mAdapter.getCursor(); for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { @@ -411,12 +411,13 @@ public class BrowserBookmarksPage extends Activity implements View.OnCreateConte } if (map.getBoolean("invalidateThumbnail") == true) { - values.put(Browser.BookmarkColumns.THUMBNAIL, new byte[0]); + values.putNull(Browser.BookmarkColumns.THUMBNAIL); } if (values.size() > 0) { - getContentResolver().update(Browser.BOOKMARKS_URI, values, - "_id = ?", new String[] { Integer.toString(id) }); + getContentResolver().update( + ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), + values, null, null); } } diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java index f22c9fe..6f498b6 100644 --- a/src/com/android/browser/BrowserDownloadAdapter.java +++ b/src/com/android/browser/BrowserDownloadAdapter.java @@ -26,7 +26,6 @@ import android.database.Cursor; import android.drm.mobile1.DrmRawContent; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Handler; import android.provider.Downloads; import android.text.format.Formatter; import android.view.LayoutInflater; @@ -56,9 +55,9 @@ public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter { private int mMimetypeColumnId; private int mDateColumnId; - public BrowserDownloadAdapter(Context context, Cursor c, int index, - Handler handler) { - super(context, c, index, handler); + public BrowserDownloadAdapter(Context context, Cursor c, int index) { + super(context, index); + changeCursor(c); mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE); mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION); mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS); diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java index bbf1191..a897f99 100644 --- a/src/com/android/browser/BrowserDownloadPage.java +++ b/src/com/android/browser/BrowserDownloadPage.java @@ -18,13 +18,10 @@ package com.android.browser; import android.app.AlertDialog; import android.app.ExpandableListActivity; -import android.content.ActivityNotFoundException; +import android.content.ContentUris; import android.content.ContentValues; import android.content.DialogInterface; import android.content.Intent; -import android.content.ContentUris; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; @@ -34,17 +31,13 @@ import android.provider.Downloads; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; -import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuItem; import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.widget.AdapterView; import android.widget.ExpandableListView; import java.io.File; -import java.util.List; /** * View showing the user's current browser downloads @@ -100,7 +93,7 @@ public class BrowserDownloadPage extends ExpandableListActivity { // Create a list "controller" for the data mDownloadAdapter = new BrowserDownloadAdapter(this, mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow( - Downloads.Impl.COLUMN_LAST_MODIFICATION), mHandler); + Downloads.Impl.COLUMN_LAST_MODIFICATION)); setListAdapter(mDownloadAdapter); mListView.setOnCreateContextMenuListener(this); diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java index 5298b9a..8116b97 100644 --- a/src/com/android/browser/BrowserHistoryPage.java +++ b/src/com/android/browser/BrowserHistoryPage.java @@ -18,33 +18,30 @@ package com.android.browser; import android.app.Activity; import android.app.ExpandableListActivity; +import android.app.LoaderManager.LoaderCallbacks; import android.content.ClipboardManager; import android.content.Context; +import android.content.CursorLoader; import android.content.Intent; +import android.content.Loader; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.os.AsyncTask; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.ServiceManager; import android.provider.Browser; import android.provider.BrowserContract.History; -import android.util.Log; import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.ContextMenu.ContextMenuInfo; import android.view.ViewStub; import android.webkit.WebIconDatabase.IconListener; -import android.widget.ExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.Toast; @@ -53,21 +50,41 @@ import android.widget.Toast; * Activity for displaying the browser's history, divided into * days of viewing. */ -public class BrowserHistoryPage extends ExpandableListActivity { - private HistoryAdapter mAdapter; - private boolean mDisableNewWindow; - private HistoryItem mContextHeader; +public class BrowserHistoryPage extends ExpandableListActivity + implements LoaderCallbacks<Cursor> { + + static final int LOADER_HISTORY = 1; - private final static String LOGTAG = "browser"; + HistoryAdapter mAdapter; + boolean mDisableNewWindow; + HistoryItem mContextHeader; // Implementation of WebIconDatabase.IconListener - private class IconReceiver implements IconListener { + class IconReceiver implements IconListener { + @Override public void onReceivedIcon(String url, Bitmap icon) { - setListAdapter(mAdapter); + mAdapter.notifyDataSetChanged(); } } + // Instance of IconReceiver - private final IconReceiver mIconReceiver = new IconReceiver(); + final IconReceiver mIconReceiver = new IconReceiver(); + + static interface HistoryQuery { + static final String[] PROJECTION = new String[] { + History._ID, // 0 + History.DATE_LAST_VISITED, // 1 + History.TITLE, // 2 + History.URL, // 3 + History.FAVICON, // 4 + }; + + static final int INDEX_ID = 0; + static final int INDEX_DATE_LAST_VISITED = 1; + static final int INDEX_TITE = 2; + static final int INDEX_URL = 3; + static final int INDEX_FAVICON = 4; + } /** * Report back to the calling activity to load a site. @@ -90,81 +107,73 @@ public class BrowserHistoryPage extends ExpandableListActivity { cm.setText(text); } - private static final int ADAPTER_CREATED = 1000; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case ADAPTER_CREATED: - mAdapter = (HistoryAdapter) msg.obj; - setListAdapter(mAdapter); - final ExpandableListView list = getExpandableListView(); - // Add an empty view late, so it does not claim an empty - // history before the adapter is present - View v = new ViewStub(BrowserHistoryPage.this, - R.layout.empty_history); - addContentView(v, new LayoutParams( - LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - list.setEmptyView(v); - list.setOnCreateContextMenuListener( - BrowserHistoryPage.this); - // Do not post the runnable if there is nothing in the list. - if (list.getExpandableListAdapter().getGroupCount() > 0) { - list.post(new Runnable() { - public void run() { - // In case the history gets cleared before this - // event happens - if (list.getExpandableListAdapter() - .getGroupCount() > 0) { - list.expandGroup(0); - } - } - }); - } - break; + @Override + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + switch (id) { + case LOADER_HISTORY: { + CursorLoader loader = new CursorLoader(this, History.CONTENT_URI, + HistoryQuery.PROJECTION, null, null, null); + return loader; + } + + default: { + throw new IllegalArgumentException(); } } - }; + } @Override + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + switch (loader.getId()) { + case LOADER_HISTORY: { + mAdapter.changeCursor(data); + + // Add an empty view late, so it does not claim an empty + // history before the adapter is present + final ExpandableListView list = getExpandableListView(); + View v = new ViewStub(this, R.layout.empty_history); + addContentView(v, new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT)); + list.setEmptyView(v); + + // Do not post the runnable if there is nothing in the list. + if (list.getExpandableListAdapter().getGroupCount() > 0) { + list.post(new Runnable() { + @Override + public void run() { + // In case the history gets cleared before this + // event happens + if (list.getExpandableListAdapter() + .getGroupCount() > 0) { + list.expandGroup(0); + } + } + }); + } + break; + } + + default: { + throw new IllegalArgumentException(); + } + } + } + + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); setTitle(R.string.browser_history); - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... unused) { - final String whereClause = Browser.BookmarkColumns.VISITS - + " > 0" - // In AddBookmarkPage, where we save new bookmarks, we - // add three visits to newly created bookmarks, so that - // bookmarks that have not been visited will show up in - // the most visited, and higher in the goto search box. - // However, this puts the site in the history, unless - // we ignore sites with a DATE of 0, which the next - // line does. - + " AND " + Browser.BookmarkColumns.DATE + " > 0"; - final String orderBy = Browser.BookmarkColumns.DATE + " DESC"; - - Cursor cursor = managedQuery( - Browser.BOOKMARKS_URI, - Browser.HISTORY_PROJECTION, - whereClause, null, orderBy); - - HistoryAdapter adapter = new HistoryAdapter( - BrowserHistoryPage.this, cursor, - Browser.HISTORY_PROJECTION_DATE_INDEX, mHandler); - mHandler.obtainMessage(ADAPTER_CREATED, adapter).sendToTarget(); - return null; - } - }.execute(); - mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window", - false); + getExpandableListView().setOnCreateContextMenuListener(this); + + mAdapter = new HistoryAdapter(this); + setListAdapter(mAdapter); + + mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window", false); // Register to receive icons in case they haven't all been loaded. - CombinedBookmarkHistoryActivity.getIconListenerSet() - .addListener(mIconReceiver); + CombinedBookmarkHistoryActivity.getIconListenerSet().addListener(mIconReceiver); Activity parent = getParent(); if (null == parent @@ -172,14 +181,17 @@ public class BrowserHistoryPage extends ExpandableListActivity { throw new AssertionError("history page can only be viewed as a tab" + "in CombinedBookmarkHistoryActivity"); } + // initialize the result to canceled, so that if the user just presses // back then it will have the correct result setResultToParent(RESULT_CANCELED, null); + + // Start the loader + getLoaderManager().initLoader(LOADER_HISTORY, null, this); } @Override protected void onDestroy() { - mHandler.removeCallbacksAndMessages(null); super.onDestroy(); CombinedBookmarkHistoryActivity.getIconListenerSet() .removeListener(mIconReceiver); @@ -195,7 +207,8 @@ public class BrowserHistoryPage extends ExpandableListActivity { @Override public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.clear_history_menu_id).setVisible(Browser.canClearHistory(this.getContentResolver())); + menu.findItem(R.id.clear_history_menu_id).setVisible( + Browser.canClearHistory(this.getContentResolver())); return true; } @@ -208,7 +221,6 @@ public class BrowserHistoryPage extends ExpandableListActivity { // CombinedBookmarkHistoryActivity ((CombinedBookmarkHistoryActivity) getParent()) .removeParentChildRelationShips(); - if (mAdapter != null) mAdapter.refreshData(); return true; default: @@ -292,7 +304,6 @@ public class BrowserHistoryPage extends ExpandableListActivity { return true; case R.id.delete_context_menu_id: Browser.deleteFromHistory(getContentResolver(), url); - if (mAdapter != null) mAdapter.refreshData(); return true; case R.id.homepage_context_menu_id: BrowserSettings.getInstance().setHomePage(this, url); @@ -304,12 +315,12 @@ public class BrowserHistoryPage extends ExpandableListActivity { } return super.onContextItemSelected(item); } - + @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { - if (v instanceof HistoryItem) { - loadUrl(((HistoryItem) v).getUrl(), false); + if (v instanceof BookmarkItem) { + loadUrl(((BookmarkItem) v).getUrl(), false); return true; } return false; @@ -324,17 +335,16 @@ public class BrowserHistoryPage extends ExpandableListActivity { } private class HistoryAdapter extends DateSortedExpandableListAdapter { - HistoryAdapter(Context context, Cursor cursor, int index, - Handler handler) { - super(context, cursor, index, handler); - + HistoryAdapter(Context context) { + super(context, HistoryQuery.INDEX_DATE_LAST_VISITED); } + @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { - HistoryItem item; - if (null == convertView || !(convertView instanceof HistoryItem)) { - item = new HistoryItem(BrowserHistoryPage.this); + BookmarkItem item; + if (null == convertView || !(convertView instanceof BookmarkItem)) { + item = new BookmarkItem(BrowserHistoryPage.this); // Add padding on the left so it will be indented from the // arrows on the group views. item.setPadding(item.getPaddingLeft() + 10, @@ -342,16 +352,18 @@ public class BrowserHistoryPage extends ExpandableListActivity { item.getPaddingRight(), item.getPaddingBottom()); } else { - item = (HistoryItem) convertView; + item = (BookmarkItem) convertView; } + // Bail early if the Cursor is closed. if (!moveCursorToChildPosition(groupPosition, childPosition)) { return item; } - item.setName(getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)); - String url = getString(Browser.HISTORY_PROJECTION_URL_INDEX); + + item.setName(getString(HistoryQuery.INDEX_TITE)); + String url = getString(HistoryQuery.INDEX_URL); item.setUrl(url); - byte[] data = getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX); + byte[] data = getBlob(HistoryQuery.INDEX_FAVICON); if (data != null) { item.setFavicon(BitmapFactory.decodeByteArray(data, 0, data.length)); @@ -359,8 +371,6 @@ public class BrowserHistoryPage extends ExpandableListActivity { item.setFavicon(CombinedBookmarkHistoryActivity .getIconListenerSet().getFavicon(url)); } - item.setIsBookmark(1 == - getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX)); return item; } } diff --git a/src/com/android/browser/DateSortedExpandableListAdapter.java b/src/com/android/browser/DateSortedExpandableListAdapter.java index f8261d8..a48efe6 100644 --- a/src/com/android/browser/DateSortedExpandableListAdapter.java +++ b/src/com/android/browser/DateSortedExpandableListAdapter.java @@ -17,65 +17,55 @@ package com.android.browser; import android.content.Context; -import android.database.ContentObserver; import android.database.Cursor; import android.database.DataSetObserver; -import android.os.Handler; -import android.provider.BaseColumns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.DateSorter; -import android.widget.ExpandableListAdapter; +import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.TextView; -import java.util.Vector; - /** * ExpandableListAdapter which separates data into categories based on date. * Used for History and Downloads. */ -public class DateSortedExpandableListAdapter implements ExpandableListAdapter { +public class DateSortedExpandableListAdapter extends BaseExpandableListAdapter { // Array for each of our bins. Each entry represents how many items are // in that bin. private int mItemMap[]; // This is our GroupCount. We will have at most DateSorter.DAY_COUNT // bins, less if the user has no items in one or more bins. private int mNumberOfBins; - private Vector<DataSetObserver> mObservers; private Cursor mCursor; private DateSorter mDateSorter; private int mDateIndex; private int mIdIndex; private Context mContext; - private class ChangeObserver extends ContentObserver { - public ChangeObserver(Handler handler) { - super(handler); - } + boolean mDataValid; + DataSetObserver mDataSetObserver = new DataSetObserver() { @Override - public boolean deliverSelfNotifications() { - return true; + public void onChanged() { + mDataValid = true; + notifyDataSetChanged(); } @Override - public void onChange(boolean selfChange) { - refreshData(); + public void onInvalidated() { + mDataValid = false; + notifyDataSetInvalidated(); } - } - - public DateSortedExpandableListAdapter(Context context, Cursor cursor, - int dateIndex, Handler handler) { + }; + + public DateSortedExpandableListAdapter(Context context, int dateIndex) { mContext = context; mDateSorter = new DateSorter(context); - mObservers = new Vector<DataSetObserver>(); - mCursor = cursor; - mIdIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID); - cursor.registerContentObserver(new ChangeObserver(handler)); mDateIndex = dateIndex; - buildMap(); + mDataValid = false; + mIdIndex = -1; } /** @@ -122,6 +112,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * @return corresponding byte array from the Cursor. */ /* package */ byte[] getBlob(int cursorIndex) { + if (!mDataValid) return null; return mCursor.getBlob(cursorIndex); } @@ -138,6 +129,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * @return corresponding integer from the Cursor. */ /* package */ int getInt(int cursorIndex) { + if (!mDataValid) return 0; return mCursor.getInt(cursorIndex); } @@ -146,6 +138,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * already been moved to the correct position. */ /* package */ long getLong(int cursorIndex) { + if (!mDataValid) return 0; return mCursor.getLong(cursorIndex); } @@ -158,6 +151,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * @return corresponding String from the Cursor. */ /* package */ String getString(int cursorIndex) { + if (!mDataValid) return null; return mCursor.getString(cursorIndex); } @@ -166,6 +160,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * @param childId ID of the child view in question. * @return int Group position of the containing group. /* package */ int groupFromChildId(long childId) { + if (!mDataValid) return -1; int group = -1; for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) { @@ -173,11 +168,15 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { int bin = mDateSorter.getIndex(getLong(mDateIndex)); // bin is the same as the group if the number of bins is the // same as DateSorter - if (mDateSorter.DAY_COUNT == mNumberOfBins) return bin; + if (DateSorter.DAY_COUNT == mNumberOfBins) { + return bin; + } // There are some empty bins. Find the corresponding group. group = 0; for (int i = 0; i < bin; i++) { - if (mItemMap[i] != 0) group++; + if (mItemMap[i] != 0) { + group++; + } } break; } @@ -193,6 +192,7 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { * @return The corresponding bin that holds that group. */ private int groupPositionToBin(int groupPosition) { + if (!mDataValid) return -1; if (groupPosition < 0 || groupPosition >= DateSorter.DAY_COUNT) { throw new AssertionError("group position out of range"); } @@ -241,7 +241,9 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { */ /* package */ boolean moveCursorToChildPosition(int groupPosition, int childPosition) { - if (mCursor.isClosed()) return false; + if (!mDataValid || mCursor.isClosed()) { + return false; + } groupPosition = groupPositionToBin(groupPosition); int index = childPosition; for (int i = 0; i < groupPosition; i++) { @@ -250,19 +252,34 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { return mCursor.moveToPosition(index); } - /* package */ void refreshData() { - if (mCursor.isClosed()) { + public void changeCursor(Cursor cursor) { + if (cursor == mCursor) { return; } - mCursor.requery(); - buildMap(); - for (DataSetObserver o : mObservers) { - o.onChanged(); + if (mCursor != null) { + mCursor.unregisterDataSetObserver(mDataSetObserver); + mCursor.close(); + } + mCursor = cursor; + if (cursor != null) { + cursor.registerDataSetObserver(mDataSetObserver); + mIdIndex = cursor.getColumnIndexOrThrow("_id"); + mDataValid = true; + buildMap(); + // notify the observers about the new cursor + notifyDataSetChanged(); + } else { + mIdIndex = -1; + mDataValid = false; + // notify the observers about the lack of a data set + notifyDataSetInvalidated(); } } + @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + if (!mDataValid) throw new IllegalStateException("Data is not valid"); TextView item; if (null == convertView || !(convertView instanceof TextView)) { LayoutInflater factory = LayoutInflater.from(mContext); @@ -275,73 +292,87 @@ public class DateSortedExpandableListAdapter implements ExpandableListAdapter { return item; } + @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + if (!mDataValid) throw new IllegalStateException("Data is not valid"); return null; } + @Override public boolean areAllItemsEnabled() { return true; } + @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } + @Override public int getGroupCount() { + if (!mDataValid) return 0; return mNumberOfBins; } + @Override public int getChildrenCount(int groupPosition) { + if (!mDataValid) return 0; return mItemMap[groupPositionToBin(groupPosition)]; } + @Override public Object getGroup(int groupPosition) { return null; } + @Override public Object getChild(int groupPosition, int childPosition) { return null; } + @Override public long getGroupId(int groupPosition) { + if (!mDataValid) return 0; return groupPosition; } + @Override public long getChildId(int groupPosition, int childPosition) { + if (!mDataValid) return 0; if (moveCursorToChildPosition(groupPosition, childPosition)) { return getLong(mIdIndex); } return 0; } + @Override public boolean hasStableIds() { return true; } - public void registerDataSetObserver(DataSetObserver observer) { - mObservers.add(observer); - } - - public void unregisterDataSetObserver(DataSetObserver observer) { - mObservers.remove(observer); - } - + @Override public void onGroupExpanded(int groupPosition) { } + @Override public void onGroupCollapsed(int groupPosition) { } + @Override public long getCombinedChildId(long groupId, long childId) { + if (!mDataValid) return 0; return childId; } + @Override public long getCombinedGroupId(long groupId) { + if (!mDataValid) return 0; return groupId; } + @Override public boolean isEmpty() { - return mCursor.isClosed() || mCursor.getCount() == 0; + return !mDataValid || mCursor == null || mCursor.isClosed() || mCursor.getCount() == 0; } } diff --git a/src/com/android/browser/DownloadTouchIcon.java b/src/com/android/browser/DownloadTouchIcon.java index 2816f58..1442683 100644 --- a/src/com/android/browser/DownloadTouchIcon.java +++ b/src/com/android/browser/DownloadTouchIcon.java @@ -16,6 +16,13 @@ package com.android.browser; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.HttpClientParams; +import org.apache.http.conn.params.ConnRouteParams; + import android.app.Activity; import android.content.ContentResolver; import android.content.ContentUris; @@ -23,21 +30,14 @@ import android.content.ContentValues; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.net.http.AndroidHttpClient; import android.net.Proxy; +import android.net.http.AndroidHttpClient; import android.os.AsyncTask; import android.os.Bundle; import android.os.Message; -import android.provider.Browser; +import android.provider.BrowserContract; import android.webkit.WebView; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.params.HttpClientParams; -import org.apache.http.conn.params.ConnRouteParams; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -102,7 +102,7 @@ class DownloadTouchIcon extends AsyncTask<String, Void, Void> { public Void doInBackground(String... values) { if (mContentResolver != null) { mCursor = Bookmarks.queryBookmarksForUrl(mContentResolver, - mOriginalUrl, mUrl, true); + mOriginalUrl, mUrl); } boolean inBookmarksDatabase = mCursor != null && mCursor.getCount() > 0; @@ -180,13 +180,13 @@ class DownloadTouchIcon extends AsyncTask<String, Void, Void> { final ByteArrayOutputStream os = new ByteArrayOutputStream(); icon.compress(Bitmap.CompressFormat.PNG, 100, os); ContentValues values = new ContentValues(); - values.put(Browser.BookmarkColumns.TOUCH_ICON, + values.put(BrowserContract.Bookmarks.TOUCH_ICON, os.toByteArray()); if (mCursor.moveToFirst()) { do { mContentResolver.update(ContentUris.withAppendedId( - Browser.BOOKMARKS_URI, mCursor.getInt(0)), + BrowserContract.Bookmarks.CONTENT_URI, mCursor.getLong(0)), values, null, null); } while (mCursor.moveToNext()); } diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java index 9abf32f..e7309a6 100644 --- a/src/com/android/browser/Tab.java +++ b/src/com/android/browser/Tab.java @@ -16,13 +16,16 @@ package com.android.browser; +import com.android.browser.TabControl.TabChangeListener; +import com.android.common.speech.LoggingEvents; + import android.app.AlertDialog; import android.app.SearchManager; import android.content.ContentResolver; import android.content.ContentValues; import android.content.DialogInterface; -import android.content.Intent; import android.content.DialogInterface.OnCancelListener; +import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; @@ -34,14 +37,15 @@ import android.os.Bundle; import android.os.Message; import android.os.SystemClock; import android.provider.Browser; +import android.provider.BrowserContract.History; import android.speech.RecognizerResultsIntent; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewStub; -import android.view.View.OnClickListener; import android.webkit.ConsoleMessage; import android.webkit.CookieSyncManager; import android.webkit.DownloadListener; @@ -63,10 +67,6 @@ import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; -import com.android.browser.TabControl.TabChangeListener; -import com.android.common.speech.LoggingEvents; - -import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -992,26 +992,12 @@ class Tab { .replace("_", "\\_"); Cursor c = null; try { - final ContentResolver cr - = mActivity.getContentResolver(); - url = "%" + url; - String [] selArgs = new String[] { url }; - String where = Browser.BookmarkColumns.URL - + " LIKE ? ESCAPE '\\' AND " - + Browser.BookmarkColumns.BOOKMARK + " = 0"; - c = cr.query(Browser.BOOKMARKS_URI, new String[] - { Browser.BookmarkColumns._ID }, where, selArgs, - null); - if (c.moveToFirst()) { - // Current implementation of database only has one - // entry per url. - ContentValues map = new ContentValues(); - map.put(Browser.BookmarkColumns.TITLE, title); - String[] projection = new String[] - { Integer.valueOf(c.getInt(0)).toString() }; - cr.update(Browser.BOOKMARKS_URI, map, "_id = ?", - projection); - } + final ContentResolver cr = mActivity.getContentResolver(); + String selection = History.URL + " LIKE ? ESCAPE '\\'"; + String [] selectionArgs = new String[] { "%" + url }; + ContentValues values = new ContentValues(); + values.put(History.TITLE, title); + cr.update(History.CONTENT_URI, values, selection, selectionArgs); } catch (IllegalStateException e) { Log.e(LOGTAG, "Tab onReceived title", e); } catch (SQLiteException ex) { diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java index 0aae911..ab24c03 100644 --- a/src/com/android/browser/provider/BrowserProvider2.java +++ b/src/com/android/browser/provider/BrowserProvider2.java @@ -51,9 +51,8 @@ public class BrowserProvider2 extends SQLiteContentProvider { static final String TABLE_SEARCHES = "searches"; static final String TABLE_SYNC_STATE = "syncstate"; - static final String HISTORY_JOIN_BOOKMARKS = - "history LEFT OUTER JOIN bookmarks ON (history.url = bookmarks.url)"; - + static final String DEFAULT_HISTORY_SORT = History.DATE_LAST_VISITED + " DESC"; + static final int BOOKMARKS = 1000; static final int BOOKMARKS_ID = 1001; static final int BOOKMARKS_FOLDER = 1002; @@ -96,17 +95,13 @@ public class BrowserProvider2 extends SQLiteContentProvider { matcher.addURI(BrowserContract.AUTHORITY, "syncstate", SYNCSTATE); matcher.addURI(BrowserContract.AUTHORITY, "syncstate/#", SYNCSTATE_ID); - // Common BookmarkColumns - HashMap<String, String> bookmarksColumns = new HashMap(); - bookmarksColumns.put(Bookmarks.TITLE, Bookmarks.TITLE); - bookmarksColumns.put(Bookmarks.URL, Bookmarks.URL); - bookmarksColumns.put(Bookmarks.FAVICON, Bookmarks.FAVICON); - bookmarksColumns.put(Bookmarks.THUMBNAIL, Bookmarks.THUMBNAIL); - bookmarksColumns.put(Bookmarks.TOUCH_ICON, Bookmarks.TOUCH_ICON); - // Bookmarks HashMap<String, String> map = BOOKMARKS_PROJECTION_MAP; - map.putAll(bookmarksColumns); + map.put(Bookmarks.TITLE, Bookmarks.TITLE); + map.put(Bookmarks.URL, Bookmarks.URL); + map.put(Bookmarks.FAVICON, Bookmarks.FAVICON); + map.put(Bookmarks.THUMBNAIL, Bookmarks.THUMBNAIL); + map.put(Bookmarks.TOUCH_ICON, Bookmarks.TOUCH_ICON); map.put(Bookmarks._ID, TABLE_BOOKMARKS + "._id AS _id"); map.put(Bookmarks.IS_FOLDER, Bookmarks.IS_FOLDER); map.put(Bookmarks.PARENT, Bookmarks.PARENT); @@ -130,11 +125,16 @@ public class BrowserProvider2 extends SQLiteContentProvider { // History map = HISTORY_PROJECTION_MAP; - map.putAll(bookmarksColumns); - map.put(History._ID, TABLE_HISTORY + "._id AS _id"); + map.put(History._ID, qualifyColumn(TABLE_HISTORY, History._ID)); + map.put(History.TITLE, Bookmarks.TITLE); + map.put(History.URL, Bookmarks.URL); + map.put(History.FAVICON, Bookmarks.FAVICON); + map.put(History.THUMBNAIL, Bookmarks.THUMBNAIL); + map.put(History.TOUCH_ICON, Bookmarks.TOUCH_ICON); map.put(History.DATE_CREATED, History.DATE_CREATED); map.put(History.DATE_LAST_VISITED, History.DATE_LAST_VISITED); map.put(History.VISITS, History.VISITS); + map.put(History.USER_ENTERED, History.USER_ENTERED); // Sync state map = SYNC_STATE_PROJECTION_MAP; @@ -144,12 +144,16 @@ public class BrowserProvider2 extends SQLiteContentProvider { map.put(SyncState.DATA, SyncState.DATA); } + static final String qualifyColumn(String table, String column) { + return table + "." + column + " AS " + column; + } + DatabaseHelper mOpenHelper; SyncStateContentProviderHelper mSyncHelper = new SyncStateContentProviderHelper(); final class DatabaseHelper extends SQLiteOpenHelper { static final String DATABASE_NAME = "browser2.db"; - static final int DATABASE_VERSION = 11; + static final int DATABASE_VERSION = 15; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @@ -186,10 +190,15 @@ public class BrowserProvider2 extends SQLiteContentProvider { db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" + History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + History.TITLE + " TEXT," + History.URL + " TEXT NOT NULL," + + History.FAVICON + " BLOB," + + History.THUMBNAIL + " BLOB," + + History.TOUCH_ICON + " BLOB," + History.DATE_CREATED + " INTEGER," + History.DATE_LAST_VISITED + " INTEGER," + - History.VISITS + " INTEGER NOT NULL DEFAULT 0" + + History.VISITS + " INTEGER NOT NULL DEFAULT 0," + + History.USER_ENTERED + " INTEGER" + ");"); db.execSQL("CREATE TABLE " + TABLE_SEARCHES + " (" + @@ -482,8 +491,11 @@ public class BrowserProvider2 extends SQLiteContentProvider { // fall through } case HISTORY: { + if (sortOrder == null) { + sortOrder = DEFAULT_HISTORY_SORT; + } qb.setProjectionMap(HISTORY_PROJECTION_MAP); - qb.setTables(HISTORY_JOIN_BOOKMARKS); + qb.setTables(TABLE_HISTORY); break; } |