13918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott/*
23918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Copyright (C) 2009 The Android Open Source Project
33918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott *
43918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Licensed under the Apache License, Version 2.0 (the "License");
53918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * you may not use this file except in compliance with the License.
63918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * You may obtain a copy of the License at
73918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott *
83918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott *      http://www.apache.org/licenses/LICENSE-2.0
93918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott *
103918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Unless required by applicable law or agreed to in writing, software
113918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * distributed under the License is distributed on an "AS IS" BASIS,
123918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * See the License for the specific language governing permissions and
143918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * limitations under the License.
153918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott */
163918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
173918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottpackage com.android.browser;
183918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
1930ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.io.IOException;
2030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.net.HttpURLConnection;
2130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.net.URL;
228ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton
233918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.content.ContentResolver;
243918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.content.ContentValues;
25980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baardimport android.content.Context;
263918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.database.Cursor;
273918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.graphics.Bitmap;
283918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.graphics.BitmapFactory;
293918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.os.AsyncTask;
30e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdochimport android.os.Bundle;
31e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdochimport android.os.Message;
32bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scrogginsimport android.provider.BrowserContract;
331a805652e389d9404ee0fda7c993a6202332e92bJeff Hamiltonimport android.provider.BrowserContract.Images;
343918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.webkit.WebView;
353918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
363918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport java.io.ByteArrayOutputStream;
373918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport java.io.InputStream;
383918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
39a74f6963e548b7552d25fc4f851360dc74248958Patrick Scottclass DownloadTouchIcon extends AsyncTask<String, Void, Void> {
40bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck
413918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    private final ContentResolver mContentResolver;
42c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins    private Cursor mCursor;
433918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    private final String mOriginalUrl;
443918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    private final String mUrl;
45e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    private final String mUserAgent; // Sites may serve a different icon to different UAs
46e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    private Message mMessage;
47e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
4822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba    /* package */ Tab mTab;
493918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
50e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    /**
51e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * Use this ctor to store the touch icon in the bookmarks database for
52e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * the originalUrl so we take account of redirects. Used when the user
53e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * bookmarks a page from outside the bookmarks activity.
54e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     */
5530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath    public DownloadTouchIcon(Tab tab, ContentResolver cr, WebView view) {
5622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mTab = tab;
573918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mContentResolver = cr;
583918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        // Store these in case they change.
593918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mOriginalUrl = view.getOriginalUrl();
603918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mUrl = view.getUrl();
613918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mUserAgent = view.getSettings().getUserAgentString();
623918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    }
633918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
64e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    /**
65e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * Use this ctor to download the touch icon and update the bookmarks database
66e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * entry for the given url. Used when the user creates a bookmark from
67e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * within the bookmarks activity and there haven't been any redirects.
68e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * TODO: Would be nice to set the user agent here so that there is no
69e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * potential for the three different ctors here to return different icons.
70e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     */
7130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath    public DownloadTouchIcon(ContentResolver cr, String url) {
7222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        mTab = null;
733918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mContentResolver = cr;
743918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mOriginalUrl = null;
753918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mUrl = url;
763918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        mUserAgent = null;
773918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    }
783918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
79e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    /**
80e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     * Use this ctor to not store the touch icon in a database, rather add it to
81bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins     * the passed Message's data bundle with the key
82bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins     * {@link BrowserContract.Bookmarks#TOUCH_ICON} and then send the message.
83e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch     */
8430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath    public DownloadTouchIcon(Message msg, String userAgent) {
85e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        mMessage = msg;
86e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        mContentResolver = null;
87e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        mOriginalUrl = null;
88e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        mUrl = null;
89e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        mUserAgent = userAgent;
90e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch    }
91e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
923918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    @Override
93a74f6963e548b7552d25fc4f851360dc74248958Patrick Scott    public Void doInBackground(String... values) {
94e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        if (mContentResolver != null) {
951a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton            mCursor = Bookmarks.queryCombinedForUrl(mContentResolver,
968ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton                    mOriginalUrl, mUrl);
97e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        }
98e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
991a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton        boolean inDatabase = mCursor != null && mCursor.getCount() > 0;
1003918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
1011a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton        if (inDatabase || mMessage != null) {
10230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath            HttpURLConnection connection = null;
103bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck            try {
10430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                URL url = new URL(values[0]);
10530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                connection = (HttpURLConnection) url.openConnection();
10630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                if (mUserAgent != null) {
10730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    connection.addRequestProperty("User-Agent", mUserAgent);
108bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck                }
109d159ec534823b87f9896843e95912b0df8c27e16Andreas Sandblad
11030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                if (connection.getResponseCode() == 200) {
11130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    InputStream content = connection.getInputStream();
11230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    Bitmap icon = null;
11330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    try {
11430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        icon = BitmapFactory.decodeStream(
11530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                                content, null, null);
11630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    } finally {
11730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        try {
11830ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                            content.close();
11930ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        } catch (IOException ignored) {
120c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins                        }
1213918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott                    }
12230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath
12330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    if (inDatabase) {
12430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        storeIcon(icon);
12530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    } else if (mMessage != null) {
12630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        Bundle b = mMessage.getData();
12730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                        b.putParcelable(BrowserContract.Bookmarks.TOUCH_ICON, icon);
12830ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    }
1293918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott                }
13030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath            } catch (IOException ignored) {
131c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins            } finally {
13230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                if (connection != null) {
13330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath                    connection.disconnect();
134bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck                }
1353918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott            }
1363918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        }
137e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
1388e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott        if (mCursor != null) {
1398e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott            mCursor.close();
1408e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott        }
141e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
142e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        if (mMessage != null) {
143e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch            mMessage.sendToTarget();
144e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch        }
145e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch
1463918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        return null;
1473918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    }
1483918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott
1493918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    @Override
15059ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott    protected void onCancelled() {
15159ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott        if (mCursor != null) {
15259ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott            mCursor.close();
15359ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott        }
15459ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott    }
15559ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott
156a74f6963e548b7552d25fc4f851360dc74248958Patrick Scott    private void storeIcon(Bitmap icon) {
15759ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott        // Do this first in case the download failed.
15822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba        if (mTab != null) {
15959ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott            // Remove the touch icon loader from the BrowserActivity.
16022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba            mTab.mTouchIconLoader = null;
16159ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott        }
16259ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott
16359ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott        if (icon == null || mCursor == null || isCancelled()) {
1643918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott            return;
1653918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        }
16659ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott
1673918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        if (mCursor.moveToFirst()) {
1681a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton            final ByteArrayOutputStream os = new ByteArrayOutputStream();
1691a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton            icon.compress(Bitmap.CompressFormat.PNG, 100, os);
1701a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton
1711a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton            ContentValues values = new ContentValues();
1721a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton            values.put(Images.TOUCH_ICON, os.toByteArray());
1731a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton
1743918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott            do {
1759e7686e110d3fd1e3ad7742ec27a1c7d54cf9408John Reck                values.put(Images.URL, mCursor.getString(0));
1761a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton                mContentResolver.update(Images.CONTENT_URI, values, null, null);
1773918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott            } while (mCursor.moveToNext());
1783918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott        }
1793918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott    }
1803918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott}
181