OSDN Git Service

Deprecate fill_parent and introduce match_parent.
[android-x86/packages-apps-Browser.git] / src / com / android / browser / Bookmarks.java
1 /*
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
17 package com.android.browser;
18
19 import android.content.ContentResolver;
20 import android.content.ContentUris;
21 import android.content.ContentValues;
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.graphics.Bitmap;
25 import android.net.Uri;
26 import android.provider.Browser;
27 import android.util.Log;
28 import android.webkit.WebIconDatabase;
29 import android.widget.Toast;
30
31 import java.io.ByteArrayOutputStream;
32 import java.util.Date;
33
34 /**
35  *  This class is purely to have a common place for adding/deleting bookmarks.
36  */
37 /* package */ class Bookmarks {
38     private static final String     WHERE_CLAUSE
39             = "url = ? OR url = ? OR url = ? OR url = ?";
40     private static final String     WHERE_CLAUSE_SECURE = "url = ? OR url = ?";
41
42     private static String[]         SELECTION_ARGS;
43
44     // We only want the user to be able to bookmark content that
45     // the browser can handle directly.
46     private static final String acceptableBookmarkSchemes[] = {
47             "http:",
48             "https:",
49             "about:",
50             "data:",
51             "javascript:",
52             "file:",
53             "content:"
54     };
55
56     /**
57      *  Add a bookmark to the database.
58      *  @param context Context of the calling Activity.  This is used to make
59      *          Toast confirming that the bookmark has been added.  If the
60      *          caller provides null, the Toast will not be shown.
61      *  @param cr The ContentResolver being used to add the bookmark to the db.
62      *  @param url URL of the website to be bookmarked.
63      *  @param name Provided name for the bookmark.
64      *  @param thumbnail A thumbnail for the bookmark.
65      *  @param retainIcon Whether to retain the page's icon in the icon database.
66      *          This will usually be <code>true</code> except when bookmarks are
67      *          added by a settings restore agent.
68      */
69     /* package */ static void addBookmark(Context context,
70             ContentResolver cr, String url, String name,
71             Bitmap thumbnail, boolean retainIcon) {
72         // Want to append to the beginning of the list
73         long creationTime = new Date().getTime();
74         // First we check to see if the user has already visited this
75         // site.  They may have bookmarked it in a different way from
76         // how it's stored in the database, so allow different combos
77         // to map to the same url.
78         boolean secure = false;
79         String compareString = url;
80         if (compareString.startsWith("http://")) {
81             compareString = compareString.substring(7);
82         } else if (compareString.startsWith("https://")) {
83             compareString = compareString.substring(8);
84             secure = true;
85         }
86         if (compareString.startsWith("www.")) {
87             compareString = compareString.substring(4);
88         }
89         if (secure) {
90             SELECTION_ARGS = new String[2];
91             SELECTION_ARGS[0] = "https://" + compareString;
92             SELECTION_ARGS[1] = "https://www." + compareString;
93         } else {
94             SELECTION_ARGS = new String[4];
95             SELECTION_ARGS[0] = compareString;
96             SELECTION_ARGS[1] = "www." + compareString;
97             SELECTION_ARGS[2] = "http://" + compareString;
98             SELECTION_ARGS[3] = "http://" + SELECTION_ARGS[1];
99         }
100         Cursor cursor = cr.query(Browser.BOOKMARKS_URI,
101                 Browser.HISTORY_PROJECTION,
102                 secure ? WHERE_CLAUSE_SECURE : WHERE_CLAUSE,
103                 SELECTION_ARGS,
104                 null);
105         ContentValues map = new ContentValues();
106         if (cursor.moveToFirst() && cursor.getInt(
107                 Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
108             // This means we have been to this site but not bookmarked
109             // it, so convert the history item to a bookmark
110             map.put(Browser.BookmarkColumns.CREATED, creationTime);
111             map.put(Browser.BookmarkColumns.TITLE, name);
112             map.put(Browser.BookmarkColumns.BOOKMARK, 1);
113             map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
114             cr.update(Browser.BOOKMARKS_URI, map,
115                     "_id = " + cursor.getInt(0), null);
116         } else {
117             int count = cursor.getCount();
118             boolean matchedTitle = false;
119             for (int i = 0; i < count; i++) {
120                 // One or more bookmarks already exist for this site.
121                 // Check the names of each
122                 cursor.moveToPosition(i);
123                 if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)
124                         .equals(name)) {
125                     // The old bookmark has the same name.
126                     // Update its creation time.
127                     map.put(Browser.BookmarkColumns.CREATED,
128                             creationTime);
129                     cr.update(Browser.BOOKMARKS_URI, map,
130                             "_id = " + cursor.getInt(0), null);
131                     matchedTitle = true;
132                     break;
133                 }
134             }
135             if (!matchedTitle) {
136                 // Adding a bookmark for a site the user has visited,
137                 // or a new bookmark (with a different name) for a site
138                 // the user has visited
139                 map.put(Browser.BookmarkColumns.TITLE, name);
140                 map.put(Browser.BookmarkColumns.URL, url);
141                 map.put(Browser.BookmarkColumns.CREATED, creationTime);
142                 map.put(Browser.BookmarkColumns.BOOKMARK, 1);
143                 map.put(Browser.BookmarkColumns.DATE, 0);
144                 map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
145                 int visits = 0;
146                 if (count > 0) {
147                     // The user has already bookmarked, and possibly
148                     // visited this site.  However, they are creating
149                     // a new bookmark with the same url but a different
150                     // name.  The new bookmark should have the same
151                     // number of visits as the already created bookmark.
152                     visits = cursor.getInt(
153                             Browser.HISTORY_PROJECTION_VISITS_INDEX);
154                 }
155                 // Bookmark starts with 3 extra visits so that it will
156                 // bubble up in the most visited and goto search box
157                 map.put(Browser.BookmarkColumns.VISITS, visits + 3);
158                 cr.insert(Browser.BOOKMARKS_URI, map);
159             }
160         }
161         if (retainIcon) {
162             WebIconDatabase.getInstance().retainIconForPageUrl(url);
163         }
164         cursor.deactivate();
165         if (context != null) {
166             Toast.makeText(context, R.string.added_to_bookmarks,
167                     Toast.LENGTH_LONG).show();
168         }
169     }
170
171     /**
172      *  Remove a bookmark from the database.  If the url is a visited site, it
173      *  will remain in the database, but only as a history item, and not as a
174      *  bookmarked site.
175      *  @param context Context of the calling Activity.  This is used to make
176      *          Toast confirming that the bookmark has been removed.  If the
177      *          caller provides null, the Toast will not be shown.
178      *  @param cr The ContentResolver being used to remove the bookmark.
179      *  @param url URL of the website to be removed.
180      */
181     /* package */ static void removeFromBookmarks(Context context,
182             ContentResolver cr, String url, String title) {
183         Cursor cursor = cr.query(
184                 Browser.BOOKMARKS_URI,
185                 Browser.HISTORY_PROJECTION,
186                 "url = ? AND title = ?",
187                 new String[] { url, title },
188                 null);
189         boolean first = cursor.moveToFirst();
190         // Should be in the database no matter what
191         if (!first) {
192             throw new AssertionError("URL is not in the database! " + url + " " + title);
193         }
194         // Remove from bookmarks
195         WebIconDatabase.getInstance().releaseIconForPageUrl(url);
196         Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
197                 cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
198         int numVisits = cursor.getInt(
199                 Browser.HISTORY_PROJECTION_VISITS_INDEX);
200         if (0 == numVisits) {
201             cr.delete(uri, null, null);
202         } else {
203             // It is no longer a bookmark, but it is still a visited
204             // site.
205             ContentValues values = new ContentValues();
206             values.put(Browser.BookmarkColumns.BOOKMARK, 0);
207             try {
208                 cr.update(uri, values, null, null);
209             } catch (IllegalStateException e) {
210                 Log.e("removeFromBookmarks", "no database!");
211             }
212         }
213         if (context != null) {
214             Toast.makeText(context, R.string.removed_from_bookmarks,
215                     Toast.LENGTH_LONG).show();
216         }
217         cursor.deactivate();
218     }
219
220     private static byte[] bitmapToBytes(Bitmap bm) {
221         if (bm == null) {
222             return null;
223         }
224
225         final ByteArrayOutputStream os = new ByteArrayOutputStream();
226         bm.compress(Bitmap.CompressFormat.PNG, 100, os);
227         return os.toByteArray();
228     }
229
230     /* package */ static boolean urlHasAcceptableScheme(String url) {
231         if (url == null) {
232             return false;
233         }
234
235         for (int i = 0; i < acceptableBookmarkSchemes.length; i++) {
236             if (url.startsWith(acceptableBookmarkSchemes[i])) {
237                 return true;
238             }
239         }
240         return false;
241     }
242 }