Merge "Fixed close tab NPE" into honeycomb
diff --git a/res/layout/add_to_option.xml b/res/layout/add_to_option.xml
new file mode 100644
index 0000000..4cfa9f8
--- /dev/null
+++ b/res/layout/add_to_option.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight" />
diff --git a/res/layout/browser_add_bookmark.xml b/res/layout/browser_add_bookmark.xml
index 8adf4b6..e25f903 100644
--- a/res/layout/browser_add_bookmark.xml
+++ b/res/layout/browser_add_bookmark.xml
@@ -131,19 +131,15 @@
             android:text="@string/containing_folder"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
-        <TextView
+        <view class="com.android.browser.addbookmark.FolderSpinner"
             android:id="@+id/folder"
             android:layout_height="wrap_content"
-            android:layout_width="250dip"
+            android:layout_width="wrap_content"
             android:layout_marginRight="20dip"
             android:layout_marginLeft="20dip"
+            android:spinnerMode="dropdown"
             android:gravity="center_vertical"
-            android:singleLine="true"
-            android:ellipsize="start"
-            android:text="@string/bookmarks"
-            android:drawableLeft="@drawable/ic_menu_bookmarks"
-            android:layout_marginBottom="40dip"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
+            />
       </TableRow>
     </TableLayout>
 
diff --git a/res/menu/folder_choice.xml b/res/menu/folder_choice.xml
deleted file mode 100644
index c62e2f8..0000000
--- a/res/menu/folder_choice.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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/home_screen"
-        android:icon="@*android:drawable/ic_menu_home"
-        android:title="@string/add_to_homescreen_menu_option"/>
-    <item android:id="@+id/bookmarks"
-        android:icon="@drawable/ic_menu_bookmarks"
-        android:title="@string/add_to_bookmarks_menu_option"/>
-    <item android:id="@+id/other"
-        android:icon="@*android:drawable/ic_menu_archive"
-        android:title="@string/add_to_other_folder_menu_option"/>
-</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2a00f1d..b8a45bf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -522,7 +522,7 @@
     <string name="pref_content_load_page">Open pages in overview</string>
     <!-- Settings summary -->
     <string name="pref_content_load_page_summary">Show overview of newly opened pages</string>
-    <!-- Settings screen, section title -->
+    <!-- Settings screen, section title [CHAR LIMIT=50] -->
     <string name="pref_extras_title">Advanced</string>
     <!-- Settings label -->
     <string name="pref_extras_website_settings">Website settings</string>
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index d3c147c..9d8c73c 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -17,6 +17,7 @@
 package com.android.browser;
 
 import com.android.browser.provider.BrowserProvider2;
+import com.android.browser.addbookmark.FolderSpinnerAdapter;
 
 import android.app.Activity;
 import android.app.LoaderManager;
@@ -44,7 +45,6 @@
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
-import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
@@ -55,7 +55,7 @@
 import android.widget.CursorAdapter;
 import android.widget.EditText;
 import android.widget.ListView;
-import android.widget.PopupMenu;
+import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -66,7 +66,7 @@
 public class AddBookmarkPage extends Activity
         implements View.OnClickListener, TextView.OnEditorActionListener,
         AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor>,
-        BreadCrumbView.Controller, PopupMenu.OnMenuItemClickListener {
+        BreadCrumbView.Controller, AdapterView.OnItemSelectedListener {
 
     public static final long DEFAULT_FOLDER_ID = -1;
     public static final String TOUCH_ICON_URL = "touch_icon_url";
@@ -94,7 +94,7 @@
     private Bundle      mMap;
     private String      mTouchIconUrl;
     private String      mOriginalUrl;
-    private TextView mFolder;
+    private Spinner mFolder;
     private View mDefaultView;
     private View mFolderSelector;
     private EditText mFolderNamer;
@@ -112,7 +112,9 @@
     private long mRootFolder;
     private TextView mTopLevelLabel;
     private Drawable mHeaderIcon;
-
+    // We manually change the spinner's selection if the edited bookmark is not
+    // in the root folder.  This makes sure our listener ignores this change.
+    private boolean mIgnoreSelectionChange;
     private static class Folder {
         String Name;
         long Id;
@@ -198,11 +200,22 @@
             if (data != null) {
                 Folder folder = (Folder) data;
                 mCurrentFolder = folder.Id;
-                int resource = mCurrentFolder == mRootFolder ?
-                        R.drawable.ic_menu_bookmarks :
-                        com.android.internal.R.drawable.ic_menu_archive;
-                Drawable drawable = getResources().getDrawable(resource);
-                updateFolderLabel(folder.Name, drawable);
+                if (mCurrentFolder == mRootFolder) {
+                    // The Spinner changed to show "Other folder ..."  Change
+                    // it back to "Bookmarks", which is position 0 if we are
+                    // editing a folder, 1 otherwise.
+                    mFolder.setSelection(mEditingFolder ? 0 : 1);
+                } else {
+                    ((TextView) mFolder.getSelectedView()).setText(folder.Name);
+                }
+            }
+        } else {
+            // The user canceled selecting a folder.  Revert back to the earlier
+            // selection.
+            if (mSaveToHomeScreen) {
+                mFolder.setSelection(0);
+            } else {
+                mFolder.setSelection(mEditingFolder ? 0 : 1);
             }
         }
     }
@@ -230,15 +243,6 @@
             } else {
                 finish();
             }
-        } else if (v == mFolder) {
-            PopupMenu popup = new PopupMenu(this, mFolder);
-            popup.getMenuInflater().inflate(R.menu.folder_choice,
-                    popup.getMenu());
-            if (mEditingFolder) {
-                popup.getMenu().removeItem(R.id.home_screen);
-            }
-            popup.setOnMenuItemClickListener(this);
-            popup.show();
         } else if (v == mAddNewFolder) {
             setShowFolderNamer(true);
             mFolderNamer.setText(R.string.new_folder);
@@ -254,25 +258,32 @@
     }
 
     @Override
-    public boolean onMenuItemClick(MenuItem item) {
-        switch(item.getItemId()) {
-            case R.id.bookmarks:
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        if (mIgnoreSelectionChange) {
+            mIgnoreSelectionChange = false;
+            return;
+        }
+        // In response to the spinner changing.
+        int intId = (int) id;
+        switch (intId) {
+            case FolderSpinnerAdapter.ROOT_FOLDER:
                 mCurrentFolder = mRootFolder;
-                updateFolderLabel(item.getTitle(), item.getIcon());
                 mSaveToHomeScreen = false;
                 break;
-            case R.id.home_screen:
+            case FolderSpinnerAdapter.HOME_SCREEN:
                 // Create a short cut to the home screen
                 mSaveToHomeScreen = true;
-                updateFolderLabel(item.getTitle(), item.getIcon());
                 break;
-            case R.id.other:
+            case FolderSpinnerAdapter.OTHER_FOLDER:
                 switchToFolderSelector();
                 break;
             default:
-                return false;
+                break;
         }
-        return true;
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
     }
 
     private void completeOrCancelFolderNaming(boolean cancel) {
@@ -317,6 +328,8 @@
     }
 
     private void switchToFolderSelector() {
+        // Set the list to the top in case it is scrolled.
+        mListView.setSelection(0);
         mDefaultView.setVisibility(View.GONE);
         mFolderSelector.setVisibility(View.VISIBLE);
         mCrumbHolder.setVisibility(View.VISIBLE);
@@ -399,9 +412,7 @@
                     moveCursorToFolder(cursor, parent, idIndex);
                     String name = cursor.getString(titleIndex);
                     if (parent == mCurrentFolder) {
-                        Drawable draw = getResources().getDrawable(
-                                com.android.internal.R.drawable.ic_menu_archive);
-                        updateFolderLabel(name, draw);
+                        ((TextView) mFolder.getSelectedView()).setText(name);
                     }
                     folderStack.push(new Folder(name, parent));
                     parent = cursor.getLong(parentIndex);
@@ -448,18 +459,6 @@
         }
     }
 
-    /**
-     * Update the name and image to show where the bookmark will be added
-     * @param name Name of the location to save (folder name, bookmarks, or home
-     *             screen.
-     * @param drawable Image to show corresponding to the save location.
-     */
-    void updateFolderLabel(CharSequence name, Drawable drawable) {
-        mFolder.setText(name);
-        mFolder.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null,
-                null);
-    }
-
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position,
             long id) {
@@ -573,8 +572,15 @@
         mCancelButton = findViewById(R.id.cancel);
         mCancelButton.setOnClickListener(this);
 
-        mFolder = (TextView) findViewById(R.id.folder);
-        mFolder.setOnClickListener(this);
+        mFolder = (Spinner) findViewById(R.id.folder);
+        mFolder.setAdapter(new FolderSpinnerAdapter(!mEditingFolder));
+        if (!mEditingFolder) {
+            // Initially the "Bookmarks" folder should be showing, rather than
+            // the home screen.  In the editing folder case, home screen is not
+            // an option, so "Bookmarks" folder is already at the top.
+            mFolder.setSelection(FolderSpinnerAdapter.ROOT_FOLDER);
+        }
+        mFolder.setOnItemSelectedListener(this);
 
         mDefaultView = findViewById(R.id.default_view);
         mFolderSelector = findViewById(R.id.folder_selector);
@@ -609,6 +615,11 @@
         if (mCurrentFolder != mRootFolder) {
             // Find all the folders
             manager.initLoader(LOADER_ID_ALL_FOLDERS, null, this);
+            // Since we're not in the root folder, change the selection to other
+            // folder now.  The text will get changed once we select the correct
+            // folder.
+            mIgnoreSelectionChange = true;
+            mFolder.setSelection(mEditingFolder ? 1 : 2);
         } else {
             setShowBookmarkIcon(true);
         }
diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java
index 5f76f72..bd7f8e6 100644
--- a/src/com/android/browser/WebStorageSizeManager.java
+++ b/src/com/android/browser/WebStorageSizeManager.java
@@ -141,11 +141,11 @@
         }
 
         public long getFreeSpaceSizeBytes() {
-            return mFs.getAvailableBlocks() * mFs.getBlockSize();
+            return (long)(mFs.getAvailableBlocks()) * mFs.getBlockSize();
         }
 
         public long getTotalSizeBytes() {
-            return mFs.getBlockCount() * mFs.getBlockSize();
+            return (long)(mFs.getBlockCount()) * mFs.getBlockSize();
         }
     };
 
diff --git a/src/com/android/browser/addbookmark/FolderSpinner.java b/src/com/android/browser/addbookmark/FolderSpinner.java
new file mode 100644
index 0000000..789c1f1
--- /dev/null
+++ b/src/com/android/browser/addbookmark/FolderSpinner.java
@@ -0,0 +1,45 @@
+/*
+ * 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.addbookmark;
+
+import android.content.Context;
+import android.view.View;
+import android.util.AttributeSet;
+import android.widget.Spinner;
+
+/**
+ * Special Spinner class which calls onItemSelected even if the item selected
+ * was already selected.  In that case, it passes null for the View.
+ */
+public class FolderSpinner extends Spinner {
+    public FolderSpinner(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setSelection(int position) {
+        int oldPosition = getSelectedItemPosition();
+        super.setSelection(position);
+        if (oldPosition == position) {
+            // Normally this is not called because the item did not actually
+            // change, but in this case, we still want it to be called.
+            long id = getAdapter().getItemId(position);
+            getOnItemSelectedListener().onItemSelected(this, null, position, id);
+        }
+    }
+}
+
diff --git a/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java b/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java
new file mode 100644
index 0000000..5c17bfa
--- /dev/null
+++ b/src/com/android/browser/addbookmark/FolderSpinnerAdapter.java
@@ -0,0 +1,135 @@
+/*
+ * 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.addbookmark;
+
+import com.android.browser.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.DataSetObserver;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Adapter;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+/**
+ * SpinnerAdapter used in the AddBookmarkPage to select where to save a
+ * bookmark/folder.
+ */
+public class FolderSpinnerAdapter implements SpinnerAdapter {
+    private boolean mIncludeHomeScreen;
+
+    public static final int HOME_SCREEN = 0;
+    public static final int ROOT_FOLDER = 1;
+    public static final int OTHER_FOLDER = 2;
+
+    public FolderSpinnerAdapter(boolean includeHomeScreen) {
+        mIncludeHomeScreen = includeHomeScreen;
+    }
+
+    @Override
+    public View getDropDownView(int position, View convertView, ViewGroup parent) {
+        int labelResource;
+        int drawableResource;
+        if (!mIncludeHomeScreen) {
+            position++;
+        }
+        switch (position) {
+            case HOME_SCREEN:
+                labelResource = R.string.add_to_homescreen_menu_option;
+                drawableResource = com.android.internal.R.drawable.ic_menu_home;
+                break;
+            case ROOT_FOLDER:
+                labelResource = R.string.add_to_bookmarks_menu_option;
+                drawableResource = R.drawable.ic_menu_bookmarks;
+                break;
+            case OTHER_FOLDER:
+                labelResource = R.string.add_to_other_folder_menu_option;
+                drawableResource = com.android.internal.R.drawable.ic_menu_archive;
+                break;
+            default:
+                labelResource = 0;
+                drawableResource = 0;
+                // assert
+                break;
+        }
+        Context context = parent.getContext();
+        LayoutInflater factory = LayoutInflater.from(context);
+        TextView textView = (TextView) factory.inflate(R.layout.add_to_option, null);
+        textView.setText(labelResource);
+        Drawable drawable = context.getResources().getDrawable(drawableResource);
+        textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null,
+                null, null);
+        return textView;
+    }
+
+    @Override
+    public void registerDataSetObserver(DataSetObserver observer) {
+    }
+
+    @Override
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+    }
+
+    @Override
+    public int getCount() {
+        return mIncludeHomeScreen ? 3 : 2;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return null;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        long id = position;
+        if (!mIncludeHomeScreen) {
+            id++;
+        }
+        return id;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        return getDropDownView(position, convertView, parent);
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        // Never want to recycle views
+        return Adapter.IGNORE_ITEM_VIEW_TYPE;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return false;
+    }
+}