AddBookmarkPage.java revision e89daa99d144e8cba904f3733147daea093875cc
10c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project/*
20c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
30c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
40c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
50c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * you may not use this file except in compliance with the License.
60c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * You may obtain a copy of the License at
70c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
80c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
90c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project *
100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
120c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * See the License for the specific language governing permissions and
140c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project * limitations under the License.
150c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project */
160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectpackage com.android.browser;
180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
1925230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scrogginsimport com.android.browser.provider.BrowserProvider2;
2025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins
210c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.app.Activity;
22052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.app.LoaderManager;
230c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.ContentResolver;
24d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolbimport android.content.ContentUris;
25052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.content.ContentValues;
26052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.content.Context;
27052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.content.CursorLoader;
280c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.Intent;
29052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.content.Loader;
3025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scrogginsimport android.content.SharedPreferences;
310c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.content.res.Resources;
323918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.database.Cursor;
33aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdochimport android.graphics.Bitmap;
340c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.net.ParseException;
35d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolbimport android.net.Uri;
360c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.net.WebAddress;
370c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.os.Bundle;
381794fe252866c311f3b4700a2a1e44e843962243Ben Murdochimport android.os.Handler;
391794fe252866c311f3b4700a2a1e44e843962243Ben Murdochimport android.os.Message;
4025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scrogginsimport android.preference.PreferenceManager;
41052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.provider.BrowserContract;
4225230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scrogginsimport android.text.TextUtils;
43052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.view.KeyEvent;
44052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.view.LayoutInflater;
4588d080394ca18120e05c6926b178fd6843ff9cecLeon Scrogginsimport android.view.MenuItem;
460c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.View;
47052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.view.ViewGroup;
480c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.view.Window;
4976a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins IIIimport android.view.WindowManager;
50052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.view.inputmethod.EditorInfo;
51052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.view.inputmethod.InputMethodManager;
52052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.widget.AdapterView;
53052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.widget.CursorAdapter;
540c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.widget.EditText;
55052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport android.widget.ListView;
5688d080394ca18120e05c6926b178fd6843ff9cecLeon Scrogginsimport android.widget.PopupMenu;
570c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.widget.TextView;
580c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Projectimport android.widget.Toast;
590c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
60f2407c682fafef77d568deba9987b193a5f2d361Cary Clarkimport java.net.URI;
61f2407c682fafef77d568deba9987b193a5f2d361Cary Clarkimport java.net.URISyntaxException;
62052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIimport java.util.ArrayList;
6374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scrogginsimport java.util.Stack;
64052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
65052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins IIIpublic class AddBookmarkPage extends Activity
66052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        implements View.OnClickListener, TextView.OnEditorActionListener,
6774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor>,
6888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        BreadCrumbView.Controller, PopupMenu.OnMenuItemClickListener {
690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
70370a4f3e47b740fd10b9028aae9e87e17254caa8Michael Kolb    public static final long DEFAULT_FOLDER_ID = -1;
71bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins    public static final String TOUCH_ICON_URL = "touch_icon_url";
72bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins    // Place on an edited bookmark to remove the saved thumbnail
73bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins    public static final String REMOVE_THUMBNAIL = "remove_thumbnail";
74bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins    public static final String USER_AGENT = "user_agent";
75370a4f3e47b740fd10b9028aae9e87e17254caa8Michael Kolb
7674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    private static final int MAX_CRUMBS_SHOWN = 2;
7774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins
780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private final String LOGTAG = "Bookmarks";
7974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    // Set to true to see the crash on the code I would like to run.
8074dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    private final boolean DEBUG_CRASH = false;
810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
82052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    // IDs for the CursorLoaders that are used.
83052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private final int LOADER_ID_FOLDER_CONTENTS = 0;
84052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private final int LOADER_ID_ALL_FOLDERS = 1;
85052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private EditText    mTitle;
870c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private EditText    mAddress;
880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private TextView    mButton;
890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private View        mCancelButton;
900c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private boolean     mEditingExisting;
910c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    private Bundle      mMap;
923918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    private String      mTouchIconUrl;
93aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch    private String      mOriginalUrl;
94052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private TextView mFolder;
95052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private View mDefaultView;
96052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private View mFolderSelector;
97052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private EditText mFolderNamer;
98052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private View mAddNewFolder;
997e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins    private View mAddSeparator;
100052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private long mCurrentFolder = 0;
101052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private FolderAdapter mAdapter;
10274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    private BreadCrumbView mCrumbs;
1037e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins    private TextView mFakeTitle;
1047e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins    private View mCrumbHolder;
1056573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    private ListView mListView;
10688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins    private boolean mSaveToHomeScreen;
107052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
108052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private static class Folder {
109052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        String Name;
110052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        long Id;
111052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        Folder(String name, long id) {
112052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            Name = name;
113052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            Id = id;
114052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
115052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
1160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
1171794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch    // Message IDs
1181794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch    private static final int SAVE_BOOKMARK = 100;
11988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins    private static final int TOUCH_ICON_DOWNLOADED = 101;
1201794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
1211794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch    private Handler mHandler;
1221794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
123b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert    private InputMethodManager getInputMethodManager() {
124b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert        return (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
125b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert    }
126b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert
127052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    @Override
12874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    public void onTop(int level, Object data) {
12974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        if (null == data) return;
13052f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        Folder folderData = (Folder) data;
13152f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        long folder = folderData.Id;
13252f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        Uri uri = BrowserContract.Bookmarks.buildFolderUri(folder);
13374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        LoaderManager manager = getLoaderManager();
13474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        CursorLoader loader = (CursorLoader) ((Loader) manager.getLoader(
13574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                LOADER_ID_FOLDER_CONTENTS));
13674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        loader.setUri(uri);
13774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        loader.forceLoad();
13874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        updateVisible();
1396573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        if (mFolderNamer.getVisibility() == View.VISIBLE) {
1406573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            completeOrCancelFolderNaming(true);
1416573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        }
14274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    }
14374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins
14474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    /**
14574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins     * Update the views shown to only show the two deepest levels of crumbs.
14674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins     * Note that this method depends on internal knowledge of BreadCrumbView.
14774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins     */
14874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    private void updateVisible() {
14974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins      if (MAX_CRUMBS_SHOWN > 0) {
15074dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          int invisibleCrumbs = mCrumbs.size() - MAX_CRUMBS_SHOWN;
15174dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          // This class always uses a back button, which is the first child.
15274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          int childIndex = 1;
15374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          if (invisibleCrumbs > 0) {
15474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins              int crumbIndex = 0;
15574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins              while (crumbIndex < invisibleCrumbs) {
15674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  // Set the crumb to GONE.
15774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  mCrumbs.getChildAt(childIndex).setVisibility(View.GONE);
15874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  childIndex++;
15974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  // Each crumb is followed by a separator (except the last
16074dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  // one).  Also make it GONE
16174dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  mCrumbs.getChildAt(childIndex).setVisibility(View.GONE);
16274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  childIndex++;
16374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  // Move to the next crumb.
16474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                  crumbIndex++;
16574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins              }
16674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          }
16774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          // Make sure the last two are visible.
16874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          int childCount = mCrumbs.getChildCount();
16974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          while (childIndex < childCount) {
17074dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins              mCrumbs.getChildAt(childIndex).setVisibility(View.VISIBLE);
17174dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins              childIndex++;
17274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins          }
17374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins      }
17474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    }
17574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins
17674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins    @Override
177052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
178052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        if (v == mFolderNamer) {
179052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            if (v.getText().length() > 0) {
180052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                if (actionId == EditorInfo.IME_NULL) {
181052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    // Only want to do this once.
182052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    if (event.getAction() == KeyEvent.ACTION_UP) {
1836573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins                        completeOrCancelFolderNaming(false);
184052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    }
185052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                }
1860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
18731829b941ca8ac02a828619440cb62b64673caa8Michael Kolb            // Steal the key press; otherwise a newline will be added
18831829b941ca8ac02a828619440cb62b64673caa8Michael Kolb            return true;
1890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
190052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        return false;
191052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
1920c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
19352f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins    private void switchToDefaultView(boolean changedFolder) {
19452f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mFolderSelector.setVisibility(View.GONE);
19552f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mDefaultView.setVisibility(View.VISIBLE);
19652f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mCrumbHolder.setVisibility(View.GONE);
19752f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mFakeTitle.setVisibility(View.VISIBLE);
19852f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        if (changedFolder) {
19952f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            Object data = mCrumbs.getTopData();
20052f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            if (data != null) {
20152f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                Folder folder = (Folder) data;
20252f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                mCurrentFolder = folder.Id;
20352f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                mFolder.setText(folder.Name);
20452f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            }
20552f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        }
20652f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins    }
20752f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins
208052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    @Override
209052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    public void onClick(View v) {
210052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        if (v == mButton) {
211052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            if (mFolderSelector.getVisibility() == View.VISIBLE) {
21252f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                // We are showing the folder selector.
213d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                if (mFolderNamer.getVisibility() == View.VISIBLE) {
2146573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins                    completeOrCancelFolderNaming(false);
215d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                } else {
216d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                    // User has selected a folder.  Go back to the opening page
21788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    mSaveToHomeScreen = false;
21852f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                    switchToDefaultView(true);
219d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                }
220052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            } else if (save()) {
221052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                finish();
222052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            }
223052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        } else if (v == mCancelButton) {
224d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            if (mFolderNamer.getVisibility() == View.VISIBLE) {
2256573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins                completeOrCancelFolderNaming(true);
22652f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            } else if (mFolderSelector.getVisibility() == View.VISIBLE) {
22752f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                switchToDefaultView(false);
228d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            } else {
229d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                finish();
230d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            }
231052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        } else if (v == mFolder) {
23226318a1383d4bbe6dc210a964354bf42d1ef4776Leon Scroggins            PopupMenu popup = new PopupMenu(this, mFolder);
23388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            popup.getMenuInflater().inflate(R.menu.folder_choice,
23488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    popup.getMenu());
23588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            popup.setOnMenuItemClickListener(this);
23688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            popup.show();
237052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        } else if (v == mAddNewFolder) {
238052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            mFolderNamer.setVisibility(View.VISIBLE);
239052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            mFolderNamer.setText(R.string.new_folder);
240052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            mFolderNamer.requestFocus();
2416573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            updateList();
242d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            mAddNewFolder.setVisibility(View.GONE);
2437e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins            mAddSeparator.setVisibility(View.GONE);
244b1402a5c3e1617867c58d32d1fe9782cf6de423fBjorn Bringert            getInputMethodManager().showSoftInput(mFolderNamer,
245052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    InputMethodManager.SHOW_IMPLICIT);
246052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
247052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
248052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
24988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins    @Override
25088d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins    public boolean onMenuItemClick(MenuItem item) {
25188d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        switch(item.getItemId()) {
25288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            case R.id.bookmarks:
25388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                mCurrentFolder = getBookmarksBarId(this);
25488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                mFolder.setText(item.getTitle());
25588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                mSaveToHomeScreen = false;
25688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                break;
25788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            case R.id.home_screen:
25888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                // Create a short cut to the home screen
25988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                mSaveToHomeScreen = true;
26088d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                mFolder.setText(item.getTitle());
26188d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                break;
26288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            case R.id.other:
26388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                switchToFolderSelector();
26488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                break;
26588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            default:
26688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                return false;
26788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        }
26888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        return true;
26988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins    }
27088d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins
2716573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    // Refresh the ListView to hide or show the empty view, as necessary.
2726573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    // Should be called after mFolderNamer is shown or hidden.
2736573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    private void updateList() {
2746573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        if (mAdapter.getCount() == 0) {
2756573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            // XXX: Is there a better way to refresh the ListView?
2766573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            mListView.setAdapter(mAdapter);
2776573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        }
2786573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    }
2796573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins
2806573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins    private void completeOrCancelFolderNaming(boolean cancel) {
2816573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        if (!cancel && !TextUtils.isEmpty(mFolderNamer.getText())) {
28231829b941ca8ac02a828619440cb62b64673caa8Michael Kolb            String name = mFolderNamer.getText().toString();
28331829b941ca8ac02a828619440cb62b64673caa8Michael Kolb            long id = addFolderToCurrent(mFolderNamer.getText().toString());
28431829b941ca8ac02a828619440cb62b64673caa8Michael Kolb            descendInto(name, id);
28531829b941ca8ac02a828619440cb62b64673caa8Michael Kolb        }
2866573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mFolderNamer.setVisibility(View.GONE);
2876573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mAddNewFolder.setVisibility(View.VISIBLE);
2886573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mAddSeparator.setVisibility(View.VISIBLE);
2896573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        getInputMethodManager().hideSoftInputFromWindow(
2906573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins                mFolderNamer.getWindowToken(), 0);
2916573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        updateList();
29231829b941ca8ac02a828619440cb62b64673caa8Michael Kolb    }
29331829b941ca8ac02a828619440cb62b64673caa8Michael Kolb
294d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb    private long addFolderToCurrent(String name) {
295d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        // Add the folder to the database
296d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        ContentValues values = new ContentValues();
297d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        values.put(BrowserContract.Bookmarks.TITLE,
298d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                name);
299d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        values.put(BrowserContract.Bookmarks.IS_FOLDER, 1);
300e89daa99d144e8cba904f3733147daea093875ccJohn Reck        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
301e89daa99d144e8cba904f3733147daea093875ccJohn Reck        String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
302e89daa99d144e8cba904f3733147daea093875ccJohn Reck        String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
303e89daa99d144e8cba904f3733147daea093875ccJohn Reck        if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
304e89daa99d144e8cba904f3733147daea093875ccJohn Reck            values.put(BrowserContract.Bookmarks.ACCOUNT_TYPE, accountType);
305e89daa99d144e8cba904f3733147daea093875ccJohn Reck            values.put(BrowserContract.Bookmarks.ACCOUNT_NAME, accountName);
306e89daa99d144e8cba904f3733147daea093875ccJohn Reck        }
30752f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        long currentFolder;
30852f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        Object data = mCrumbs.getTopData();
30952f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        if (data != null) {
31052f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            currentFolder = ((Folder) data).Id;
31152f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        } else {
31252f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            currentFolder = getBookmarksBarId(this);
31352f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        }
31452f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        values.put(BrowserContract.Bookmarks.PARENT, currentFolder);
315d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        Uri uri = getContentResolver().insert(
316d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                BrowserContract.Bookmarks.CONTENT_URI, values);
317d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        if (uri != null) {
318d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            return ContentUris.parseId(uri);
319d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        } else {
320d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            return -1;
321d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        }
322d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb    }
323d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb
324052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private void switchToFolderSelector() {
325052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mDefaultView.setVisibility(View.GONE);
326052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolderSelector.setVisibility(View.VISIBLE);
3277e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mCrumbHolder.setVisibility(View.VISIBLE);
3287e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mFakeTitle.setVisibility(View.GONE);
3297e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mAddNewFolder.setVisibility(View.VISIBLE);
3307e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mAddSeparator.setVisibility(View.VISIBLE);
331052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
332052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
333d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb    private void descendInto(String foldername, long id) {
334370a4f3e47b740fd10b9028aae9e87e17254caa8Michael Kolb        if (id != DEFAULT_FOLDER_ID) {
33552f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins            mCrumbs.pushView(foldername, new Folder(foldername, id));
33674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins            mCrumbs.notifyController();
337d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb        }
338d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb    }
339d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb
340052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    @Override
341052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
342052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        String[] projection;
343052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        switch (id) {
344052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            case LOADER_ID_ALL_FOLDERS:
345052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                projection = new String[] {
346052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks._ID,
347052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.PARENT,
348052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.TITLE,
349052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.IS_FOLDER
350052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                };
351052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                return new CursorLoader(this,
352052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.CONTENT_URI,
353052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        projection,
354052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.IS_FOLDER + " != 0",
355052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        null,
356052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        null);
357052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            case LOADER_ID_FOLDER_CONTENTS:
358052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                projection = new String[] {
359052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks._ID,
360052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.TITLE,
361052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.IS_FOLDER
362052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                };
363052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                return new CursorLoader(this,
364052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.buildFolderUri(
365052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        mCurrentFolder),
366052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        projection,
367052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.IS_FOLDER + " != 0",
368052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        null,
369052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        null);
370052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            default:
371052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                throw new AssertionError("Asking for nonexistant loader!");
372052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
373052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
374052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
375052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    @Override
376052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
377052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        switch (loader.getId()) {
378052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            case LOADER_ID_FOLDER_CONTENTS:
379052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                mAdapter.changeCursor(cursor);
380052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                break;
381052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            case LOADER_ID_ALL_FOLDERS:
382052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                long parent = mCurrentFolder;
383052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                int idIndex = cursor.getColumnIndexOrThrow(
384052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks._ID);
385052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                int titleIndex = cursor.getColumnIndexOrThrow(
386052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.TITLE);
387052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                int parentIndex = cursor.getColumnIndexOrThrow(
388052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        BrowserContract.Bookmarks.PARENT);
38974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                Stack folderStack = new Stack();
390d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                while ((parent != BrowserProvider2.FIXED_ID_ROOT) &&
391d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                        (parent != 0)) {
392052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    // First, find the folder corresponding to the current
393052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    // folder
394052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    if (!cursor.moveToFirst()) {
395052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        throw new AssertionError("No folders in the database!");
396052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    }
397052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    long folder;
398052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    do {
399052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        folder = cursor.getLong(idIndex);
400052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    } while (folder != parent && cursor.moveToNext());
401052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    if (cursor.isAfterLast()) {
402052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        throw new AssertionError("Folder(id=" + parent
403052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                                + ") holding this bookmark does not exist!");
404052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    }
405052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    String name = cursor.getString(titleIndex);
40652f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                    if (parent == mCurrentFolder) {
40752f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                        mFolder.setText(name);
40852f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                    }
40974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                    folderStack.push(new Folder(name, parent));
410052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    parent = cursor.getLong(parentIndex);
411052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                }
41274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                while (!folderStack.isEmpty()) {
41374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                    Folder thisFolder = (Folder) folderStack.pop();
41452f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                    mCrumbs.pushView(thisFolder.Name, thisFolder);
41574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                }
416052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                getLoaderManager().stopLoader(LOADER_ID_ALL_FOLDERS);
41774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                updateVisible();
418052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                break;
419052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            default:
420052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                break;
421052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
422052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
423052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
424052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    @Override
425052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    public void onItemClick(AdapterView<?> parent, View view, int position,
426052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            long id) {
427d14cb123f8d80896d568104f0f776be8cdc1aa60Leon Scroggins        TextView tv = (TextView) view.findViewById(android.R.id.text1);
428052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        // Switch to the folder that was clicked on.
429d14cb123f8d80896d568104f0f776be8cdc1aa60Leon Scroggins        descendInto(tv.getText().toString(), id);
430052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
431052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
432052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    /**
433052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III     * Shows a list of names of folders.
434052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III     */
435052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    private class FolderAdapter extends CursorAdapter {
436052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        public FolderAdapter(Context context) {
437052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            super(context, null);
4380c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
439052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
440052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        @Override
441052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        public void bindView(View view, Context context, Cursor cursor) {
442052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            ((TextView) view.findViewById(android.R.id.text1)).setText(
443052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    cursor.getString(cursor.getColumnIndexOrThrow(
444052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                    BrowserContract.Bookmarks.TITLE)));
445052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
446052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
447052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        @Override
448052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        public View newView(Context context, Cursor cursor, ViewGroup parent) {
449d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            View view = LayoutInflater.from(context).inflate(
450d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                    R.layout.folder_list_item, null);
451d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            view.setBackgroundDrawable(context.getResources().
452d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb                    getDrawable(android.R.drawable.list_selector_background));
453d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb            return view;
454052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
4556573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins
4566573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        @Override
4576573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        public boolean isEmpty() {
4586573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            // Do not show the empty view if the user is creating a new folder.
4596573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins            return super.isEmpty() && mFolderNamer.getVisibility() == View.GONE;
4606573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        }
461052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III    }
4620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
4630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    protected void onCreate(Bundle icicle) {
4640c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        super.onCreate(icicle);
46574dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        if (DEBUG_CRASH) {
46674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins            requestWindowFeature(Window.FEATURE_NO_TITLE);
46774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        } else {
46874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins            requestWindowFeature(Window.FEATURE_LEFT_ICON);
46974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        }
470eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
471eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch        mMap = getIntent().getExtras();
472eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
473052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        setContentView(R.layout.browser_add_bookmark);
474eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
47576a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III        Window window = getWindow();
47674dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        if (!DEBUG_CRASH) {
47774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins            setTitle(R.string.bookmark_this_page);
47874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins            window.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_list_bookmark);
47974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        }
480d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb
4810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        String title = null;
4820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        String url = null;
483eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
48452f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mFakeTitle = (TextView) findViewById(R.id.fake_title);
48552f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins
4860c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (mMap != null) {
4870c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            Bundle b = mMap.getBundle("bookmark");
4880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            if (b != null) {
4890c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                mMap = b;
4900c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                mEditingExisting = true;
4917e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins                mFakeTitle.setText(R.string.edit_bookmark);
49274dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                if (!DEBUG_CRASH) {
49374dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                    setTitle(R.string.bookmark_this_page);
49474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins                }
49576a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III            } else {
49676a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                int gravity = mMap.getInt("gravity", -1);
49776a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                if (gravity != -1) {
49876a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                    WindowManager.LayoutParams l = window.getAttributes();
49976a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                    l.gravity = gravity;
50076a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                    window.setAttributes(l);
50176a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III                }
5020c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
503bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            title = mMap.getString(BrowserContract.Bookmarks.TITLE);
504bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            url = mOriginalUrl = mMap.getString(BrowserContract.Bookmarks.URL);
505bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            mTouchIconUrl = mMap.getString(TOUCH_ICON_URL);
506370a4f3e47b740fd10b9028aae9e87e17254caa8Michael Kolb            mCurrentFolder = mMap.getLong(BrowserContract.Bookmarks.PARENT, DEFAULT_FOLDER_ID);
50725230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        }
508370a4f3e47b740fd10b9028aae9e87e17254caa8Michael Kolb        if (mCurrentFolder == DEFAULT_FOLDER_ID) {
50925230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins            mCurrentFolder = getBookmarksBarId(this);
5100c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
5110c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
5120c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTitle = (EditText) findViewById(R.id.title);
5130c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mTitle.setText(title);
514eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
515052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mAddress = (EditText) findViewById(R.id.address);
516052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mAddress.setText(url);
5170c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
5180c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mButton = (TextView) findViewById(R.id.OK);
519052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mButton.setOnClickListener(this);
5200c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project
5210c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        mCancelButton = findViewById(R.id.cancel);
522052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mCancelButton.setOnClickListener(this);
523052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
524052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolder = (TextView) findViewById(R.id.folder);
525052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolder.setOnClickListener(this);
526052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
527052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mDefaultView = findViewById(R.id.default_view);
528052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolderSelector = findViewById(R.id.folder_selector);
529052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
530052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolderNamer = (EditText) findViewById(R.id.folder_namer);
531052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mFolderNamer.setOnEditorActionListener(this);
532052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
533052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mAddNewFolder = findViewById(R.id.add_new_folder);
534052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mAddNewFolder.setOnClickListener(this);
5357e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mAddSeparator = findViewById(R.id.add_divider);
536052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
53774dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        mCrumbs = (BreadCrumbView) findViewById(R.id.crumbs);
53874dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        mCrumbs.setUseBackButton(true);
53974dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins        mCrumbs.setController(this);
54052f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        String name = getString(R.string.bookmarks);
54152f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        mCrumbs.pushView(name, false,
54252f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins                new Folder(name, BrowserProvider2.FIXED_ID_ROOT));
5437e5f735150ad3fa89305a32889356ff94e453851Leon Scroggins        mCrumbHolder = findViewById(R.id.crumb_holder);
54474dbe014c9be6ebbba80f1f08aec12d15254fcc7Leon Scroggins
545052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        mAdapter = new FolderAdapter(this);
5466573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mListView = (ListView) findViewById(R.id.list);
5476573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        View empty = findViewById(R.id.empty);
5486573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mListView.setEmptyView(empty);
5496573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mListView.setAdapter(mAdapter);
5506573f9edd734c8dc42251840d6f693058ca4dfd8Leon Scroggins        mListView.setOnItemClickListener(this);
551052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        LoaderManager manager = getLoaderManager();
552a9bad830efad4c098e6f874704dedc005958aedfJeff Hamilton        if (mCurrentFolder != BrowserProvider2.FIXED_ID_ROOT) {
553052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            // Find all the folders
554052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            manager.initLoader(LOADER_ID_ALL_FOLDERS, null, this);
555052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        }
55652f7daafdd225359cca972e766f0ebaba6ae9beeLeon Scroggins        // Find the contents of the current folder
557052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        manager.initLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
558052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III
559d40ac1afadfbba82bc266eebc029f3c99884c9a3Michael Kolb
56076a0e9ce21bc3ad4798f5f76b36b1d514e3595beLeon Scroggins III        if (!window.getDecorView().isInTouchMode()) {
5610c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            mButton.requestFocus();
5620c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
5630c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
5641794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
56525230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins    // FIXME: Use a CursorLoader
56625230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins    private long getBookmarksBarId(Context context) {
56725230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        SharedPreferences prefs
56825230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                = PreferenceManager.getDefaultSharedPreferences(context);
56925230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        String accountName =
57025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
57125230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        String accountType =
57225230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
57325230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
574a9bad830efad4c098e6f874704dedc005958aedfJeff Hamilton            return BrowserProvider2.FIXED_ID_ROOT;
57525230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        }
57625230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        Cursor cursor = null;
57725230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        try {
57825230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins            cursor = context.getContentResolver().query(
57925230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                    BrowserContract.Bookmarks.CONTENT_URI,
58025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                    new String[] { BrowserContract.Bookmarks._ID },
58125230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                    BrowserContract.ChromeSyncColumns.SERVER_UNIQUE + "=? AND "
58225230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                            + BrowserContract.Bookmarks.ACCOUNT_NAME + "=? AND "
58325230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                            + BrowserContract.Bookmarks.ACCOUNT_TYPE + "=?",
58425230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                    new String[] {
58525230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                            BrowserContract.ChromeSyncColumns
58625230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                                    .FOLDER_NAME_BOOKMARKS_BAR,
58725230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                            accountName,
58825230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                            accountType },
58925230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                    null);
59025230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins            if (cursor != null && cursor.moveToFirst()) {
59125230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins                return cursor.getLong(0);
59225230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins            }
59325230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        } finally {
59425230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins            if (cursor != null) cursor.close();
59525230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins        }
596a9bad830efad4c098e6f874704dedc005958aedfJeff Hamilton        return BrowserProvider2.FIXED_ID_ROOT;
59725230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins    }
59825230d7c576c18f40a0feeb7ef8b4a57e2e6240dLeon Scroggins
59902065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins    /**
60002065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins     * Runnable to save a bookmark, so it can be performed in its own thread.
60102065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins     */
60202065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins    private class SaveBookmarkRunnable implements Runnable {
603052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        // FIXME: This should be an async task.
60402065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins        private Message mMessage;
605980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baard        private Context mContext;
606980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baard        public SaveBookmarkRunnable(Context ctx, Message msg) {
607980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baard            mContext = ctx;
60802065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            mMessage = msg;
60902065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins        }
61002065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins        public void run() {
61102065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            // Unbundle bookmark data.
61202065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            Bundle bundle = mMessage.getData();
613bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            String title = bundle.getString(BrowserContract.Bookmarks.TITLE);
614bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            String url = bundle.getString(BrowserContract.Bookmarks.URL);
615bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            boolean invalidateThumbnail = bundle.getBoolean(REMOVE_THUMBNAIL);
61602065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            Bitmap thumbnail = invalidateThumbnail ? null
617bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                    : (Bitmap) bundle.getParcelable(BrowserContract.Bookmarks.THUMBNAIL);
618bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            String touchIconUrl = bundle.getString(TOUCH_ICON_URL);
61902065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins
62002065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            // Save to the bookmarks DB.
62102065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            try {
62202065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                final ContentResolver cr = getContentResolver();
623052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                Bookmarks.addBookmark(AddBookmarkPage.this, false, url,
624052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        title, thumbnail, true, mCurrentFolder);
62502065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                if (touchIconUrl != null) {
626980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baard                    new DownloadTouchIcon(mContext, cr, url).execute(mTouchIconUrl);
62702065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                }
62802065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                mMessage.arg1 = 1;
62902065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            } catch (IllegalStateException e) {
63002065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                mMessage.arg1 = 0;
63102065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            }
63202065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins            mMessage.sendToTarget();
63302065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins        }
63402065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins    }
63502065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins
6361794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch    private void createHandler() {
6371794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch        if (mHandler == null) {
6381794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch            mHandler = new Handler() {
6391794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                @Override
6401794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                public void handleMessage(Message msg) {
6411794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                    switch (msg.what) {
6421794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                        case SAVE_BOOKMARK:
64302065b07aea6b4392c344a4172c3ab56019225edLeon Scroggins                            if (1 == msg.arg1) {
6441794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                                Toast.makeText(AddBookmarkPage.this, R.string.bookmark_saved,
6451794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                                        Toast.LENGTH_LONG).show();
6461794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                            } else {
6471794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                                Toast.makeText(AddBookmarkPage.this, R.string.bookmark_not_saved,
6481794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                                        Toast.LENGTH_LONG).show();
6491794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                            }
6501794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                            break;
65188d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                        case TOUCH_ICON_DOWNLOADED:
65288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                            Bundle b = msg.getData();
65388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                            sendBroadcast(BookmarkUtils.createAddToHomeIntent(
654bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                                    AddBookmarkPage.this,
655bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                                    b.getString(BrowserContract.Bookmarks.URL),
656bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                                    b.getString(BrowserContract.Bookmarks.TITLE),
657bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                                    (Bitmap) b.getParcelable(BrowserContract.Bookmarks.TOUCH_ICON),
658bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                                    (Bitmap) b.getParcelable(BrowserContract.Bookmarks.FAVICON)));
65988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                            break;
6601794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                    }
6611794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                }
6621794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch            };
6631794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch        }
6641794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch    }
6651794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
6660c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    /**
6671794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch     * Parse the data entered in the dialog and post a message to update the bookmarks database.
6680c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project     */
6690c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    boolean save() {
6701794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch        createHandler();
6711794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
6720c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        String title = mTitle.getText().toString().trim();
673eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch        String unfilteredUrl;
674052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III        unfilteredUrl = BrowserActivity.fixUrl(mAddress.getText().toString());
675eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
6760c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        boolean emptyTitle = title.length() == 0;
6770c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        boolean emptyUrl = unfilteredUrl.trim().length() == 0;
6780c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        Resources r = getResources();
6790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        if (emptyTitle || emptyUrl) {
6800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            if (emptyTitle) {
6810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project                mTitle.setError(r.getText(R.string.bookmark_needs_title));
6820c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
6830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            if (emptyUrl) {
684052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                mAddress.setError(r.getText(R.string.bookmark_needs_url));
6850c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
6866e3faea951326f28bd9db6923d777281de1837d1Leon Scroggins III            return false;
687eecb4e6cb64af03aad3f9facdbf6fd7190091b41Ben Murdoch
6880c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
689ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch        String url = unfilteredUrl.trim();
690f2407c682fafef77d568deba9987b193a5f2d361Cary Clark        try {
691ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch            // We allow bookmarks with a javascript: scheme, but these will in most cases
692ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch            // fail URI parsing, so don't try it if that's the kind of bookmark we have.
693ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch
694ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch            if (!url.toLowerCase().startsWith("javascript:")) {
695ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                URI uriObj = new URI(url);
696ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                String scheme = uriObj.getScheme();
697ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                if (!Bookmarks.urlHasAcceptableScheme(url)) {
698ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    // If the scheme was non-null, let the user know that we
699ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    // can't save their bookmark. If it was null, we'll assume
700ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    // they meant http when we parse it in the WebAddress class.
701ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    if (scheme != null) {
702052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III                        mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
703ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                        return false;
704ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    }
705ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    WebAddress address;
706ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    try {
707ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                        address = new WebAddress(unfilteredUrl);
708ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    } catch (ParseException e) {
709ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                        throw new URISyntaxException("", "");
710ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    }
711131ab511f73b573b76fe8e692b829df4fe89bd54Bjorn Bringert                    if (address.getHost().length() == 0) {
712ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                        throw new URISyntaxException("", "");
713ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    }
714ca12cfa98fdf995c4cf37f487a050d0d4fb261e0Ben Murdoch                    url = address.toString();
715f2407c682fafef77d568deba9987b193a5f2d361Cary Clark                }
7160c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project            }
717f2407c682fafef77d568deba9987b193a5f2d361Cary Clark        } catch (URISyntaxException e) {
718052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
719f2407c682fafef77d568deba9987b193a5f2d361Cary Clark            return false;
7200c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
7211794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch
72288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        if (mSaveToHomeScreen) {
72388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            mEditingExisting = false;
72488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        }
72588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins
72688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins        boolean urlUnmodified = url.equals(mOriginalUrl);
72788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins
7281794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch        if (mEditingExisting) {
729bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            mMap.putString(BrowserContract.Bookmarks.TITLE, title);
730bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            mMap.putString(BrowserContract.Bookmarks.URL, url);
731bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            mMap.putBoolean(REMOVE_THUMBNAIL, !urlUnmodified);
732052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            // FIXME: This does not work yet
733052ce667ce77c4fb3208c0b0dacba7be79c072d9Leon Scroggins III            mMap.putLong(BrowserContract.Bookmarks.PARENT, mCurrentFolder);
7341794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch            setResult(RESULT_OK, (new Intent()).setAction(
7351794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch                    getIntent().toString()).putExtras(mMap));
7361794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch        } else {
73788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            Bitmap thumbnail;
73888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            Bitmap favicon;
73988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            if (urlUnmodified) {
740bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                thumbnail = (Bitmap) mMap.getParcelable(
741bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                        BrowserContract.Bookmarks.THUMBNAIL);
742bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                favicon = (Bitmap) mMap.getParcelable(
743bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                        BrowserContract.Bookmarks.FAVICON);
74488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            } else {
74588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                thumbnail = null;
74688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                favicon = null;
74788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            }
74888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins
7491794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch            Bundle bundle = new Bundle();
750bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            bundle.putString(BrowserContract.Bookmarks.TITLE, title);
751bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            bundle.putString(BrowserContract.Bookmarks.URL, url);
752bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins            bundle.putParcelable(BrowserContract.Bookmarks.FAVICON, favicon);
75388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins
75488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            if (mSaveToHomeScreen) {
75588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                if (mTouchIconUrl != null && urlUnmodified) {
75688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    Message msg = Message.obtain(mHandler,
75788d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                            TOUCH_ICON_DOWNLOADED);
75888d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    msg.setData(bundle);
75988d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    DownloadTouchIcon icon = new DownloadTouchIcon(this, msg,
760bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                            mMap.getString(USER_AGENT));
76188d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    icon.execute(mTouchIconUrl);
76288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                } else {
76388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                    sendBroadcast(BookmarkUtils.createAddToHomeIntent(this, url,
76488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                            title, null /*touchIcon*/, favicon));
76588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                }
76688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            } else {
767bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                bundle.putParcelable(BrowserContract.Bookmarks.THUMBNAIL, thumbnail);
768bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                bundle.putBoolean(REMOVE_THUMBNAIL, !urlUnmodified);
769bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins                bundle.putString(TOUCH_ICON_URL, mTouchIconUrl);
77088d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                // Post a message to write to the DB.
77188d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                Message msg = Message.obtain(mHandler, SAVE_BOOKMARK);
77288d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                msg.setData(bundle);
77388d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                // Start a new thread so as to not slow down the UI
77488d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                Thread t = new Thread(new SaveBookmarkRunnable(getApplicationContext(), msg));
77588d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins                t.start();
77688d080394ca18120e05c6926b178fd6843ff9cecLeon Scroggins            }
7771794fe252866c311f3b4700a2a1e44e843962243Ben Murdoch            setResult(RESULT_OK);
7780a1d838ccd16ac08300bb8ac89b61ee0c956a49bKristian Monsen            LogTag.logBookmarkAdded(url, "bookmarkview");
7790c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        }
7800c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project        return true;
7810c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project    }
78231829b941ca8ac02a828619440cb62b64673caa8Michael Kolb
7830c90888c75eed12f6e2e14a9044faf50bd4af8edThe Android Open Source Project}
784