1e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins/*
2e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * Copyright (C) 2009 The Android Open Source Project
3e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins *
4e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * Licensed under the Apache License, Version 2.0 (the "License");
5e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * you may not use this file except in compliance with the License.
6e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * You may obtain a copy of the License at
7e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins *
8e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins *      http://www.apache.org/licenses/LICENSE-2.0
9e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins *
10e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * Unless required by applicable law or agreed to in writing, software
11e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * distributed under the License is distributed on an "AS IS" BASIS,
12e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * See the License for the specific language governing permissions and
14e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins * limitations under the License.
15e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins */
16e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins
17e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginspackage com.android.browser;
18e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins
19e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.content.ContentResolver;
20e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.content.ContentUris;
21e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.content.ContentValues;
22e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.content.Context;
23e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.database.Cursor;
24aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdochimport android.graphics.Bitmap;
25e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.net.Uri;
26e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.provider.Browser;
27e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.util.Log;
28e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.webkit.WebIconDatabase;
29e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport android.widget.Toast;
30e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins
31aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdochimport java.io.ByteArrayOutputStream;
32e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scrogginsimport java.util.Date;
33e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins
34e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins/**
35e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins *  This class is purely to have a common place for adding/deleting bookmarks.
36e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins */
37e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins/* package */ class Bookmarks {
38de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    // We only want the user to be able to bookmark content that
39de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    // the browser can handle directly.
40de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    private static final String acceptableBookmarkSchemes[] = {
41de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "http:",
42de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "https:",
43de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "about:",
44de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "data:",
45de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "javascript:",
46de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "file:",
47de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            "content:"
48de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    };
49de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch
502c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins    private final static String LOGTAG = "Bookmarks";
51e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    /**
52e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  Add a bookmark to the database.
53e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param context Context of the calling Activity.  This is used to make
54e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *          Toast confirming that the bookmark has been added.  If the
55e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *          caller provides null, the Toast will not be shown.
56e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param cr The ContentResolver being used to add the bookmark to the db.
57e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param url URL of the website to be bookmarked.
58e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param name Provided name for the bookmark.
59aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch     *  @param thumbnail A thumbnail for the bookmark.
609c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate     *  @param retainIcon Whether to retain the page's icon in the icon database.
619c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate     *          This will usually be <code>true</code> except when bookmarks are
629c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate     *          added by a settings restore agent.
63e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     */
64e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    /* package */ static void addBookmark(Context context,
659c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate            ContentResolver cr, String url, String name,
66aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch            Bitmap thumbnail, boolean retainIcon) {
67e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        // Want to append to the beginning of the list
68e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        long creationTime = new Date().getTime();
69e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        ContentValues map = new ContentValues();
702c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        Cursor cursor = null;
712c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        try {
722c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            cursor = Browser.getVisitedLike(cr, url);
732c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (cursor.moveToFirst() && cursor.getInt(
742c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
752c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                // This means we have been to this site but not bookmarked
762c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                // it, so convert the history item to a bookmark
77e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins                map.put(Browser.BookmarkColumns.CREATED, creationTime);
782c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                map.put(Browser.BookmarkColumns.TITLE, name);
79e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins                map.put(Browser.BookmarkColumns.BOOKMARK, 1);
802c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                map.put(Browser.BookmarkColumns.THUMBNAIL,
812c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        bitmapToBytes(thumbnail));
822c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                cr.update(Browser.BOOKMARKS_URI, map,
832c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        "_id = " + cursor.getInt(0), null);
842c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            } else {
852c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                int count = cursor.getCount();
862c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                boolean matchedTitle = false;
872c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                for (int i = 0; i < count; i++) {
882c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // One or more bookmarks already exist for this site.
892c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // Check the names of each
902c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    cursor.moveToPosition(i);
912c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)
922c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                            .equals(name)) {
932c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // The old bookmark has the same name.
942c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // Update its creation time.
952c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        map.put(Browser.BookmarkColumns.CREATED,
962c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                                creationTime);
972c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        cr.update(Browser.BOOKMARKS_URI, map,
982c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                                "_id = " + cursor.getInt(0), null);
992c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        matchedTitle = true;
1002c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        break;
1012c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    }
1022c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                }
1032c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                if (!matchedTitle) {
1042c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // Adding a bookmark for a site the user has visited,
1052c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // or a new bookmark (with a different name) for a site
1062c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // the user has visited
1072c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.TITLE, name);
1082c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.URL, url);
1092c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.CREATED, creationTime);
1102c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.BOOKMARK, 1);
1112c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.DATE, 0);
1122c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.THUMBNAIL,
1132c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                            bitmapToBytes(thumbnail));
1142c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    int visits = 0;
1152c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    if (count > 0) {
1162c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // The user has already bookmarked, and possibly
1172c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // visited this site.  However, they are creating
1182c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // a new bookmark with the same url but a different
1192c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // name.  The new bookmark should have the same
1202c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        // number of visits as the already created bookmark.
1212c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        visits = cursor.getInt(
1222c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                                Browser.HISTORY_PROJECTION_VISITS_INDEX);
1232c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    }
1242c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // Bookmark starts with 3 extra visits so that it will
1252c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    // bubble up in the most visited and goto search box
1262c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    map.put(Browser.BookmarkColumns.VISITS, visits + 3);
1272c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    cr.insert(Browser.BOOKMARKS_URI, map);
128e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins                }
129e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins            }
1302c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        } catch (IllegalStateException e) {
1312c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            Log.e(LOGTAG, "addBookmark", e);
1322c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        } finally {
1332c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (cursor != null) cursor.close();
134e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        }
1359c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate        if (retainIcon) {
1369c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate            WebIconDatabase.getInstance().retainIconForPageUrl(url);
1379c0dd8caacff99ba76bbb9dc2cab156cded505a8Christopher Tate        }
138e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        if (context != null) {
139e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins            Toast.makeText(context, R.string.added_to_bookmarks,
140e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins                    Toast.LENGTH_LONG).show();
141e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        }
142e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    }
143e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins
144e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    /**
145e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  Remove a bookmark from the database.  If the url is a visited site, it
146e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  will remain in the database, but only as a history item, and not as a
147e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  bookmarked site.
148e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param context Context of the calling Activity.  This is used to make
149e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *          Toast confirming that the bookmark has been removed.  If the
150e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *          caller provides null, the Toast will not be shown.
151e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param cr The ContentResolver being used to remove the bookmark.
152e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     *  @param url URL of the website to be removed.
153e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins     */
154e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    /* package */ static void removeFromBookmarks(Context context,
155c95261955cf08f30b484b6a229c4bcff42c645ceAndrei Popescu            ContentResolver cr, String url, String title) {
1562c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        Cursor cursor = null;
1572c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        try {
1582c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            cursor = cr.query(
1592c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    Browser.BOOKMARKS_URI,
1602c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    Browser.HISTORY_PROJECTION,
1612c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    "url = ? AND title = ?",
1622c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    new String[] { url, title },
1632c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    null);
1642c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            boolean first = cursor.moveToFirst();
1652c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            // Should be in the database no matter what
1662c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (!first) {
1672c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                throw new AssertionError("URL is not in the database! " + url
1682c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        + " " + title);
169e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins            }
1702c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            // Remove from bookmarks
1712c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            WebIconDatabase.getInstance().releaseIconForPageUrl(url);
1722c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
1732c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
1742c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            int numVisits = cursor.getInt(
1752c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    Browser.HISTORY_PROJECTION_VISITS_INDEX);
1762c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (0 == numVisits) {
1772c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                cr.delete(uri, null, null);
1782c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            } else {
1792c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                // It is no longer a bookmark, but it is still a visited
1802c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                // site.
1812c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                ContentValues values = new ContentValues();
1822c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                values.put(Browser.BookmarkColumns.BOOKMARK, 0);
1832c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                try {
1842c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    cr.update(uri, values, null, null);
1852c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                } catch (IllegalStateException e) {
1862c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                    Log.e("removeFromBookmarks", "no database!");
1872c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                }
1882c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            }
1892c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (context != null) {
1902c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                Toast.makeText(context, R.string.removed_from_bookmarks,
1912c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins                        Toast.LENGTH_LONG).show();
1922c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            }
1932c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        } catch (IllegalStateException e) {
1942c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            Log.e(LOGTAG, "removeFromBookmarks", e);
1952c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins        } finally {
1962c0f611fab8c0a24365c0dd5cbf0a90f70f314c8Leon Scroggins            if (cursor != null) cursor.close();
197e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins        }
198e372c02c732cf0881c21eb8423454a555e8fc75cLeon Scroggins    }
199aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch
200aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch    private static byte[] bitmapToBytes(Bitmap bm) {
201aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch        if (bm == null) {
202aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch            return null;
203aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch        }
204aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch
205aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch        final ByteArrayOutputStream os = new ByteArrayOutputStream();
206aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch        bm.compress(Bitmap.CompressFormat.PNG, 100, os);
207aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch        return os.toByteArray();
208aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch    }
209de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch
210de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    /* package */ static boolean urlHasAcceptableScheme(String url) {
211de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch        if (url == null) {
212de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            return false;
213de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch        }
214de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch
215de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch        for (int i = 0; i < acceptableBookmarkSchemes.length; i++) {
216de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            if (url.startsWith(acceptableBookmarkSchemes[i])) {
217de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch                return true;
218de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch            }
219de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch        }
220de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch        return false;
221de353621650d17a412b6ffe2cbf0366db5f11c40Ben Murdoch    }
222aac7aa6fcfcb519755987ec126be066323f589c8Ben Murdoch}
223