AddBookmarkPage.java revision c8393d9cfa47e3f5f279b17c412fd363e7ea94bd
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.app.Activity;
20import android.content.ContentResolver;
21import android.content.Intent;
22import android.content.res.Resources;
23import android.database.Cursor;
24import android.graphics.Bitmap;
25import android.net.ParseException;
26import android.net.WebAddress;
27import android.os.Bundle;
28import android.os.Handler;
29import android.os.Message;
30import android.provider.Browser;
31import android.view.View;
32import android.view.Window;
33import android.widget.EditText;
34import android.widget.TextView;
35import android.widget.Toast;
36
37import java.net.URI;
38import java.net.URISyntaxException;
39import java.util.Date;
40
41public class AddBookmarkPage extends Activity {
42
43    private final String LOGTAG = "Bookmarks";
44
45    private EditText    mTitle;
46    private EditText    mAddress;
47    private TextView    mButton;
48    private View        mCancelButton;
49    private boolean     mEditingExisting;
50    private Bundle      mMap;
51    private String      mTouchIconUrl;
52    private Bitmap      mThumbnail;
53    private String      mOriginalUrl;
54
55    // Message IDs
56    private static final int SAVE_BOOKMARK = 100;
57
58    private Handler mHandler;
59
60    private View.OnClickListener mSaveBookmark = new View.OnClickListener() {
61        public void onClick(View v) {
62            if (save()) {
63                finish();
64            }
65        }
66    };
67
68    private View.OnClickListener mCancel = new View.OnClickListener() {
69        public void onClick(View v) {
70            finish();
71        }
72    };
73
74    protected void onCreate(Bundle icicle) {
75        super.onCreate(icicle);
76        requestWindowFeature(Window.FEATURE_LEFT_ICON);
77        setContentView(R.layout.browser_add_bookmark);
78        setTitle(R.string.save_to_bookmarks);
79        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_list_bookmark);
80
81        String title = null;
82        String url = null;
83        mMap = getIntent().getExtras();
84        if (mMap != null) {
85            Bundle b = mMap.getBundle("bookmark");
86            if (b != null) {
87                mMap = b;
88                mEditingExisting = true;
89                setTitle(R.string.edit_bookmark);
90            }
91            title = mMap.getString("title");
92            url = mOriginalUrl = mMap.getString("url");
93            mTouchIconUrl = mMap.getString("touch_icon_url");
94            mThumbnail = (Bitmap) mMap.getParcelable("thumbnail");
95        }
96
97        mTitle = (EditText) findViewById(R.id.title);
98        mTitle.setText(title);
99        mAddress = (EditText) findViewById(R.id.address);
100        mAddress.setText(url);
101
102        View.OnClickListener accept = mSaveBookmark;
103        mButton = (TextView) findViewById(R.id.OK);
104        mButton.setOnClickListener(accept);
105
106        mCancelButton = findViewById(R.id.cancel);
107        mCancelButton.setOnClickListener(mCancel);
108
109        if (!getWindow().getDecorView().isInTouchMode()) {
110            mButton.requestFocus();
111        }
112    }
113
114    /**
115     * Runnable to save a bookmark, so it can be performed in its own thread.
116     */
117    private class SaveBookmarkRunnable implements Runnable {
118        private Message mMessage;
119        public SaveBookmarkRunnable(Message msg) {
120            mMessage = msg;
121        }
122        public void run() {
123            // Unbundle bookmark data.
124            Bundle bundle = mMessage.getData();
125            String title = bundle.getString("title");
126            String url = bundle.getString("url");
127            boolean invalidateThumbnail = bundle.getBoolean(
128                    "invalidateThumbnail");
129            Bitmap thumbnail = invalidateThumbnail ? null
130                    : (Bitmap) bundle.getParcelable("thumbnail");
131            String touchIconUrl = bundle.getString("touchIconUrl");
132
133            // Save to the bookmarks DB.
134            try {
135                final ContentResolver cr = getContentResolver();
136                Bookmarks.addBookmark(null, cr, url, title, thumbnail, true);
137                if (touchIconUrl != null) {
138                    new DownloadTouchIcon(cr, url).execute(mTouchIconUrl);
139                }
140                mMessage.arg1 = 1;
141            } catch (IllegalStateException e) {
142                mMessage.arg1 = 0;
143            }
144            mMessage.sendToTarget();
145        }
146    }
147
148    private void createHandler() {
149        if (mHandler == null) {
150            mHandler = new Handler() {
151                @Override
152                public void handleMessage(Message msg) {
153                    switch (msg.what) {
154                        case SAVE_BOOKMARK:
155                            if (1 == msg.arg1) {
156                                Toast.makeText(AddBookmarkPage.this, R.string.bookmark_saved,
157                                        Toast.LENGTH_LONG).show();
158                            } else {
159                                Toast.makeText(AddBookmarkPage.this, R.string.bookmark_not_saved,
160                                        Toast.LENGTH_LONG).show();
161                            }
162                            break;
163                    }
164                }
165            };
166        }
167    }
168
169    /**
170     * Parse the data entered in the dialog and post a message to update the bookmarks database.
171     */
172    boolean save() {
173        createHandler();
174
175        String title = mTitle.getText().toString().trim();
176        String unfilteredUrl =
177                BrowserActivity.fixUrl(mAddress.getText().toString());
178        boolean emptyTitle = title.length() == 0;
179        boolean emptyUrl = unfilteredUrl.trim().length() == 0;
180        Resources r = getResources();
181        if (emptyTitle || emptyUrl) {
182            if (emptyTitle) {
183                mTitle.setError(r.getText(R.string.bookmark_needs_title));
184            }
185            if (emptyUrl) {
186                mAddress.setError(r.getText(R.string.bookmark_needs_url));
187            }
188            return false;
189        }
190        String url = unfilteredUrl.trim();
191        try {
192            // We allow bookmarks with a javascript: scheme, but these will in most cases
193            // fail URI parsing, so don't try it if that's the kind of bookmark we have.
194
195            if (!url.toLowerCase().startsWith("javascript:")) {
196                URI uriObj = new URI(url);
197                String scheme = uriObj.getScheme();
198                if (!Bookmarks.urlHasAcceptableScheme(url)) {
199                    // If the scheme was non-null, let the user know that we
200                    // can't save their bookmark. If it was null, we'll assume
201                    // they meant http when we parse it in the WebAddress class.
202                    if (scheme != null) {
203                        mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
204                        return false;
205                    }
206                    WebAddress address;
207                    try {
208                        address = new WebAddress(unfilteredUrl);
209                    } catch (ParseException e) {
210                        throw new URISyntaxException("", "");
211                    }
212                    if (address.mHost.length() == 0) {
213                        throw new URISyntaxException("", "");
214                    }
215                    url = address.toString();
216                }
217            }
218        } catch (URISyntaxException e) {
219            mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
220            return false;
221        }
222
223        if (mEditingExisting) {
224            mMap.putString("title", title);
225            mMap.putString("url", url);
226            mMap.putBoolean("invalidateThumbnail", !url.equals(mOriginalUrl));
227            setResult(RESULT_OK, (new Intent()).setAction(
228                    getIntent().toString()).putExtras(mMap));
229        } else {
230            // Post a message to write to the DB.
231            Bundle bundle = new Bundle();
232            bundle.putString("title", title);
233            bundle.putString("url", url);
234            bundle.putParcelable("thumbnail", mThumbnail);
235            bundle.putBoolean("invalidateThumbnail", !url.equals(mOriginalUrl));
236            bundle.putString("touchIconUrl", mTouchIconUrl);
237            Message msg = Message.obtain(mHandler, SAVE_BOOKMARK);
238            msg.setData(bundle);
239            // Start a new thread so as to not slow down the UI
240            Thread t = new Thread(new SaveBookmarkRunnable(msg));
241            t.start();
242            setResult(RESULT_OK);
243            LogTag.logBookmarkAdded(url, "bookmarkview");
244        }
245        return true;
246    }
247}
248