Beginning work on adding bookmarks with folders.

Bug: 2953515

Provides the basic functionality for the AddBookmark page, allowing
the user to save the bookmark in a folder of his/her choosing.

Change-Id: I170599b723069aaee661dae3fc1a0fb915793906
diff --git a/res/layout/browser_add_bookmark.xml b/res/layout/browser_add_bookmark.xml
index f15caf2..e22e820 100644
--- a/res/layout/browser_add_bookmark.xml
+++ b/res/layout/browser_add_bookmark.xml
@@ -29,11 +29,10 @@
         android:layout_marginLeft="10dip"
         android:layout_marginRight="10dip"/>
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    <RelativeLayout android:id="@+id/default_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:orientation="vertical"
         android:paddingTop="5dip"
         android:paddingBottom="13dip"
         android:paddingLeft="20dip"
@@ -43,6 +42,10 @@
             android:id="@+id/titleText"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_marginRight="50dip"
+            android:layout_marginBottom="40dip"
+            android:layout_marginTop="40dip"
             android:text="@string/name"
             android:gravity="left"
             android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -52,8 +55,11 @@
             android:layout_height="wrap_content"
             android:layout_width="250dip"
             android:gravity="fill_horizontal"
+            android:layout_alignBaseline="@+id/titleText"
+            android:layout_toRightOf="@+id/titleText"
             android:inputType="textCapSentences"
             android:selectAllOnFocus="true"
+            android:ellipsize="end"
             android:textAppearance="?android:attr/textAppearanceMedium" />
                 
 
@@ -64,6 +70,10 @@
             android:layout_width="wrap_content"
             android:text="@string/location"
             android:gravity="left"
+            android:layout_below="@+id/titleText"
+            android:layout_alignLeft="@+id/titleText"
+            android:layout_marginBottom="40dip"
+            android:layout_marginRight="20dip"
             android:textAppearance="?android:attr/textAppearanceMedium" />
                 
         <EditText
@@ -71,12 +81,73 @@
             android:layout_height="wrap_content"
             android:layout_width="250dip"
             android:hint="@string/http"
+            android:layout_alignBaseline="@+id/addressText"
+            android:layout_alignLeft="@+id/title"
             android:gravity="fill_horizontal"
             android:inputType="textUri"
             android:selectAllOnFocus="true"
+            android:ellipsize="end"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView
+            android:id="@+id/add_to"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:text="@string/containing_folder"
+            android:layout_below="@+id/addressText"
+            android:layout_alignLeft="@+id/titleText"
+            android:layout_marginRight="20dip"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <TextView
+            android:id="@+id/folder"
+            android:layout_height="wrap_content"
+            android:layout_width="250dip"
+            android:layout_alignLeft="@+id/title"
+            android:layout_alignBaseline="@+id/add_to"
+            android:singleLine="true"
+            android:ellipsize="start"
+            android:text="@string/bookmarks"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    </RelativeLayout>
+
+    <LinearLayout android:id="@+id/folder_selector"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:visibility="gone"
+        >
+
+        <TextView
+            android:id="@+id/path"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="start"
+            android:text="@string/bookmarks"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <ListView
+            android:id="@+id/list"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            />
+        <EditText
+            android:id="@+id/folder_namer"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone"
+            />
+        <Button
+            android:id="@+id/add_new_folder"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:text="@string/add_new_folder"
             android:textAppearance="?android:attr/textAppearanceMedium" />
     </LinearLayout>
-        
+
     <LinearLayout 
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -102,4 +173,3 @@
     </LinearLayout>
 
 </LinearLayout>
-
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cbd9bbc..3ceec67 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -122,14 +122,22 @@
     <!-- Button label to cancel saving a bookmark. -->
     <string name="do_not_save">Cancel</string>
     <!-- Field label in Bookmark dialog box: refers to URL of the page to bookmark -->
-    <string name="location">Location</string>
+    <string name="location">Address</string>
+    <!-- Field label in Bookmark dialog box: refers to the folder in which to save the bookmark -->
+    <string name="containing_folder">Add to</string>
+    <!-- Button text for a button that allows the user to add a new folder.  Also used as the title of the add bookmarks dialog on the page
+         that allows choosing the folder to place it in. -->
+    <string name="add_new_folder">Add new folder</string>
+    <!-- Default name for a new folder -->
+    <string name="new_folder">New folder</string>
     <!-- Field label in Bookmark dialog box: title that the user wishes to use for the bookmark -->
-    <string name="name">Name</string>
+    <string name="name">label</string>
     <!-- Initial value in Location field in Bookmark dialog box -->
     <string name="http">http://</string>
-    <!-- Menu item that opens a dialog to save a bookmark for the current page, also displayed as
-            the title of the dialog used for adding a bookmark -->
-    <string name="save_to_bookmarks">Bookmark this page</string>
+    <!-- Menu item that opens a dialog to save a bookmark for the current page -->
+    <string name="save_to_bookmarks">Add to Bookmarks</string>
+    <!-- Title of the dialog to bookmark a page -->
+    <string name="bookmark_this_page">Bookmark this page</string>
     <!-- Menu item on the bookmarks page, to edit an existing bookmark -->
     <string name="edit_bookmark">Edit bookmark</string>
     <!-- Context menu item to create a shortcut to the bookmark on the desktop -->
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 1d6edc5..2a252a7 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -17,8 +17,13 @@
 package com.android.browser;
 
 import android.app.Activity;
+import android.app.LoaderManager;
 import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.CursorLoader;
 import android.content.Intent;
+import android.content.Loader;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -27,21 +32,38 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.provider.Browser;
+import android.provider.BrowserContract;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Window;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.CursorAdapter;
 import android.widget.EditText;
+import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.Date;
 
-public class AddBookmarkPage extends Activity {
+import android.util.Log;
+
+public class AddBookmarkPage extends Activity
+        implements View.OnClickListener, TextView.OnEditorActionListener,
+        AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {
 
     private final String LOGTAG = "Bookmarks";
 
+    // IDs for the CursorLoaders that are used.
+    private final int LOADER_ID_FOLDER_CONTENTS = 0;
+    private final int LOADER_ID_ALL_FOLDERS = 1;
+
     private EditText    mTitle;
     private EditText    mAddress;
     private TextView    mButton;
@@ -51,43 +73,223 @@
     private String      mTouchIconUrl;
     private Bitmap      mThumbnail;
     private String      mOriginalUrl;
-    private boolean     mIsUrlEditable = true;
+    private TextView mFolder;
+    private View mDefaultView;
+    private View mFolderSelector;
+    private EditText mFolderNamer;
+    private View mAddNewFolder;
+    private long mCurrentFolder = 0;
+    private FolderAdapter mAdapter;
+    private ArrayList<Folder> mPaths;
+    private TextView    mPath;
+
+    private static class Folder {
+        String Name;
+        long Id;
+        Folder(String name, long id) {
+            Name = name;
+            Id = id;
+        }
+    }
 
     // Message IDs
     private static final int SAVE_BOOKMARK = 100;
 
     private Handler mHandler;
 
-    private View.OnClickListener mSaveBookmark = new View.OnClickListener() {
-        public void onClick(View v) {
-            if (save()) {
-                finish();
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        if (v == mFolderNamer) {
+            if (v.getText().length() > 0) {
+                if (actionId == EditorInfo.IME_NULL) {
+                    // Only want to do this once.
+                    if (event.getAction() == KeyEvent.ACTION_UP) {
+                        // Add the folder to the database
+                        ContentValues values = new ContentValues();
+                        values.put(BrowserContract.Bookmarks.TITLE,
+                                v.getText().toString());
+                        values.put(BrowserContract.Bookmarks.IS_FOLDER, 1);
+                        values.put(BrowserContract.Bookmarks.PARENT,
+                                mCurrentFolder);
+                        getContentResolver().insert(
+                                BrowserContract.Bookmarks.CONTENT_URI, values);
+
+                        mFolderNamer.setVisibility(View.GONE);
+                        InputMethodManager.getInstance(this)
+                                .hideSoftInputFromWindow(
+                                mFolderNamer.getWindowToken(), 0);
+                    }
+                    // Steal the key press for both up and down
+                    return true;
+                }
             }
         }
-    };
+        return false;
+    }
 
-    private View.OnClickListener mCancel = new View.OnClickListener() {
-        public void onClick(View v) {
+    @Override
+    public void onClick(View v) {
+        if (v == mButton) {
+            if (mFolderSelector.getVisibility() == View.VISIBLE) {
+                // We are showing the folder selector.  This means that the user
+                // has selected a folder.  Go back to the opening page
+                mFolderSelector.setVisibility(View.GONE);
+                mDefaultView.setVisibility(View.VISIBLE);
+                setTitle(R.string.bookmark_this_page);
+            } else if (save()) {
+                finish();
+            }
+        } else if (v == mCancelButton) {
             finish();
+        } else if (v == mFolder) {
+            switchToFolderSelector();
+        } else if (v == mAddNewFolder) {
+            mFolderNamer.setVisibility(View.VISIBLE);
+            mFolderNamer.setText(R.string.new_folder);
+            mFolderNamer.requestFocus();
+            InputMethodManager.getInstance(this).showSoftInput(mFolderNamer,
+                    InputMethodManager.SHOW_IMPLICIT);
         }
-    };
+    }
+
+    private void switchToFolderSelector() {
+        mDefaultView.setVisibility(View.GONE);
+        mFolderSelector.setVisibility(View.VISIBLE);
+        setTitle(R.string.containing_folder);
+    }
+
+    @Override
+    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+        String[] projection;
+        switch (id) {
+            case LOADER_ID_ALL_FOLDERS:
+                projection = new String[] {
+                        BrowserContract.Bookmarks._ID,
+                        BrowserContract.Bookmarks.PARENT,
+                        BrowserContract.Bookmarks.TITLE,
+                        BrowserContract.Bookmarks.IS_FOLDER
+                };
+                return new CursorLoader(this,
+                        BrowserContract.Bookmarks.CONTENT_URI,
+                        projection,
+                        BrowserContract.Bookmarks.IS_FOLDER + " != 0",
+                        null,
+                        null);
+            case LOADER_ID_FOLDER_CONTENTS:
+                projection = new String[] {
+                        BrowserContract.Bookmarks._ID,
+                        BrowserContract.Bookmarks.TITLE,
+                        BrowserContract.Bookmarks.IS_FOLDER
+                };
+
+                return new CursorLoader(this,
+                        BrowserContract.Bookmarks.buildFolderUri(
+                        mCurrentFolder),
+                        projection,
+                        BrowserContract.Bookmarks.IS_FOLDER + " != 0",
+                        null,
+                        null);
+            default:
+                throw new AssertionError("Asking for nonexistant loader!");
+        }
+    }
+
+    @Override
+    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+        switch (loader.getId()) {
+            case LOADER_ID_FOLDER_CONTENTS:
+                mAdapter.changeCursor(cursor);
+                break;
+            case LOADER_ID_ALL_FOLDERS:
+                long parent = mCurrentFolder;
+                int idIndex = cursor.getColumnIndexOrThrow(
+                        BrowserContract.Bookmarks._ID);
+                int titleIndex = cursor.getColumnIndexOrThrow(
+                        BrowserContract.Bookmarks.TITLE);
+                int parentIndex = cursor.getColumnIndexOrThrow(
+                        BrowserContract.Bookmarks.PARENT);
+                while (parent != 0) {
+                    // First, find the folder corresponding to the current
+                    // folder
+                    if (!cursor.moveToFirst()) {
+                        throw new AssertionError("No folders in the database!");
+                    }
+                    long folder;
+                    do {
+                        folder = cursor.getLong(idIndex);
+                    } while (folder != parent && cursor.moveToNext());
+                    if (cursor.isAfterLast()) {
+                        throw new AssertionError("Folder(id=" + parent
+                                + ") holding this bookmark does not exist!");
+                    }
+                    String name = cursor.getString(titleIndex);
+                    mPaths.add(1, new Folder(name, parent));
+                    parent = cursor.getLong(parentIndex);
+                }
+                getLoaderManager().stopLoader(LOADER_ID_ALL_FOLDERS);
+                updatePathString();
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Update the TextViews in both modes to display the full path of the
+     * current location to insert.
+     */
+    private void updatePathString() {
+        String path = mPaths.get(0).Name;
+        int size = mPaths.size();
+        for (int i = 1; i < size; i++) {
+            path += " / " + mPaths.get(i).Name;
+        }
+        mPath.setText(path);
+        mFolder.setText(path);
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position,
+            long id) {
+        // Switch to the folder that was clicked on.
+        mCurrentFolder = id;
+        mPaths.add(new Folder(((TextView) view).getText().toString(), id));
+        updatePathString();
+
+        getLoaderManager().restartLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+    }
+
+    /**
+     * Shows a list of names of folders.
+     */
+    private class FolderAdapter extends CursorAdapter {
+        public FolderAdapter(Context context) {
+            super(context, null);
+        }
+
+        @Override
+        public void bindView(View view, Context context, Cursor cursor) {
+            ((TextView) view.findViewById(android.R.id.text1)).setText(
+                    cursor.getString(cursor.getColumnIndexOrThrow(
+                    BrowserContract.Bookmarks.TITLE)));
+        }
+
+        @Override
+        public View newView(Context context, Cursor cursor, ViewGroup parent) {
+            return LayoutInflater.from(context).inflate(
+                    android.R.layout.simple_list_item_1, null);
+        }
+    }
 
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         requestWindowFeature(Window.FEATURE_LEFT_ICON);
 
         mMap = getIntent().getExtras();
-        if (mMap != null) {
-            mIsUrlEditable = mMap.getBoolean("url_editable", true);
-        }
 
-        if (mIsUrlEditable) {
-            setContentView(R.layout.browser_add_bookmark);
-        } else {
-            setContentView(R.layout.browser_add_bookmark_const_url);
-        }
+        setContentView(R.layout.browser_add_bookmark);
 
-        setTitle(R.string.save_to_bookmarks);
+        setTitle(R.string.bookmark_this_page);
         getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_list_bookmark);
         
         String title = null;
@@ -104,32 +306,82 @@
             url = mOriginalUrl = mMap.getString("url");
             mTouchIconUrl = mMap.getString("touch_icon_url");
             mThumbnail = (Bitmap) mMap.getParcelable("thumbnail");
+            mCurrentFolder = mMap.getLong(BrowserContract.Bookmarks.PARENT);
         }
 
         mTitle = (EditText) findViewById(R.id.title);
         mTitle.setText(title);
 
-        if (mIsUrlEditable) {
-            mAddress = (EditText) findViewById(R.id.address);
-            mAddress.setText(url);
-        }
+        mAddress = (EditText) findViewById(R.id.address);
+        mAddress.setText(url);
 
-        View.OnClickListener accept = mSaveBookmark;
         mButton = (TextView) findViewById(R.id.OK);
-        mButton.setOnClickListener(accept);
+        mButton.setOnClickListener(this);
 
         mCancelButton = findViewById(R.id.cancel);
-        mCancelButton.setOnClickListener(mCancel);
+        mCancelButton.setOnClickListener(this);
+
+        mFolder = (TextView) findViewById(R.id.folder);
+        mFolder.setOnClickListener(this);
+
+        mDefaultView = findViewById(R.id.default_view);
+        mFolderSelector = findViewById(R.id.folder_selector);
+
+        mFolderNamer = (EditText) findViewById(R.id.folder_namer);
+        mFolderNamer.setOnEditorActionListener(this);
+
+        mAddNewFolder = findViewById(R.id.add_new_folder);
+        mAddNewFolder.setOnClickListener(this);
+
+        mPath = (TextView) findViewById(R.id.path);
+                ListView list = (ListView) findViewById(R.id.list);
+
+        mPaths = new ArrayList<Folder>();
+        mPaths.add(0, new Folder(getString(R.string.bookmarks), 0));
+        mAdapter = new FolderAdapter(this);
+        list.setAdapter(mAdapter);
+        list.setOnItemClickListener(this);
+        LoaderManager manager = getLoaderManager();
+        if (mCurrentFolder != 0) {
+            // Find all the folders
+            manager.initLoader(LOADER_ID_ALL_FOLDERS, null, this);
+        }
+        manager.initLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+
         
         if (!getWindow().getDecorView().isInTouchMode()) {
             mButton.requestFocus();
         }
     }
 
+    @Override
+    public boolean dispatchKeyEvent (KeyEvent event) {
+        if (mFolderSelector.getVisibility() == View.VISIBLE
+                && KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
+            if (KeyEvent.ACTION_UP == event.getAction()) {
+                int size = mPaths.size();
+                if (1 == size) {
+                    // We have reached the top level
+                    finish();
+                } else {
+                    // Go up a level
+                    mPaths.remove(size - 1);
+                    mCurrentFolder = mPaths.get(size - 2).Id;
+                    updatePathString();
+                    getLoaderManager().restartLoader(LOADER_ID_FOLDER_CONTENTS,
+                            null, this);
+                }
+            }
+            return true;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
     /**
      * Runnable to save a bookmark, so it can be performed in its own thread.
      */
     private class SaveBookmarkRunnable implements Runnable {
+        // FIXME: This should be an async task.
         private Message mMessage;
         public SaveBookmarkRunnable(Message msg) {
             mMessage = msg;
@@ -148,7 +400,8 @@
             // Save to the bookmarks DB.
             try {
                 final ContentResolver cr = getContentResolver();
-                Bookmarks.addBookmark(AddBookmarkPage.this, false, url, title, thumbnail, true);
+                Bookmarks.addBookmark(AddBookmarkPage.this, false, url,
+                        title, thumbnail, true, mCurrentFolder);
                 if (touchIconUrl != null) {
                     new DownloadTouchIcon(AddBookmarkPage.this, cr, url).execute(mTouchIconUrl);
                 }
@@ -189,12 +442,7 @@
 
         String title = mTitle.getText().toString().trim();
         String unfilteredUrl;
-        if (mIsUrlEditable) {
-            unfilteredUrl =
-                    BrowserActivity.fixUrl(mAddress.getText().toString());
-        } else {
-            unfilteredUrl = mOriginalUrl;
-        }
+        unfilteredUrl = BrowserActivity.fixUrl(mAddress.getText().toString());
 
         boolean emptyTitle = title.length() == 0;
         boolean emptyUrl = unfilteredUrl.trim().length() == 0;
@@ -204,12 +452,7 @@
                 mTitle.setError(r.getText(R.string.bookmark_needs_title));
             }
             if (emptyUrl) {
-                if (mIsUrlEditable) {
-                    mAddress.setError(r.getText(R.string.bookmark_needs_url));
-                } else {
-                    Toast.makeText(AddBookmarkPage.this, R.string.bookmark_needs_url,
-                            Toast.LENGTH_LONG).show();
-                }
+                mAddress.setError(r.getText(R.string.bookmark_needs_url));
             }
             return false;
 
@@ -227,12 +470,7 @@
                     // can't save their bookmark. If it was null, we'll assume
                     // they meant http when we parse it in the WebAddress class.
                     if (scheme != null) {
-                        if (mIsUrlEditable) {
-                            mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
-                        } else {
-                            Toast.makeText(AddBookmarkPage.this, R.string.bookmark_cannot_save_url,
-                                    Toast.LENGTH_LONG).show();
-                        }
+                        mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
                         return false;
                     }
                     WebAddress address;
@@ -248,12 +486,7 @@
                 }
             }
         } catch (URISyntaxException e) {
-            if (mIsUrlEditable) {
-                mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
-            } else {
-                Toast.makeText(AddBookmarkPage.this, R.string.bookmark_url_not_valid,
-                        Toast.LENGTH_LONG).show();
-            }
+            mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
             return false;
         }
 
@@ -261,6 +494,8 @@
             mMap.putString("title", title);
             mMap.putString("url", url);
             mMap.putBoolean("invalidateThumbnail", !url.equals(mOriginalUrl));
+            // FIXME: This does not work yet
+            mMap.putLong(BrowserContract.Bookmarks.PARENT, mCurrentFolder);
             setResult(RESULT_OK, (new Intent()).setAction(
                     getIntent().toString()).putExtras(mMap));
         } else {
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index 0bccbed..383ae7f 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -57,19 +57,18 @@
      *  @param context Context of the calling Activity.  This is used to make
      *          Toast confirming that the bookmark has been added.  If the
      *          caller provides null, the Toast will not be shown.
-     *  @param cr The ContentResolver being used to add the bookmark to the db.
      *  @param url URL of the website to be bookmarked.
      *  @param name Provided name for the bookmark.
      *  @param thumbnail A thumbnail for the bookmark.
      *  @param retainIcon Whether to retain the page's icon in the icon database.
      *          This will usually be <code>true</code> except when bookmarks are
      *          added by a settings restore agent.
+     *  @param parent ID of the parent folder.
      */
     /* package */ static void addBookmark(Context context, boolean showToast, String url,
-            String name, Bitmap thumbnail, boolean retainIcon) {
+            String name, Bitmap thumbnail, boolean retainIcon, long parent) {
         // Want to append to the beginning of the list
         ContentValues values = new ContentValues();
-        Cursor cursor = null;
         try {
             SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
             String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
@@ -81,11 +80,10 @@
             values.put(BrowserContract.Bookmarks.IS_FOLDER, 0);
             values.put(BrowserContract.Bookmarks.THUMBNAIL,
                     bitmapToBytes(thumbnail));
+            values.put(BrowserContract.Bookmarks.PARENT, parent);
             context.getContentResolver().insert(BrowserContract.Bookmarks.CONTENT_URI, values);
         } catch (IllegalStateException e) {
             Log.e(LOGTAG, "addBookmark", e);
-        } finally {
-            if (cursor != null) cursor.close();
         }
         if (retainIcon) {
             WebIconDatabase.getInstance().retainIconForPageUrl(url);
diff --git a/src/com/android/browser/BookmarksLoader.java b/src/com/android/browser/BookmarksLoader.java
index 0947184..770ca60 100644
--- a/src/com/android/browser/BookmarksLoader.java
+++ b/src/com/android/browser/BookmarksLoader.java
@@ -33,6 +33,7 @@
     public static final int COLUMN_INDEX_THUMBNAIL = 4;
     public static final int COLUMN_INDEX_TOUCH_ICON = 5;
     public static final int COLUMN_INDEX_IS_FOLDER = 6;
+    public static final int COLUMN_INDEX_PARENT = 8;
 
     public static final String[] PROJECTION = new String[] {
         Bookmarks._ID, // 0
@@ -43,6 +44,7 @@
         Bookmarks.TOUCH_ICON, // 5
         Bookmarks.IS_FOLDER, // 6
         Bookmarks.POSITION, // 7
+        Bookmarks.PARENT, // 8
     };
 
     private String mAccountType;
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index c3d3d9c..9a29357 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -1527,7 +1527,6 @@
         i.putExtra("touch_icon_url", w.getTouchIconUrl());
         i.putExtra("thumbnail", createScreenshot(w, getDesiredThumbnailWidth(this),
                 getDesiredThumbnailHeight(this)));
-        i.putExtra("url_editable", false);
         startActivity(i);
     }
 
diff --git a/src/com/android/browser/BrowserBackupAgent.java b/src/com/android/browser/BrowserBackupAgent.java
index fb1933f..9c5d65b 100644
--- a/src/com/android/browser/BrowserBackupAgent.java
+++ b/src/com/android/browser/BrowserBackupAgent.java
@@ -166,8 +166,11 @@
                                 if (DEBUG) Log.v(TAG, "Did not see url: " + mark.url);
                                 // Right now we do not reconstruct the db entry in its
                                 // entirety; we just add a new bookmark with the same data
+                                // FIXME: This file needs to be reworked
+                                // anyway For now, add the bookmark at
+                                // the root level.
                                 Bookmarks.addBookmark(this, false,
-                                        mark.url, mark.title, null, false);
+                                        mark.url, mark.title, null, false, 0);
                                 nUnique++;
                             } else {
                                 if (DEBUG) Log.v(TAG, "Skipping extant url: " + mark.url);
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index ba1321a..a36bd08 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -538,6 +538,8 @@
                     BitmapFactory.decodeByteArray(data, 0, data.length));
         }
         item.putInt("id", cursor.getInt(BookmarksLoader.COLUMN_INDEX_ID));
+        item.putLong(BrowserContract.Bookmarks.PARENT,
+                cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT));
         intent.putExtra("bookmark", item);
         startActivityForResult(intent, BOOKMARKS_SAVE);
     }
diff --git a/src/com/android/browser/HistoryItem.java b/src/com/android/browser/HistoryItem.java
index b591b03..a03c29f 100644
--- a/src/com/android/browser/HistoryItem.java
+++ b/src/com/android/browser/HistoryItem.java
@@ -41,7 +41,9 @@
             public void onCheckedChanged(CompoundButton buttonView,
                     boolean isChecked) {
                 if (isChecked) {
-                    Bookmarks.addBookmark(mContext, true, mUrl, getName(), null, true);
+                    // FIXME: For now, add at the root level.  Should we
+                    // open AddBookmark from here?
+                    Bookmarks.addBookmark(mContext, true, mUrl, getName(), null, true, 0);
                     LogTag.logBookmarkAdded(mUrl, "history");
                 } else {
                     Bookmarks.removeFromBookmarks(mContext,