Merge "apply() instead of commit() SharedPrefs change in BookmarkWidget"
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/snapshot_go_live.xml b/res/menu/snapshot_go_live.xml
new file mode 100644
index 0000000..aa6b38e
--- /dev/null
+++ b/res/menu/snapshot_go_live.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <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 ee3ce95..6c1b102 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1010,4 +1010,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/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 8461d30..39abf33 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -454,7 +454,12 @@
     }
 
     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();
     }
 
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 @@
             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/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.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 @@
         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 @@
         }
     }
 
+    @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 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 @@
         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 @@
                 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/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
index 36064a5..1821b50 100644
--- a/src/com/android/browser/provider/BrowserProvider2.java
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -81,6 +81,15 @@
         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 @@
 
     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 @@
 
     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 @@
         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 @@
 
     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 @@
             }
 
             enableSync(db);
+            createOmniboxSuggestions(db);
+        }
+
+        void createOmniboxSuggestions(SQLiteDatabase db) {
+            db.execSQL(SQL_CREATE_VIEW_OMNIBOX_SUGGESTIONS);
         }
 
         void createThumbnails(SQLiteDatabase db) {
@@ -545,6 +562,9 @@
 
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            if (oldVersion < 32) {
+                createOmniboxSuggestions(db);
+            }
             if (oldVersion < 31) {
                 createThumbnails(db);
             }
@@ -1034,6 +1054,11 @@
                 break;
             }
 
+            case OMNIBOX_SUGGESTIONS: {
+                qb.setTables(VIEW_OMNIBOX_SUGGESTIONS);
+                break;
+            }
+
             default: {
                 throw new UnsupportedOperationException("Unknown URL " + uri.toString());
             }
@@ -2062,4 +2087,21 @@
             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/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java b/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java
index 36f7aba..91f7238 100644
--- a/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java
+++ b/tests/src/com/android/browser/tests/BP1to2UpgradeTests.java
@@ -99,8 +99,8 @@
         c.close();
         // Next, test public API
         c = getMockContentResolver().query(Browser.BOOKMARKS_URI,
-                Browser.HISTORY_PROJECTION, BookmarkColumns.BOOKMARK + " = ?",
-                new String[] { "0" }, null);
+                Browser.HISTORY_PROJECTION, BookmarkColumns.BOOKMARK + " = 0",
+                null, null);
         assertEquals("public API", 1, c.getCount());
         assertTrue(c.moveToFirst());
         assertEquals("http://slashdot.org/",
@@ -129,7 +129,7 @@
         // Next, test public API
         c = getMockContentResolver().query(Browser.BOOKMARKS_URI,
                 new String[] { BookmarkColumns.URL, BookmarkColumns.CREATED },
-                BookmarkColumns.BOOKMARK + " = ?", new String[] { "1" }, null);
+                BookmarkColumns.BOOKMARK + " = 1", null, null);
         assertEquals("public API", 1, c.getCount());
         assertTrue(c.moveToFirst());
         assertEquals("http://slashdot.org/", c.getString(0));