blob: 4422113c55b29f17c80539e57ad98999f330cb0b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 android.provider;
18
19import android.content.ContentResolver;
Jeff Hamilton6f42edc2010-08-18 11:12:05 -050020import android.content.ContentUris;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.ContentValues;
22import android.content.Context;
23import android.content.Intent;
24import android.database.Cursor;
25import android.database.DatabaseUtils;
Jeff Hamilton31d95db2010-07-29 16:00:55 -050026import android.graphics.BitmapFactory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.net.Uri;
Jeff Hamilton6f42edc2010-08-18 11:12:05 -050028import android.provider.BrowserContract.Bookmarks;
29import android.provider.BrowserContract.History;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.util.Log;
31import android.webkit.WebIconDatabase;
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033public class Browser {
34 private static final String LOGTAG = "browser";
Jeff Hamilton31d95db2010-07-29 16:00:55 -050035
36 /**
37 * A table containing both bookmarks and history items. The columns of the table are defined in
38 * {@link BookmarkColumns}. Reading this table requires the
39 * {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS} permission and writing to it
40 * requires the {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS} permission.
41 */
42 public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44 /**
45 * The name of extra data when starting Browser with ACTION_VIEW or
46 * ACTION_SEARCH intent.
47 * <p>
48 * The value should be an integer between 0 and 1000. If not set or set to
49 * 0, the Browser will use default. If set to 100, the Browser will start
50 * with 100%.
51 */
52 public static final String INITIAL_ZOOM_LEVEL = "browser.initialZoomLevel";
53
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070054 /**
55 * The name of the extra data when starting the Browser from another
56 * application.
57 * <p>
58 * The value is a unique identification string that will be used to
Jeff Hamilton31d95db2010-07-29 16:00:55 -050059 * identify the calling application. The Browser will attempt to reuse the
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070060 * same window each time the application launches the Browser with the same
61 * identifier.
62 */
Jeff Hamilton31d95db2010-07-29 16:00:55 -050063 public static final String EXTRA_APPLICATION_ID = "com.android.browser.application_id";
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070064
Mitsuru Oshima8eb241b2009-06-10 15:18:08 -070065 /**
Grace Kloba67909182010-01-27 14:11:13 -080066 * The name of the extra data in the VIEW intent. The data are key/value
67 * pairs in the format of Bundle. They will be sent in the HTTP request
Grace Klobad0d9bc22010-01-26 18:08:28 -080068 * headers for the provided url. The keys can't be the standard HTTP headers
69 * as they are set by the WebView. The url's schema must be http(s).
70 * <p>
71 */
Grace Kloba67909182010-01-27 14:11:13 -080072 public static final String EXTRA_HEADERS = "com.android.browser.headers";
Grace Klobad0d9bc22010-01-26 18:08:28 -080073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 /* if you change column order you must also change indices
75 below */
76 public static final String[] HISTORY_PROJECTION = new String[] {
Jeff Hamilton31d95db2010-07-29 16:00:55 -050077 BookmarkColumns._ID, // 0
78 BookmarkColumns.URL, // 1
79 BookmarkColumns.VISITS, // 2
80 BookmarkColumns.DATE, // 3
81 BookmarkColumns.BOOKMARK, // 4
82 BookmarkColumns.TITLE, // 5
83 BookmarkColumns.FAVICON, // 6
84 BookmarkColumns.THUMBNAIL, // 7
85 BookmarkColumns.TOUCH_ICON, // 8
86 BookmarkColumns.USER_ENTERED, // 9
87 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088
89 /* these indices dependent on HISTORY_PROJECTION */
90 public static final int HISTORY_PROJECTION_ID_INDEX = 0;
91 public static final int HISTORY_PROJECTION_URL_INDEX = 1;
92 public static final int HISTORY_PROJECTION_VISITS_INDEX = 2;
93 public static final int HISTORY_PROJECTION_DATE_INDEX = 3;
94 public static final int HISTORY_PROJECTION_BOOKMARK_INDEX = 4;
95 public static final int HISTORY_PROJECTION_TITLE_INDEX = 5;
96 public static final int HISTORY_PROJECTION_FAVICON_INDEX = 6;
Leon Scroggins9f53fca2009-06-18 18:12:10 -040097 /**
Leon Scroggins7e2ff1a2009-06-18 17:45:14 -040098 * @hide
99 */
Leon Scroggins908baed2009-06-18 13:39:38 -0400100 public static final int HISTORY_PROJECTION_THUMBNAIL_INDEX = 7;
Patrick Scott2ba12622009-08-04 13:20:05 -0400101 /**
102 * @hide
103 */
104 public static final int HISTORY_PROJECTION_TOUCH_ICON_INDEX = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105
106 /* columns needed to determine whether to truncate history */
107 public static final String[] TRUNCATE_HISTORY_PROJECTION = new String[] {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500108 BookmarkColumns._ID,
109 BookmarkColumns.DATE,
110 };
111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 public static final int TRUNCATE_HISTORY_PROJECTION_ID_INDEX = 0;
113
114 /* truncate this many history items at a time */
115 public static final int TRUNCATE_N_OLDEST = 5;
116
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500117 /**
118 * A table containing a log of browser searches. The columns of the table are defined in
119 * {@link SearchColumns}. Reading this table requires the
120 * {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS} permission and writing to it
121 * requires the {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS} permission.
122 */
123 public static final Uri SEARCHES_URI = Uri.parse("content://browser/searches");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500125 /**
126 * A projection of {@link #SEARCHES_URI} that contains {@link SearchColumns#_ID},
127 * {@link SearchColumns#SEARCH}, and {@link SearchColumns#DATE}.
128 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 public static final String[] SEARCHES_PROJECTION = new String[] {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500130 // if you change column order you must also change indices below
131 SearchColumns._ID, // 0
132 SearchColumns.SEARCH, // 1
133 SearchColumns.DATE, // 2
134 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135
136 /* these indices dependent on SEARCHES_PROJECTION */
137 public static final int SEARCHES_PROJECTION_SEARCH_INDEX = 1;
138 public static final int SEARCHES_PROJECTION_DATE_INDEX = 2;
139
140 private static final String SEARCHES_WHERE_CLAUSE = "search = ?";
141
142 /* Set a cap on the count of history items in the history/bookmark
143 table, to prevent db and layout operations from dragging to a
144 crawl. Revisit this cap when/if db/layout performance
145 improvements are made. Note: this does not affect bookmark
146 entries -- if the user wants more bookmarks than the cap, they
147 get them. */
148 private static final int MAX_HISTORY_COUNT = 250;
149
150 /**
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500151 * Open an activity to save a bookmark. Launch with a title
152 * and/or a url, both of which can be edited by the user before saving.
153 *
154 * @param c Context used to launch the activity to add a bookmark.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 * @param title Title for the bookmark. Can be null or empty string.
156 * @param url Url for the bookmark. Can be null or empty string.
157 */
158 public static final void saveBookmark(Context c,
159 String title,
160 String url) {
161 Intent i = new Intent(Intent.ACTION_INSERT, Browser.BOOKMARKS_URI);
162 i.putExtra("title", title);
163 i.putExtra("url", url);
164 c.startActivity(i);
165 }
166
Leon Scrogginsdcf19a82009-12-10 12:37:09 -0500167 /**
Leon Scrogginsdcf19a82009-12-10 12:37:09 -0500168 * Stores a Bitmap extra in an {@link Intent} representing the screenshot of
169 * a page to share. When receiving an {@link Intent#ACTION_SEND} from the
170 * Browser, use this to access the screenshot.
171 * @hide
172 */
173 public final static String EXTRA_SHARE_SCREENSHOT = "share_screenshot";
174
175 /**
176 * Stores a Bitmap extra in an {@link Intent} representing the favicon of a
177 * page to share. When receiving an {@link Intent#ACTION_SEND} from the
178 * Browser, use this to access the favicon.
179 * @hide
180 */
181 public final static String EXTRA_SHARE_FAVICON = "share_favicon";
182
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500183 /**
184 * Sends the given string using an Intent with {@link Intent#ACTION_SEND} and a mime type
185 * of text/plain. The string is put into {@link Intent#EXTRA_TEXT}.
186 *
187 * @param context the context used to start the activity
188 * @param string the string to send
189 */
190 public static final void sendString(Context context, String string) {
191 sendString(context, string, context.getString(com.android.internal.R.string.sendText));
Andrei Popescu354eb662009-09-24 13:45:08 +0100192 }
193
194 /**
195 * Find an application to handle the given string and, if found, invoke
196 * it with the given string as a parameter.
197 * @param c Context used to launch the new activity.
198 * @param stringToSend The string to be handled.
199 * @param chooserDialogTitle The title of the dialog that allows the user
200 * to select between multiple applications that are all capable of handling
201 * the string.
202 * @hide pending API council approval
203 */
204 public static final void sendString(Context c,
205 String stringToSend,
206 String chooserDialogTitle) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 Intent send = new Intent(Intent.ACTION_SEND);
208 send.setType("text/plain");
Andrei Popescu354eb662009-09-24 13:45:08 +0100209 send.putExtra(Intent.EXTRA_TEXT, stringToSend);
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 try {
Andrei Popescu354eb662009-09-24 13:45:08 +0100212 c.startActivity(Intent.createChooser(send, chooserDialogTitle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 } catch(android.content.ActivityNotFoundException ex) {
214 // if no app handles it, do nothing
215 }
216 }
217
218 /**
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500219 * Return a cursor pointing to a list of all the bookmarks. The cursor will have a single
220 * column, {@link BookmarkColumns#URL}.
221 * <p>
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400222 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500223 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * @param cr The ContentResolver used to access the database.
225 */
226 public static final Cursor getAllBookmarks(ContentResolver cr) throws
227 IllegalStateException {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500228 return cr.query(Bookmarks.CONTENT_URI,
229 new String[] { Bookmarks.URL },
230 Bookmarks.IS_FOLDER + " = 0", null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 }
232
233 /**
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500234 * Return a cursor pointing to a list of all visited site urls. The cursor will
235 * have a single column, {@link BookmarkColumns#URL}.
236 * <p>
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400237 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500238 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 * @param cr The ContentResolver used to access the database.
240 */
241 public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
242 IllegalStateException {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500243 return cr.query(History.CONTENT_URI,
244 new String[] { History.URL }, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 }
246
Leon Scrogginsd2334cb2010-03-02 15:58:40 -0500247 private static final void addOrUrlEquals(StringBuilder sb) {
248 sb.append(" OR " + BookmarkColumns.URL + " = ");
249 }
250
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500251 private static final Cursor getVisitedLike(ContentResolver cr, String url) {
Leon Scrogginsd2334cb2010-03-02 15:58:40 -0500252 boolean secure = false;
253 String compareString = url;
254 if (compareString.startsWith("http://")) {
255 compareString = compareString.substring(7);
256 } else if (compareString.startsWith("https://")) {
257 compareString = compareString.substring(8);
258 secure = true;
259 }
260 if (compareString.startsWith("www.")) {
261 compareString = compareString.substring(4);
262 }
263 StringBuilder whereClause = null;
264 if (secure) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500265 whereClause = new StringBuilder(Bookmarks.URL + " = ");
Leon Scrogginsd2334cb2010-03-02 15:58:40 -0500266 DatabaseUtils.appendEscapedSQLString(whereClause,
267 "https://" + compareString);
268 addOrUrlEquals(whereClause);
269 DatabaseUtils.appendEscapedSQLString(whereClause,
270 "https://www." + compareString);
271 } else {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500272 whereClause = new StringBuilder(Bookmarks.URL + " = ");
Leon Scrogginsd2334cb2010-03-02 15:58:40 -0500273 DatabaseUtils.appendEscapedSQLString(whereClause,
274 compareString);
275 addOrUrlEquals(whereClause);
276 String wwwString = "www." + compareString;
277 DatabaseUtils.appendEscapedSQLString(whereClause,
278 wwwString);
279 addOrUrlEquals(whereClause);
280 DatabaseUtils.appendEscapedSQLString(whereClause,
281 "http://" + compareString);
282 addOrUrlEquals(whereClause);
283 DatabaseUtils.appendEscapedSQLString(whereClause,
284 "http://" + wwwString);
285 }
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500286 return cr.query(History.CONTENT_URI, new String[] { History._ID, History.VISITS },
Leon Scrogginsd2334cb2010-03-02 15:58:40 -0500287 whereClause.toString(), null, null);
288 }
289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 /**
291 * Update the visited history to acknowledge that a site has been
292 * visited.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400293 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
294 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 * @param cr The ContentResolver used to access the database.
296 * @param url The site being visited.
Leon Scroggins331c7782009-11-25 12:43:11 -0500297 * @param real If true, this is an actual visit, and should add to the
298 * number of visits. If false, the user entered it manually.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 */
300 public static final void updateVisitedHistory(ContentResolver cr,
301 String url, boolean real) {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500302 long now = System.currentTimeMillis();
Leon Scrogginse77852c2010-03-24 14:44:04 -0400303 Cursor c = null;
304 try {
305 c = getVisitedLike(cr, url);
306 /* We should only get one answer that is exactly the same. */
307 if (c.moveToFirst()) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500308 ContentValues values = new ContentValues();
Leon Scrogginse77852c2010-03-24 14:44:04 -0400309 if (real) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500310 values.put(History.VISITS, c.getInt(1) + 1);
Leon Scroggins331c7782009-11-25 12:43:11 -0500311 } else {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500312 values.put(History.USER_ENTERED, 1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 }
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500314 values.put(History.DATE_LAST_VISITED, now);
315 cr.update(ContentUris.withAppendedId(History.CONTENT_URI, c.getLong(0)),
316 values, null, null);
Leon Scrogginse77852c2010-03-24 14:44:04 -0400317 } else {
318 truncateHistory(cr);
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500319 ContentValues values = new ContentValues();
Leon Scrogginse77852c2010-03-24 14:44:04 -0400320 int visits;
321 int user_entered;
322 if (real) {
323 visits = 1;
324 user_entered = 0;
325 } else {
326 visits = 0;
327 user_entered = 1;
328 }
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500329 values.put(History.URL, url);
330 values.put(History.VISITS, visits);
331 values.put(History.DATE_LAST_VISITED, now);
332 values.put(History.TITLE, url);
333 values.put(History.DATE_CREATED, 0);
334 values.put(History.USER_ENTERED, user_entered);
335 cr.insert(History.CONTENT_URI, values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
Leon Scrogginse77852c2010-03-24 14:44:04 -0400337 } catch (IllegalStateException e) {
338 Log.e(LOGTAG, "updateVisitedHistory", e);
339 } finally {
340 if (c != null) c.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
342 }
343
344 /**
Leon Clarke9c8d8862009-09-24 15:20:10 +0100345 * Returns all the URLs in the history.
346 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
347 * @param cr The ContentResolver used to access the database.
348 * @hide pending API council approval
349 */
350 public static final String[] getVisitedHistory(ContentResolver cr) {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500351 Cursor c = null;
352 String[] str = null;
Grace Klobabf54f02b2009-09-24 14:14:11 -0700353 try {
354 String[] projection = new String[] {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500355 History.URL,
Grace Klobabf54f02b2009-09-24 14:14:11 -0700356 };
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500357 c = cr.query(History.CONTENT_URI, projection, History.VISITS + " > 0", null, null);
358 if (c == null) return new String[0];
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500359 str = new String[c.getCount()];
Grace Klobabf54f02b2009-09-24 14:14:11 -0700360 int i = 0;
361 while (c.moveToNext()) {
362 str[i] = c.getString(0);
363 i++;
364 }
Grace Klobabf54f02b2009-09-24 14:14:11 -0700365 } catch (IllegalStateException e) {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500366 Log.e(LOGTAG, "getVisitedHistory", e);
367 str = new String[0];
368 } finally {
369 if (c != null) c.close();
Grace Klobabf54f02b2009-09-24 14:14:11 -0700370 }
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500371 return str;
Leon Clarke9c8d8862009-09-24 15:20:10 +0100372 }
373
374 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 * If there are more than MAX_HISTORY_COUNT non-bookmark history
376 * items in the bookmark/history table, delete TRUNCATE_N_OLDEST
377 * of them. This is used to keep our history table to a
378 * reasonable size. Note: it does not prune bookmarks. If the
379 * user wants 1000 bookmarks, the user gets 1000 bookmarks.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400380 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
381 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 *
383 * @param cr The ContentResolver used to access the database.
384 */
385 public static final void truncateHistory(ContentResolver cr) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500386 // TODO make a single request to the provider to do this in a single transaction
387 Cursor cursor = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 try {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 // Select non-bookmark history, ordered by date
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500391 cursor = cr.query(History.CONTENT_URI,
392 new String[] { History._ID, History.URL, History.DATE_LAST_VISITED },
393 null, null, History.DATE_LAST_VISITED + " ASC");
394
395 if (cursor.moveToFirst() && cursor.getCount() >= MAX_HISTORY_COUNT) {
396 final WebIconDatabase iconDb = WebIconDatabase.getInstance();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 /* eliminate oldest history items */
398 for (int i = 0; i < TRUNCATE_N_OLDEST; i++) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500399 cr.delete(ContentUris.withAppendedId(History.CONTENT_URI, cursor.getLong(0)),
400 null, null);
401 iconDb.releaseIconForPageUrl(cursor.getString(1));
402 if (!cursor.moveToNext()) break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 } catch (IllegalStateException e) {
406 Log.e(LOGTAG, "truncateHistory", e);
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500407 } finally {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500408 if (cursor != null) cursor.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 }
410 }
411
412 /**
413 * Returns whether there is any history to clear.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400414 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 * @param cr The ContentResolver used to access the database.
416 * @return boolean True if the history can be cleared.
417 */
418 public static final boolean canClearHistory(ContentResolver cr) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500419 Cursor cursor = null;
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500420 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 try {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500422 cursor = cr.query(History.CONTENT_URI,
423 new String [] { History._ID, History.VISITS },
424 null, null, null);
425 ret = cursor.getCount() > 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 } catch (IllegalStateException e) {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500427 Log.e(LOGTAG, "canClearHistory", e);
428 } finally {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500429 if (cursor != null) cursor.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 }
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500431 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 }
433
434 /**
435 * Delete all entries from the bookmarks/history table which are
436 * not bookmarks. Also set all visited bookmarks to unvisited.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400437 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * @param cr The ContentResolver used to access the database.
439 */
440 public static final void clearHistory(ContentResolver cr) {
441 deleteHistoryWhere(cr, null);
442 }
443
444 /**
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500445 * Helper function to delete all history items and release the icons for them in the
446 * {@link WebIconDatabase}.
447 *
448 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
449 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
450 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 * @param cr The ContentResolver used to access the database.
452 * @param whereClause String to limit the items affected.
453 * null means all items.
454 */
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500455 private static final void deleteHistoryWhere(ContentResolver cr, String whereClause) {
456 Cursor cursor = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 try {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500458 cursor = cr.query(History.CONTENT_URI, new String[] { History.URL }, whereClause,
459 null, null);
460 if (cursor.moveToFirst()) {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500461 final WebIconDatabase iconDb = WebIconDatabase.getInstance();
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500462 do {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500463 // Delete favicons
464 // TODO don't release if the URL is bookmarked
465 iconDb.releaseIconForPageUrl(cursor.getString(0));
466 } while (cursor.moveToNext());
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500467
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500468 cr.delete(BOOKMARKS_URI, whereClause, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 } catch (IllegalStateException e) {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500471 Log.e(LOGTAG, "deleteHistoryWhere", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 return;
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500473 } finally {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500474 if (cursor != null) cursor.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 }
476 }
477
478 /**
479 * Delete all history items from begin to end.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400480 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 * @param cr The ContentResolver used to access the database.
482 * @param begin First date to remove. If -1, all dates before end.
483 * Inclusive.
484 * @param end Last date to remove. If -1, all dates after begin.
485 * Non-inclusive.
486 */
487 public static final void deleteHistoryTimeFrame(ContentResolver cr,
488 long begin, long end) {
489 String whereClause;
490 String date = BookmarkColumns.DATE;
491 if (-1 == begin) {
492 if (-1 == end) {
493 clearHistory(cr);
494 return;
495 }
496 whereClause = date + " < " + Long.toString(end);
497 } else if (-1 == end) {
498 whereClause = date + " >= " + Long.toString(begin);
499 } else {
500 whereClause = date + " >= " + Long.toString(begin) + " AND " + date
501 + " < " + Long.toString(end);
502 }
503 deleteHistoryWhere(cr, whereClause);
504 }
505
506 /**
507 * Remove a specific url from the history database.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400508 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 * @param cr The ContentResolver used to access the database.
510 * @param url url to remove.
511 */
512 public static final void deleteFromHistory(ContentResolver cr,
513 String url) {
Jeff Hamilton6f42edc2010-08-18 11:12:05 -0500514 cr.delete(History.CONTENT_URI, History.URL + "=?", new String[] { url });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 }
516
517 /**
518 * Add a search string to the searches database.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400519 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
520 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 * @param cr The ContentResolver used to access the database.
522 * @param search The string to add to the searches database.
523 */
524 public static final void addSearchUrl(ContentResolver cr, String search) {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500525 long now = System.currentTimeMillis();
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500526 Cursor c = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 try {
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500528 c = cr.query(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 SEARCHES_URI,
530 SEARCHES_PROJECTION,
531 SEARCHES_WHERE_CLAUSE,
532 new String [] { search },
533 null);
534 ContentValues map = new ContentValues();
535 map.put(SearchColumns.SEARCH, search);
536 map.put(SearchColumns.DATE, now);
537 /* We should only get one answer that is exactly the same. */
538 if (c.moveToFirst()) {
539 cr.update(SEARCHES_URI, map, "_id = " + c.getInt(0), null);
540 } else {
541 cr.insert(SEARCHES_URI, map);
542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 } catch (IllegalStateException e) {
544 Log.e(LOGTAG, "addSearchUrl", e);
Leon Scrogginsfe1143b2010-03-12 17:42:21 -0500545 } finally {
546 if (c != null) c.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 }
548 }
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 /**
551 * Remove all searches from the search database.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400552 * Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 * @param cr The ContentResolver used to access the database.
554 */
555 public static final void clearSearches(ContentResolver cr) {
556 // FIXME: Should this clear the urls to which these searches lead?
557 // (i.e. remove google.com/query= blah blah blah)
558 try {
559 cr.delete(SEARCHES_URI, null, null);
560 } catch (IllegalStateException e) {
561 Log.e(LOGTAG, "clearSearches", e);
562 }
563 }
564
565 /**
Patrick Scott36acfbc2010-04-09 12:42:03 -0400566 * Request all icons from the database. This call must either be called
567 * in the main thread or have had Looper.prepare() invoked in the calling
568 * thread.
Leon Scroggins9ce4c6c2009-06-19 14:13:08 -0400569 * Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 * @param cr The ContentResolver used to access the database.
571 * @param where Clause to be used to limit the query from the database.
572 * Must be an allowable string to be passed into a database query.
573 * @param listener IconListener that gets the icons once they are
574 * retrieved.
575 */
576 public static final void requestAllIcons(ContentResolver cr, String where,
577 WebIconDatabase.IconListener listener) {
Patrick Scott36acfbc2010-04-09 12:42:03 -0400578 WebIconDatabase.getInstance()
579 .bulkRequestIconForPageUrl(cr, where, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 }
581
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500582 /**
583 * Column definitions for the mixed bookmark and history items available
584 * at {@link #BOOKMARKS_URI}.
585 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 public static class BookmarkColumns implements BaseColumns {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500587 /**
588 * The URL of the bookmark or history item.
589 * <p>Type: TEXT (URL)</p>
590 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 public static final String URL = "url";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500592
593 /**
594 * The number of time the item has been visited.
595 * <p>Type: NUMBER</p>
596 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 public static final String VISITS = "visits";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500598
599 /**
600 * The date the item was last visited, in milliseconds since the epoch.
601 * <p>Type: NUMBER (date in milliseconds since January 1, 1970)</p>
602 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 public static final String DATE = "date";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500604
605 /**
606 * Flag indicating that an item is a bookmark. A value of 1 indicates a bookmark, a value
607 * of 0 indicates a history item.
608 * <p>Type: INTEGER (boolean)</p>
609 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 public static final String BOOKMARK = "bookmark";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500611
612 /**
613 * The user visible title of the bookmark or history item.
614 * <p>Type: TEXT</p>
615 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 public static final String TITLE = "title";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500617
618 /**
619 * The date the item created, in milliseconds since the epoch.
620 * <p>Type: NUMBER (date in milliseconds since January 1, 1970)</p>
621 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 public static final String CREATED = "created";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500623
624 /**
625 * The favicon of the bookmark. Must decode via {@link BitmapFactory#decodeByteArray}.
626 * <p>Type: BLOB (image)</p>
627 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 public static final String FAVICON = "favicon";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500629
Leon Scroggins9f53fca2009-06-18 18:12:10 -0400630 /**
Leon Scroggins7e2ff1a2009-06-18 17:45:14 -0400631 * @hide
632 */
Leon Scroggins908baed2009-06-18 13:39:38 -0400633 public static final String THUMBNAIL = "thumbnail";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500634
Patrick Scott2ba12622009-08-04 13:20:05 -0400635 /**
636 * @hide
637 */
638 public static final String TOUCH_ICON = "touch_icon";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500639
Leon Scroggins331c7782009-11-25 12:43:11 -0500640 /**
641 * @hide
642 */
643 public static final String USER_ENTERED = "user_entered";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 }
645
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500646 /**
647 * Column definitions for the search history table, available at {@link #SEARCHES_URI}.
648 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 public static class SearchColumns implements BaseColumns {
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500650 /**
Kristian Monsenb5503c12010-08-31 14:02:38 +0100651 * @deprecated Not used.
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500652 */
653 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 public static final String URL = "url";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500655
656 /**
657 * The user entered search term.
658 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 public static final String SEARCH = "search";
Jeff Hamilton31d95db2010-07-29 16:00:55 -0500660
661 /**
662 * The date the search was performed, in milliseconds since the epoch.
663 * <p>Type: NUMBER (date in milliseconds since January 1, 1970)</p>
664 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 public static final String DATE = "date";
666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667}