blob: 5ada9dcb8cda9967aad4193a31852a3e08378684 [file] [log] [blame]
Leon Scrogginse372c022009-06-12 17:07:29 -04001/*
2 * Copyright (C) 2009 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.content.ContentResolver;
20import android.content.ContentUris;
21import android.content.ContentValues;
22import android.content.Context;
23import android.database.Cursor;
Ben Murdochaac7aa62009-09-17 16:57:40 +010024import android.graphics.Bitmap;
Leon Scrogginse372c022009-06-12 17:07:29 -040025import android.net.Uri;
26import android.provider.Browser;
27import android.util.Log;
28import android.webkit.WebIconDatabase;
29import android.widget.Toast;
30
Ben Murdochaac7aa62009-09-17 16:57:40 +010031import java.io.ByteArrayOutputStream;
Leon Scrogginse372c022009-06-12 17:07:29 -040032import java.util.Date;
33
34/**
35 * This class is purely to have a common place for adding/deleting bookmarks.
36 */
37/* package */ class Bookmarks {
Ben Murdochde353622009-10-12 10:29:00 +010038 // We only want the user to be able to bookmark content that
39 // the browser can handle directly.
40 private static final String acceptableBookmarkSchemes[] = {
41 "http:",
42 "https:",
43 "about:",
44 "data:",
45 "javascript:",
46 "file:",
47 "content:"
48 };
49
Leon Scroggins2c0f6112010-03-12 18:09:39 -050050 private final static String LOGTAG = "Bookmarks";
Leon Scrogginse372c022009-06-12 17:07:29 -040051 /**
52 * Add a bookmark to the database.
53 * @param context Context of the calling Activity. This is used to make
54 * Toast confirming that the bookmark has been added. If the
55 * caller provides null, the Toast will not be shown.
56 * @param cr The ContentResolver being used to add the bookmark to the db.
57 * @param url URL of the website to be bookmarked.
58 * @param name Provided name for the bookmark.
Ben Murdochaac7aa62009-09-17 16:57:40 +010059 * @param thumbnail A thumbnail for the bookmark.
Christopher Tate9c0dd8c2009-07-10 17:51:48 -070060 * @param retainIcon Whether to retain the page's icon in the icon database.
61 * This will usually be <code>true</code> except when bookmarks are
62 * added by a settings restore agent.
Leon Scrogginse372c022009-06-12 17:07:29 -040063 */
64 /* package */ static void addBookmark(Context context,
Christopher Tate9c0dd8c2009-07-10 17:51:48 -070065 ContentResolver cr, String url, String name,
Ben Murdochaac7aa62009-09-17 16:57:40 +010066 Bitmap thumbnail, boolean retainIcon) {
Leon Scrogginse372c022009-06-12 17:07:29 -040067 // Want to append to the beginning of the list
68 long creationTime = new Date().getTime();
Leon Scrogginse372c022009-06-12 17:07:29 -040069 ContentValues map = new ContentValues();
Leon Scroggins2c0f6112010-03-12 18:09:39 -050070 Cursor cursor = null;
71 try {
72 cursor = Browser.getVisitedLike(cr, url);
73 if (cursor.moveToFirst() && cursor.getInt(
74 Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
75 // This means we have been to this site but not bookmarked
76 // it, so convert the history item to a bookmark
Leon Scrogginse372c022009-06-12 17:07:29 -040077 map.put(Browser.BookmarkColumns.CREATED, creationTime);
Leon Scroggins2c0f6112010-03-12 18:09:39 -050078 map.put(Browser.BookmarkColumns.TITLE, name);
Leon Scrogginse372c022009-06-12 17:07:29 -040079 map.put(Browser.BookmarkColumns.BOOKMARK, 1);
Leon Scroggins2c0f6112010-03-12 18:09:39 -050080 map.put(Browser.BookmarkColumns.THUMBNAIL,
81 bitmapToBytes(thumbnail));
82 cr.update(Browser.BOOKMARKS_URI, map,
83 "_id = " + cursor.getInt(0), null);
84 } else {
85 int count = cursor.getCount();
86 boolean matchedTitle = false;
87 for (int i = 0; i < count; i++) {
88 // One or more bookmarks already exist for this site.
89 // Check the names of each
90 cursor.moveToPosition(i);
91 if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)
92 .equals(name)) {
93 // The old bookmark has the same name.
94 // Update its creation time.
95 map.put(Browser.BookmarkColumns.CREATED,
96 creationTime);
97 cr.update(Browser.BOOKMARKS_URI, map,
98 "_id = " + cursor.getInt(0), null);
99 matchedTitle = true;
100 break;
101 }
Leon Scrogginse372c022009-06-12 17:07:29 -0400102 }
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500103 if (!matchedTitle) {
104 // Adding a bookmark for a site the user has visited,
105 // or a new bookmark (with a different name) for a site
106 // the user has visited
107 map.put(Browser.BookmarkColumns.TITLE, name);
108 map.put(Browser.BookmarkColumns.URL, url);
109 map.put(Browser.BookmarkColumns.CREATED, creationTime);
110 map.put(Browser.BookmarkColumns.BOOKMARK, 1);
111 map.put(Browser.BookmarkColumns.DATE, 0);
112 map.put(Browser.BookmarkColumns.THUMBNAIL,
113 bitmapToBytes(thumbnail));
114 int visits = 0;
115 if (count > 0) {
116 // The user has already bookmarked, and possibly
117 // visited this site. However, they are creating
118 // a new bookmark with the same url but a different
119 // name. The new bookmark should have the same
120 // number of visits as the already created bookmark.
121 visits = cursor.getInt(
122 Browser.HISTORY_PROJECTION_VISITS_INDEX);
123 }
124 // Bookmark starts with 3 extra visits so that it will
125 // bubble up in the most visited and goto search box
126 map.put(Browser.BookmarkColumns.VISITS, visits + 3);
127 cr.insert(Browser.BOOKMARKS_URI, map);
128 }
Leon Scrogginse372c022009-06-12 17:07:29 -0400129 }
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500130 } catch (IllegalStateException e) {
131 Log.e(LOGTAG, "addBookmark", e);
132 } finally {
133 if (cursor != null) cursor.close();
Leon Scrogginse372c022009-06-12 17:07:29 -0400134 }
Christopher Tate9c0dd8c2009-07-10 17:51:48 -0700135 if (retainIcon) {
136 WebIconDatabase.getInstance().retainIconForPageUrl(url);
137 }
Leon Scrogginse372c022009-06-12 17:07:29 -0400138 if (context != null) {
139 Toast.makeText(context, R.string.added_to_bookmarks,
140 Toast.LENGTH_LONG).show();
141 }
142 }
143
144 /**
145 * Remove a bookmark from the database. If the url is a visited site, it
146 * will remain in the database, but only as a history item, and not as a
147 * bookmarked site.
148 * @param context Context of the calling Activity. This is used to make
149 * Toast confirming that the bookmark has been removed. If the
150 * caller provides null, the Toast will not be shown.
151 * @param cr The ContentResolver being used to remove the bookmark.
152 * @param url URL of the website to be removed.
153 */
154 /* package */ static void removeFromBookmarks(Context context,
Andrei Popescuc9526192009-09-23 15:52:16 +0100155 ContentResolver cr, String url, String title) {
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500156 Cursor cursor = null;
157 try {
158 cursor = cr.query(
159 Browser.BOOKMARKS_URI,
160 Browser.HISTORY_PROJECTION,
161 "url = ? AND title = ?",
162 new String[] { url, title },
163 null);
164 boolean first = cursor.moveToFirst();
165 // Should be in the database no matter what
166 if (!first) {
167 throw new AssertionError("URL is not in the database! " + url
168 + " " + title);
Leon Scrogginse372c022009-06-12 17:07:29 -0400169 }
Leon Scroggins2c0f6112010-03-12 18:09:39 -0500170 // Remove from bookmarks
171 WebIconDatabase.getInstance().releaseIconForPageUrl(url);
172 Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
173 cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
174 int numVisits = cursor.getInt(
175 Browser.HISTORY_PROJECTION_VISITS_INDEX);
176 if (0 == numVisits) {
177 cr.delete(uri, null, null);
178 } else {
179 // It is no longer a bookmark, but it is still a visited
180 // site.
181 ContentValues values = new ContentValues();
182 values.put(Browser.BookmarkColumns.BOOKMARK, 0);
183 try {
184 cr.update(uri, values, null, null);
185 } catch (IllegalStateException e) {
186 Log.e("removeFromBookmarks", "no database!");
187 }
188 }
189 if (context != null) {
190 Toast.makeText(context, R.string.removed_from_bookmarks,
191 Toast.LENGTH_LONG).show();
192 }
193 } catch (IllegalStateException e) {
194 Log.e(LOGTAG, "removeFromBookmarks", e);
195 } finally {
196 if (cursor != null) cursor.close();
Leon Scrogginse372c022009-06-12 17:07:29 -0400197 }
Leon Scrogginse372c022009-06-12 17:07:29 -0400198 }
Ben Murdochaac7aa62009-09-17 16:57:40 +0100199
200 private static byte[] bitmapToBytes(Bitmap bm) {
201 if (bm == null) {
202 return null;
203 }
204
205 final ByteArrayOutputStream os = new ByteArrayOutputStream();
206 bm.compress(Bitmap.CompressFormat.PNG, 100, os);
207 return os.toByteArray();
208 }
Ben Murdochde353622009-10-12 10:29:00 +0100209
210 /* package */ static boolean urlHasAcceptableScheme(String url) {
211 if (url == null) {
212 return false;
213 }
214
215 for (int i = 0; i < acceptableBookmarkSchemes.length; i++) {
216 if (url.startsWith(acceptableBookmarkSchemes[i])) {
217 return true;
218 }
219 }
220 return false;
221 }
Ben Murdochaac7aa62009-09-17 16:57:40 +0100222}