diff options
20 files changed, 312 insertions, 87 deletions
diff --git a/res/layout/suggestion_item.xml b/res/layout/suggestion_item.xml index 2bd5466..2def735 100644 --- a/res/layout/suggestion_item.xml +++ b/res/layout/suggestion_item.xml @@ -50,7 +50,7 @@ <TextView android:id="@android:id/text1" style="@style/SuggestionLineMedium" - android:singleLine="true" + android:maxLines="1" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView diff --git a/res/menu/title_context.xml b/res/menu/snapshot_go_live.xml index a60f102..aa6b38e 100644 --- a/res/menu/title_context.xml +++ b/res/menu/snapshot_go_live.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2009 The Android Open Source Project +<!-- Copyright (C) 2011 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,12 +15,8 @@ --> <menu xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- These are for the context menu for the title bar. Note that we need a - different item from share_page_menu_id, which looks at the top - window (possibly a subwindow), because this should be the main - window.--> - <item android:id="@+id/title_bar_share_page_url" - android:title="@string/share_page"/> - <item android:id="@+id/title_bar_copy_page_url" - android:title="@string/copy_page_url"/> + <item + android:id="@+id/snapshot_go_live" + android:title="@string/snapshot_go_live" /> </menu> + diff --git a/res/values/strings.xml b/res/values/strings.xml index f4086ea..41b9831 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -573,6 +573,8 @@ <!-- Do not tranlsate. Development option --> <string name="pref_development_hardware_accel" translatable="false">Enable OpenGL Rendering</string> <!-- Do not tranlsate. Development option --> + <string name="pref_development_hardware_accel_skia" translatable="false">Enable HW Accelerated Skia</string> + <!-- Do not tranlsate. Development option --> <string name="pref_development_visual_indicator" translatable="false">Enable Visual Indicator</string> <!-- Do not tranlsate. Development option --> <string name="js_engine_flags" translatable="false">Set JS flags</string> @@ -1016,4 +1018,6 @@ <string name="empty_snapshots_folder">There are no saved pages.</string> <!-- Menu option to delete the currently selected saved page [CHAR LIMIT=50] --> <string name="remove_snapshot">Delete saved page</string> + <!-- Popup menu option to load the live version of a saved page [CHAR LIMIT=20] --> + <string name="snapshot_go_live">Go live</string> </resources> diff --git a/res/xml/debug_preferences.xml b/res/xml/debug_preferences.xml index 1fc4f4c..2d15ab2 100644 --- a/res/xml/debug_preferences.xml +++ b/res/xml/debug_preferences.xml @@ -22,6 +22,11 @@ android:defaultValue="true" android:title="@string/pref_development_hardware_accel" /> + <CheckBoxPreference + android:key="enable_hardware_accel_skia" + android:defaultValue="false" + android:title="@string/pref_development_hardware_accel_skia" /> + <ListPreference android:key="user_agent" android:title="@string/pref_development_uastring" @@ -29,13 +34,13 @@ android:entryValues="@array/pref_development_ua_values" android:defaultValue="0"/> - <!-- The javascript console is enabled by default when the user has - also enabled debug mode by navigating to about:debug. --> <CheckBoxPreference android:key="enable_visual_indicator" android:defaultValue="false" android:title="@string/pref_development_visual_indicator" /> + <!-- The javascript console is enabled by default when the user has + also enabled debug mode by navigating to about:debug. --> <CheckBoxPreference android:key="javascript_console" android:defaultValue="true" diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java index 8461d30..cb86c42 100644 --- a/src/com/android/browser/BrowserSettings.java +++ b/src/com/android/browser/BrowserSettings.java @@ -224,6 +224,7 @@ public class BrowserSettings implements OnSharedPreferenceChangeListener, settings.setJavaScriptEnabled(enableJavascript()); settings.setLightTouchEnabled(enableLightTouch()); settings.setNavDump(enableNavDump()); + settings.setHardwareAccelSkiaEnabled(isSkiaHardwareAccelerated()); settings.setShowVisualIndicator(enableVisualIndicator()); settings.setDefaultTextEncodingName(getDefaultTextEncoding()); settings.setDefaultZoom(getDefaultZoom()); @@ -454,7 +455,12 @@ public class BrowserSettings implements OnSharedPreferenceChangeListener, } public void resetDefaultPreferences() { - mPrefs.edit().clear().apply(); + // Preserve autologin setting + long gal = mPrefs.getLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, -1); + mPrefs.edit() + .clear() + .putLong(GoogleAccountLogin.PREF_AUTOLOGIN_TIME, gal) + .apply(); syncManagedSettings(); } @@ -624,6 +630,13 @@ public class BrowserSettings implements OnSharedPreferenceChangeListener, return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL, true); } + public boolean isSkiaHardwareAccelerated() { + if (!isDebugEnabled()) { + return false; + } + return mPrefs.getBoolean(PREF_ENABLE_HARDWARE_ACCEL_SKIA, false); + } + public int getUserAgent() { if (!isDebugEnabled()) { return 0; diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index 92f448c..fc4c35c 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -1636,7 +1636,6 @@ public class Controller bookmarksOrHistoryPicker(true); break; - case R.id.title_bar_share_page_url: case R.id.share_page_menu_id: Tab currentTab = mTabControl.getCurrentTab(); if (null == currentTab) { @@ -1703,20 +1702,6 @@ public class Controller int id = item.getItemId(); boolean result = true; switch (id) { - // For the context menu from the title bar - case R.id.title_bar_copy_page_url: - Tab currentTab = mTabControl.getCurrentTab(); - if (null == currentTab) { - result = false; - break; - } - WebView mainView = currentTab.getWebView(); - if (null == mainView) { - result = false; - break; - } - copy(mainView.getUrl()); - break; // -- Browser context menu case R.id.open_context_menu_id: case R.id.save_link_context_menu_id: diff --git a/src/com/android/browser/CrashRecoveryHandler.java b/src/com/android/browser/CrashRecoveryHandler.java index fdcdbc6..319ff89 100644 --- a/src/com/android/browser/CrashRecoveryHandler.java +++ b/src/com/android/browser/CrashRecoveryHandler.java @@ -243,11 +243,13 @@ public class CrashRecoveryHandler { mRecoveryState = loadCrashState(); mShouldPrompt = shouldPrompt(); } - if (mShouldPrompt) { - promptToRecover(mRecoveryState, intent); - return; - } else { - updateLastRecovered(); + if (mRecoveryState != null && !mRecoveryState.isEmpty()) { + if (mShouldPrompt) { + promptToRecover(mRecoveryState, intent); + return; + } else { + updateLastRecovered(); + } } mController.doStart(mRecoveryState, intent); mRecoveryState = null; diff --git a/src/com/android/browser/GoogleAccountLogin.java b/src/com/android/browser/GoogleAccountLogin.java index 3896560..2bd3c8c 100644 --- a/src/com/android/browser/GoogleAccountLogin.java +++ b/src/com/android/browser/GoogleAccountLogin.java @@ -67,6 +67,7 @@ public class GoogleAccountLogin implements Runnable, private String mLsid; private int mState; // {NONE(0), SID(1), LSID(2)} private boolean mTokensInvalidated; + private String mUserAgent; private GoogleAccountLogin(Activity activity, Account account, Runnable runnable) { @@ -74,6 +75,7 @@ public class GoogleAccountLogin implements Runnable, mAccount = account; mWebView = new WebView(mActivity); mRunnable = runnable; + mUserAgent = mWebView.getSettings().getUserAgentString(); // XXX: Doing pre-login causes onResume to skip calling // resumeWebViewTimers. So to avoid problems with timers not running, we @@ -106,17 +108,8 @@ public class GoogleAccountLogin implements Runnable, .appendQueryParameter("SID", mSid) .appendQueryParameter("LSID", mLsid) .build().toString(); - // Check mRunnable to see if the request has been canceled. Otherwise - // we might access a destroyed WebView. - String ua = null; - synchronized (this) { - if (mRunnable == null) { - return; - } - ua = mWebView.getSettings().getUserAgentString(); - } // Intentionally not using Proxy. - AndroidHttpClient client = AndroidHttpClient.newInstance(ua); + AndroidHttpClient client = AndroidHttpClient.newInstance(mUserAgent); HttpPost request = new HttpPost(url); String result = null; diff --git a/src/com/android/browser/NavigationBarBase.java b/src/com/android/browser/NavigationBarBase.java index a059352..724dcc8 100644 --- a/src/com/android/browser/NavigationBarBase.java +++ b/src/com/android/browser/NavigationBarBase.java @@ -74,7 +74,6 @@ public class NavigationBarBase extends LinearLayout implements OnClickListener, mFavicon = (ImageView) findViewById(R.id.favicon); mUrlInput = (UrlInputView) findViewById(R.id.url); mUrlInput.setUrlInputListener(this); - mUrlInput.setController(mUiController); mUrlInput.setOnFocusChangeListener(this); mUrlInput.setSelectAllOnFocus(true); mUrlInput.addQueryTextWatcher(this); @@ -84,6 +83,7 @@ public class NavigationBarBase extends LinearLayout implements OnClickListener, mTitleBar = titleBar; mBaseUi = mTitleBar.getUi(); mUiController = mTitleBar.getUiController(); + mUrlInput.setController(mUiController); } public void setLock(Drawable d) { diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java index 400b695..388c262 100644 --- a/src/com/android/browser/NavigationBarPhone.java +++ b/src/com/android/browser/NavigationBarPhone.java @@ -86,14 +86,6 @@ public class NavigationBarPhone extends NavigationBarBase implements } @Override - public void createContextMenu(ContextMenu menu) { - Activity activity = mBaseUi.getActivity(); - MenuInflater inflater = activity.getMenuInflater(); - inflater.inflate(R.menu.title_context, menu); - activity.onCreateContextMenu(menu, this, null); - } - - @Override protected void setSearchMode(boolean voiceSearchEnabled) { boolean showvoicebutton = voiceSearchEnabled && mUiController.supportsVoiceSearch(); diff --git a/src/com/android/browser/PreferenceKeys.java b/src/com/android/browser/PreferenceKeys.java index ce8ec9f..65218e5 100644 --- a/src/com/android/browser/PreferenceKeys.java +++ b/src/com/android/browser/PreferenceKeys.java @@ -48,6 +48,7 @@ public interface PreferenceKeys { // Keys for debug_preferences.xml // ---------------------- static final String PREF_ENABLE_HARDWARE_ACCEL = "enable_hardware_accel"; + static final String PREF_ENABLE_HARDWARE_ACCEL_SKIA = "enable_hardware_accel_skia"; static final String PREF_USER_AGENT = "user_agent"; // ---------------------- diff --git a/src/com/android/browser/SnapshotBar.java b/src/com/android/browser/SnapshotBar.java index 9fb68cf..ba0bf98 100644 --- a/src/com/android/browser/SnapshotBar.java +++ b/src/com/android/browser/SnapshotBar.java @@ -23,16 +23,22 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; +import android.view.Menu; +import android.view.MenuItem; import android.view.ViewConfiguration; import android.view.ViewPropertyAnimator; +import android.webkit.WebView; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.PopupMenu; +import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.TextView; import java.text.DateFormat; import java.util.Date; -public class SnapshotBar extends LinearLayout implements OnClickListener { +public class SnapshotBar extends LinearLayout implements OnClickListener, + OnMenuItemClickListener { private static final int MSG_SHOW_TITLE = 1; private static final long DURATION_SHOW_DATE = BaseUi.HIDE_TITLEBAR_DELAY; @@ -171,7 +177,11 @@ public class SnapshotBar extends LinearLayout implements OnClickListener { if (mBookmarks == v) { mTitleBar.getUiController().bookmarksOrHistoryPicker(false); } else if (mGoLive == v) { - goLive(); + PopupMenu popup = new PopupMenu(mContext, mGoLive); + Menu menu = popup.getMenu(); + popup.getMenuInflater().inflate(R.menu.snapshot_go_live, menu); + popup.setOnMenuItemClickListener(this); + popup.show(); } else if (mTabSwitcher == v) { ((PhoneUi) mTitleBar.getUi()).toggleNavScreen(); } else if (mOverflowMenu == v) { @@ -188,6 +198,16 @@ public class SnapshotBar extends LinearLayout implements OnClickListener { } } + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.snapshot_go_live: + goLive(); + return true; + } + return false; + } + private void goLive() { Tab t = mTitleBar.getUi().getActiveTab(); t.loadUrl(t.getUrl(), null); diff --git a/src/com/android/browser/SuggestionsAdapter.java b/src/com/android/browser/SuggestionsAdapter.java index 9a099cb..e1511b9 100644 --- a/src/com/android/browser/SuggestionsAdapter.java +++ b/src/com/android/browser/SuggestionsAdapter.java @@ -17,6 +17,7 @@ package com.android.browser; import com.android.browser.provider.BrowserProvider2; +import com.android.browser.provider.BrowserProvider2.OmniboxSuggestions; import com.android.browser.search.SearchEngine; import android.app.SearchManager; @@ -53,9 +54,12 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable, public static final int TYPE_SUGGEST = 4; public static final int TYPE_VOICE_SEARCH = 5; - private static final String[] COMBINED_PROJECTION = - {BrowserContract.Combined._ID, BrowserContract.Combined.TITLE, - BrowserContract.Combined.URL, BrowserContract.Combined.IS_BOOKMARK}; + private static final String[] COMBINED_PROJECTION = { + OmniboxSuggestions._ID, + OmniboxSuggestions.TITLE, + OmniboxSuggestions.URL, + OmniboxSuggestions.IS_BOOKMARK + }; private static final String COMBINED_SELECTION = "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)"; @@ -178,9 +182,11 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable, tv1.setText(Html.fromHtml(item.title)); if (TextUtils.isEmpty(item.url)) { tv2.setVisibility(View.GONE); + tv1.setMaxLines(2); } else { tv2.setVisibility(View.VISIBLE); tv2.setText(item.url); + tv1.setMaxLines(1); } int id = -1; switch (item.type) { @@ -470,18 +476,14 @@ public class SuggestionsAdapter extends BaseAdapter implements Filterable, args[4] = like; selection = COMBINED_SELECTION; } - Uri.Builder ub = BrowserContract.Combined.CONTENT_URI.buildUpon(); + Uri.Builder ub = OmniboxSuggestions.CONTENT_URI.buildUpon(); ub.appendQueryParameter(BrowserContract.PARAM_LIMIT, Integer.toString(Math.max(mLinesLandscape, mLinesPortrait))); ub.appendQueryParameter(BrowserProvider2.PARAM_GROUP_BY, - BrowserContract.Combined.URL); + OmniboxSuggestions.URL); mCursor = mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION, - selection, - (constraint != null) ? args : null, - BrowserContract.Combined.IS_BOOKMARK + " DESC, " + - BrowserContract.Combined.VISITS + " DESC, " + - BrowserContract.Combined.DATE_LAST_VISITED + " DESC"); + selection, (constraint != null) ? args : null, null); if (mCursor != null) { mCursor.moveToFirst(); } diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java index b2c2af8..2b4dd63 100644 --- a/src/com/android/browser/TabBar.java +++ b/src/com/android/browser/TabBar.java @@ -231,13 +231,6 @@ public class TabBar extends LinearLayout implements OnClickListener { mUi.showTitleBar(); } - @Override - public void createContextMenu(ContextMenu menu) { - MenuInflater inflater = mActivity.getMenuInflater(); - inflater.inflate(R.menu.title_context, menu); - mActivity.onCreateContextMenu(menu, this, null); - } - private TabView buildTabView(Tab tab) { TabView tabview = new TabView(mActivity, tab); mTabMap.put(tab, tabview); diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java index aeba7cf..301e09f 100644 --- a/src/com/android/browser/XLargeUi.java +++ b/src/com/android/browser/XLargeUi.java @@ -253,7 +253,7 @@ public class XLargeUi extends BaseUi { @Override public void onActionModeStarted(ActionMode mode) { if (!mTitleBar.isEditingUrl()) { - // hide the fake title bar when CAB is shown + // hide the title bar when CAB is shown hideTitleBar(); } } diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java index fe7a31b..1821b50 100644 --- a/src/com/android/browser/provider/BrowserProvider2.java +++ b/src/com/android/browser/provider/BrowserProvider2.java @@ -81,6 +81,15 @@ public class BrowserProvider2 extends SQLiteContentProvider { public static final String THUMBNAIL = "thumbnail"; } + public static interface OmniboxSuggestions { + public static final Uri CONTENT_URI = Uri.withAppendedPath( + BrowserContract.AUTHORITY_URI, "omnibox_suggestions"); + public static final String _ID = "_id"; + public static final String URL = "url"; + public static final String TITLE = "title"; + public static final String IS_BOOKMARK = "bookmark"; + } + static final String TABLE_BOOKMARKS = "bookmarks"; static final String TABLE_HISTORY = "history"; static final String TABLE_IMAGES = "images"; @@ -97,6 +106,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { static final String VIEW_ACCOUNTS = "v_accounts"; static final String VIEW_SNAPSHOTS_COMBINED = "v_snapshots_combined"; + static final String VIEW_OMNIBOX_SUGGESTIONS = "v_omnibox_suggestions"; static final String FORMAT_COMBINED_JOIN_SUBQUERY_JOIN_IMAGES = "history LEFT OUTER JOIN (%s) bookmarks " + @@ -121,6 +131,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { static final int THUMBNAILS = 10; static final int THUMBNAILS_ID = 11; + static final int OMNIBOX_SUGGESTIONS = 20; static final int BOOKMARKS = 1000; static final int BOOKMARKS_ID = 1001; @@ -200,6 +211,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { matcher.addURI(authority, "settings", SETTINGS); matcher.addURI(authority, "thumbnails", THUMBNAILS); matcher.addURI(authority, "thumbnails/#", THUMBNAILS_ID); + matcher.addURI(authority, "omnibox_suggestions", OMNIBOX_SUGGESTIONS); // Legacy matcher.addURI(LEGACY_AUTHORITY, "searches", SEARCHES); @@ -346,7 +358,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { final class DatabaseHelper extends SQLiteOpenHelper { static final String DATABASE_NAME = "browser2.db"; - static final int DATABASE_VERSION = 31; + static final int DATABASE_VERSION = 32; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @@ -418,6 +430,11 @@ public class BrowserProvider2 extends SQLiteContentProvider { } enableSync(db); + createOmniboxSuggestions(db); + } + + void createOmniboxSuggestions(SQLiteDatabase db) { + db.execSQL(SQL_CREATE_VIEW_OMNIBOX_SUGGESTIONS); } void createThumbnails(SQLiteDatabase db) { @@ -471,6 +488,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { BookmarkColumns.TITLE, // 1 BookmarkColumns.FAVICON, // 2 BookmarkColumns.TOUCH_ICON, // 3 + BookmarkColumns.CREATED, // 4 }, BookmarkColumns.BOOKMARK + "!=0", null, null, null, null); if (c != null) { @@ -478,6 +496,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { ContentValues values = new ContentValues(); values.put(Bookmarks.URL, c.getString(0)); values.put(Bookmarks.TITLE, c.getString(1)); + values.put(Bookmarks.DATE_CREATED, c.getInt(4)); values.put(Bookmarks.POSITION, 0); values.put(Bookmarks.PARENT, FIXED_ID_ROOT); ContentValues imageValues = new ContentValues(); @@ -497,7 +516,9 @@ public class BrowserProvider2 extends SQLiteContentProvider { BookmarkColumns.VISITS, // 2 BookmarkColumns.DATE, // 3 BookmarkColumns.CREATED, // 4 - }, null, null, null, null, null); + }, BookmarkColumns.VISITS + " > 0 OR " + + BookmarkColumns.BOOKMARK + " = 0", + null, null, null, null); if (c != null) { while (c.moveToNext()) { ContentValues values = new ContentValues(); @@ -541,6 +562,9 @@ public class BrowserProvider2 extends SQLiteContentProvider { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < 32) { + createOmniboxSuggestions(db); + } if (oldVersion < 31) { createThumbnails(db); } @@ -1030,6 +1054,11 @@ public class BrowserProvider2 extends SQLiteContentProvider { break; } + case OMNIBOX_SUGGESTIONS: { + qb.setTables(VIEW_OMNIBOX_SUGGESTIONS); + break; + } + default: { throw new UnsupportedOperationException("Unknown URL " + uri.toString()); } @@ -1227,6 +1256,7 @@ public class BrowserProvider2 extends SQLiteContentProvider { new String[] { Long.toString(id) }); } } + c.close(); break; } case THUMBNAILS_ID: { @@ -1259,8 +1289,12 @@ public class BrowserProvider2 extends SQLiteContentProvider { " AND account_type = ? AND account_name = ?", new String[] { ChromeSyncColumns.FOLDER_NAME_BOOKMARKS_BAR, accountType, accountName }, null, null, null); - if (c.moveToFirst()) { - return c.getLong(0); + try { + if (c.moveToFirst()) { + return c.getLong(0); + } + } finally { + c.close(); } } return FIXED_ID_ROOT; @@ -1737,8 +1771,8 @@ public class BrowserProvider2 extends SQLiteContentProvider { if (c.moveToFirst()) { parentAccountName = c.getString(0); parentAccountType = c.getString(1); - c.close(); } + c.close(); } else if (values.containsKey(Bookmarks.ACCOUNT_NAME) || values.containsKey(Bookmarks.ACCOUNT_TYPE)) { // TODO: Implement if needed (no one needs this yet) @@ -2053,4 +2087,21 @@ public class BrowserProvider2 extends SQLiteContentProvider { return mSource.moveToPosition(newPosition); } } + + // --------------------------------------------------- + // SQL below, be warned + // --------------------------------------------------- + + private static final String SQL_CREATE_VIEW_OMNIBOX_SUGGESTIONS = + "CREATE VIEW IF NOT EXISTS v_omnibox_suggestions " + + " AS " + + " SELECT _id, url, title, 1 AS bookmark, 0 AS visits, 0 AS date" + + " FROM bookmarks " + + " WHERE deleted = 0 AND folder = 0 " + + " UNION ALL " + + " SELECT _id, url, title, 0 AS bookmark, visits, date " + + " FROM history " + + " WHERE url NOT IN (SELECT url FROM bookmarks" + + " WHERE deleted = 0 AND folder = 0) " + + " ORDER BY bookmark DESC, visits DESC, date DESC "; } diff --git a/src/com/android/browser/provider/SnapshotProvider.java b/src/com/android/browser/provider/SnapshotProvider.java index 49557f7..c0aad23 100644 --- a/src/com/android/browser/provider/SnapshotProvider.java +++ b/src/com/android/browser/provider/SnapshotProvider.java @@ -106,7 +106,6 @@ public class SnapshotProvider extends ContentProvider { @Override public boolean onCreate() { - mOpenHelper = new SnapshotDatabaseHelper(getContext()); IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_EJECT); filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); getContext().registerReceiver(mExternalStorageReceiver, filter); @@ -117,13 +116,15 @@ public class SnapshotProvider extends ContentProvider { @Override public void onReceive(Context context, Intent intent) { - try { - mOpenHelper.close(); - } catch (Throwable t) { - // We failed to close the open helper, which most likely means - // another thread is busy attempting to open the database - // or use the database. Let that thread try to gracefully - // deal with the error + if (mOpenHelper != null) { + try { + mOpenHelper.close(); + } catch (Throwable t) { + // We failed to close the open helper, which most likely means + // another thread is busy attempting to open the database + // or use the database. Let that thread try to gracefully + // deal with the error + } } } }; @@ -132,6 +133,9 @@ public class SnapshotProvider extends ContentProvider { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { try { + if (mOpenHelper == null) { + mOpenHelper = new SnapshotDatabaseHelper(getContext()); + } return mOpenHelper.getWritableDatabase(); } catch (Throwable t) { return null; @@ -145,6 +149,9 @@ public class SnapshotProvider extends ContentProvider { if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { try { + if (mOpenHelper == null) { + mOpenHelper = new SnapshotDatabaseHelper(getContext()); + } return mOpenHelper.getReadableDatabase(); } catch (Throwable t) { return null; diff --git a/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java b/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java index 7d174ee..bd3e289 100644 --- a/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java +++ b/src/com/android/browser/widget/BookmarkThumbnailWidgetService.java @@ -114,7 +114,7 @@ public class BookmarkThumbnailWidgetService extends RemoteViewsService { pref.edit() .putLong(STATE_CURRENT_FOLDER, rootFolder) .putLong(STATE_ROOT_FOLDER, rootFolder) - .commit(); + .apply(); } /** diff --git a/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java b/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java new file mode 100644 index 0000000..91f7238 --- /dev/null +++ b/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser.tests; + +import com.android.browser.provider.BrowserProvider; +import com.android.browser.tests.utils.BP2TestCaseHelper; + +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.net.Uri; +import android.provider.Browser; +import android.provider.Browser.BookmarkColumns; +import android.provider.BrowserContract; +import android.provider.BrowserContract.Bookmarks; +import android.provider.BrowserContract.History; +import android.provider.BrowserContract.Images; +import android.test.suitebuilder.annotation.SmallTest; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +@SmallTest +public class BP1to2UpgradeTests extends BP2TestCaseHelper { + + BrowserProvider mBp1; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mBp1 = new BrowserProvider(); + mBp1.attachInfo(getMockContext(), null); + } + + /** + * Test that simply makes sure BP1->BP2 with no changes works as intended + */ + public void testStockUpgrade() { + Cursor c = mBp1.query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL }, null, null, + BookmarkColumns.URL + " DESC"); + ArrayList<String> urls = new ArrayList<String>(c.getCount()); + while (c.moveToNext()) { + urls.add(c.getString(0)); + } + c.close(); + // First, test the public API (which will hit BP2) + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL }, null, null, + BookmarkColumns.URL + " DESC"); + assertEquals(urls.size(), c.getCount()); + int i = 0; + while (c.moveToNext()) { + assertEquals(urls.get(i++), c.getString(0)); + } + c.close(); + // Next, test BP2's new API (not a public API) + c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + new String[] { Bookmarks.URL }, null, null, + Bookmarks.URL + " DESC"); + assertEquals(urls.size(), c.getCount()); + i = 0; + while (c.moveToNext()) { + assertEquals(urls.get(i++), c.getString(0)); + } + c.close(); + } + + public void testPreserveHistory() { + ContentValues values = new ContentValues(); + values.put(BookmarkColumns.URL, "http://slashdot.org/"); + values.put(BookmarkColumns.BOOKMARK, 0); + values.put(BookmarkColumns.DATE, 123456); + mBp1.insert(Browser.BOOKMARKS_URI, values); + // First, test internal API + Cursor c = getMockContentResolver().query(History.CONTENT_URI, + new String[] { History.URL, History.DATE_LAST_VISITED }, + null, null, null); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + // Next, test public API + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + Browser.HISTORY_PROJECTION, BookmarkColumns.BOOKMARK + " = 0", + null, null); + assertEquals("public API", 1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", + c.getString(Browser.HISTORY_PROJECTION_URL_INDEX)); + assertEquals(123456, c.getInt(Browser.HISTORY_PROJECTION_DATE_INDEX)); + c.close(); + } + + public void testPreserveBookmarks() { + // First, nuke 'er (deletes stock bookmarks) + mBp1.delete(Browser.BOOKMARKS_URI, null, null); + ContentValues values = new ContentValues(); + values.put(BookmarkColumns.URL, "http://slashdot.org/"); + values.put(BookmarkColumns.BOOKMARK, 1); + values.put(BookmarkColumns.CREATED, 123456); + mBp1.insert(Browser.BOOKMARKS_URI, values); + // First, test internal API + Cursor c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + new String[] { Bookmarks.URL, Bookmarks.DATE_CREATED }, + null, null, null); + assertEquals(1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + // Next, test public API + c = getMockContentResolver().query(Browser.BOOKMARKS_URI, + new String[] { BookmarkColumns.URL, BookmarkColumns.CREATED }, + BookmarkColumns.BOOKMARK + " = 1", null, null); + assertEquals("public API", 1, c.getCount()); + assertTrue(c.moveToFirst()); + assertEquals("http://slashdot.org/", c.getString(0)); + assertEquals(123456, c.getInt(1)); + c.close(); + } + + public void testEmptyUpgrade() { + mBp1.delete(Browser.BOOKMARKS_URI, null, null); + Cursor c = getMockContentResolver().query(Bookmarks.CONTENT_URI, + null, null, null, null); + assertEquals(0, c.getCount()); + c.close(); + } + +} diff --git a/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java b/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java index c374292..536163a 100644 --- a/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java +++ b/tests/src/com/android/browser/tests/utils/ProviderTestCase3.java @@ -69,6 +69,11 @@ public abstract class ProviderTestCase3<T extends ContentProvider> extends Andro public Context getApplicationContext() { return this; } + + @Override + public Object getSystemService(String name) { + return null; + } } /** * Constructor. @@ -114,7 +119,15 @@ public abstract class ProviderTestCase3<T extends ContentProvider> extends Andro //delegated to getContext(), // The context that file methods are delegated to filenamePrefix); - mProviderContext = new IsolatedContext(mResolver, targetContextWrapper); + // The default IsolatedContext has a mock AccountManager that doesn't + // work for us, so override getSystemService to always return null + mProviderContext = new IsolatedContext(mResolver, targetContextWrapper) { + + @Override + public Object getSystemService(String name) { + return null; + } + }; mProvider = mProviderClass.newInstance(); mProvider.attachInfo(mProviderContext, null); |